Annotation of embedaddon/libxml2/xmlschemas.c, revision 1.1.1.3
1.1 misho 1: /*
2: * schemas.c : implementation of the XML Schema handling and
3: * schema validity checking
4: *
5: * See Copyright for the status of this software.
6: *
7: * Daniel Veillard <veillard@redhat.com>
8: */
9:
10: /*
11: * TODO:
12: * - when types are redefined in includes, check that all
13: * types in the redef list are equal
14: * -> need a type equality operation.
15: * - if we don't intend to use the schema for schemas, we
16: * need to validate all schema attributes (ref, type, name)
17: * against their types.
18: * - Eliminate item creation for: ??
19: *
20: * URGENT TODO:
21: * - For xsi-driven schema acquisition, augment the IDCs after every
22: * acquisition episode (xmlSchemaAugmentIDC).
23: *
24: * NOTES:
25: * - Elimated item creation for: <restriction>, <extension>,
26: * <simpleContent>, <complexContent>, <list>, <union>
27: *
28: * PROBLEMS:
29: * - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30: * IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31: * XPath will have trouble to resolve to this namespace, since not known.
32: *
33: *
34: * CONSTRAINTS:
35: *
36: * Schema Component Constraint:
37: * All Group Limited (cos-all-limited)
38: * Status: complete
39: * (1.2)
40: * In xmlSchemaGroupDefReferenceTermFixup() and
41: * (2)
42: * In xmlSchemaParseModelGroup()
43: * TODO: Actually this should go to component-level checks,
44: * but is done here due to performance. Move it to an other layer
45: * is schema construction via an API is implemented.
46: */
47: #define IN_LIBXML
48: #include "libxml.h"
49:
50: #ifdef LIBXML_SCHEMAS_ENABLED
51:
52: #include <string.h>
53: #include <libxml/xmlmemory.h>
54: #include <libxml/parser.h>
55: #include <libxml/parserInternals.h>
56: #include <libxml/hash.h>
57: #include <libxml/uri.h>
58: #include <libxml/xmlschemas.h>
59: #include <libxml/schemasInternals.h>
60: #include <libxml/xmlschemastypes.h>
61: #include <libxml/xmlautomata.h>
62: #include <libxml/xmlregexp.h>
63: #include <libxml/dict.h>
64: #include <libxml/encoding.h>
65: #include <libxml/xmlIO.h>
66: #ifdef LIBXML_PATTERN_ENABLED
67: #include <libxml/pattern.h>
68: #endif
69: #ifdef LIBXML_READER_ENABLED
70: #include <libxml/xmlreader.h>
71: #endif
72:
73: /* #define DEBUG 1 */
74:
75: /* #define DEBUG_CONTENT 1 */
76:
77: /* #define DEBUG_TYPE 1 */
78:
79: /* #define DEBUG_CONTENT_REGEXP 1 */
80:
81: /* #define DEBUG_AUTOMATA 1 */
82:
83: /* #define DEBUG_IDC */
84:
85: /* #define DEBUG_IDC_NODE_TABLE */
86:
87: /* #define WXS_ELEM_DECL_CONS_ENABLED */
88:
89: #ifdef DEBUG_IDC
90: #ifndef DEBUG_IDC_NODE_TABLE
91: #define DEBUG_IDC_NODE_TABLE
92: #endif
93: #endif
94:
95: /* #define ENABLE_PARTICLE_RESTRICTION 1 */
96:
97: #define ENABLE_REDEFINE
98:
99: /* #define ENABLE_NAMED_LOCALS */
100:
101: /* #define ENABLE_IDC_NODE_TABLES_TEST */
102:
103: #define DUMP_CONTENT_MODEL
104:
105: #ifdef LIBXML_READER_ENABLED
106: /* #define XML_SCHEMA_READER_ENABLED */
107: #endif
108:
109: #define UNBOUNDED (1 << 30)
1.1.1.3 ! misho 110: #define TODO \
1.1 misho 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? */
1.1.1.3 ! misho 978: char *filename;
1.1 misho 979:
980: int err;
981: int nberrors;
982:
983: xmlNodePtr node;
984: xmlNodePtr cur;
985: /* xmlSchemaTypePtr type; */
986:
987: xmlRegExecCtxtPtr regexp;
988: xmlSchemaValPtr value;
989:
990: int valueWS;
991: int options;
992: xmlNodePtr validationRoot;
993: xmlSchemaParserCtxtPtr pctxt;
994: int xsiAssemble;
995:
996: int depth;
997: xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
998: int sizeElemInfos;
999: xmlSchemaNodeInfoPtr inode; /* the current element information */
1000:
1001: xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1002:
1003: xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1004: xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1005: xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1006:
1007: xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1008: int nbIdcNodes;
1009: int sizeIdcNodes;
1010:
1011: xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1012: int nbIdcKeys;
1013: int sizeIdcKeys;
1014:
1015: int flags;
1016:
1017: xmlDictPtr dict;
1018:
1019: #ifdef LIBXML_READER_ENABLED
1020: xmlTextReaderPtr reader;
1021: #endif
1022:
1023: xmlSchemaAttrInfoPtr *attrInfos;
1024: int nbAttrInfos;
1025: int sizeAttrInfos;
1026:
1027: int skipDepth;
1028: xmlSchemaItemListPtr nodeQNames;
1029: int hasKeyrefs;
1030: int createIDCNodeTables;
1031: int psviExposeIDCNodeTables;
1.1.1.3 ! misho 1032:
! 1033: /* Locator for error reporting in streaming mode */
! 1034: xmlSchemaValidityLocatorFunc locFunc;
! 1035: void *locCtxt;
1.1 misho 1036: };
1037:
1038: /**
1039: * xmlSchemaSubstGroup:
1040: *
1041: *
1042: */
1043: typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1044: typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1045: struct _xmlSchemaSubstGroup {
1046: xmlSchemaElementPtr head;
1047: xmlSchemaItemListPtr members;
1048: };
1049:
1050: /************************************************************************
1.1.1.3 ! misho 1051: * *
! 1052: * Some predeclarations *
! 1053: * *
1.1 misho 1054: ************************************************************************/
1055:
1056: static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1057: xmlSchemaPtr schema,
1058: xmlNodePtr node);
1059: static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1060: xmlSchemaPtr schema,
1061: xmlNodePtr node);
1062: static int
1063: xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1064: xmlSchemaAbstractCtxtPtr ctxt);
1065: static const xmlChar *
1066: xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1067: static int
1068: xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1069: xmlNodePtr node);
1070: static int
1071: xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1072: xmlSchemaParserCtxtPtr ctxt);
1073: static void
1074: xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1075: static xmlSchemaWhitespaceValueType
1076: xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1077: static xmlSchemaTreeItemPtr
1078: xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1079: xmlNodePtr node, xmlSchemaTypeType type,
1080: int withParticle);
1081: static const xmlChar *
1082: xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1083: static xmlSchemaTypeLinkPtr
1084: xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1085: static void
1086: xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1087: const char *funcName,
1088: const char *message);
1089: static int
1090: xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1091: xmlSchemaTypePtr type,
1092: xmlSchemaTypePtr baseType,
1093: int subset);
1094: static void
1095: xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1096: xmlSchemaParserCtxtPtr ctxt);
1097: static void
1098: xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1099: static xmlSchemaQNameRefPtr
1100: xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1101: xmlSchemaPtr schema,
1102: xmlNodePtr node);
1103:
1104: /************************************************************************
1105: * *
1.1.1.3 ! misho 1106: * Helper functions *
1.1 misho 1107: * *
1108: ************************************************************************/
1109:
1110: /**
1111: * xmlSchemaItemTypeToStr:
1112: * @type: the type of the schema item
1113: *
1114: * Returns the component name of a schema item.
1115: */
1116: static const xmlChar *
1117: xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1118: {
1119: switch (type) {
1120: case XML_SCHEMA_TYPE_BASIC:
1121: return(BAD_CAST "simple type definition");
1122: case XML_SCHEMA_TYPE_SIMPLE:
1123: return(BAD_CAST "simple type definition");
1124: case XML_SCHEMA_TYPE_COMPLEX:
1125: return(BAD_CAST "complex type definition");
1126: case XML_SCHEMA_TYPE_ELEMENT:
1127: return(BAD_CAST "element declaration");
1128: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1129: return(BAD_CAST "attribute use");
1130: case XML_SCHEMA_TYPE_ATTRIBUTE:
1131: return(BAD_CAST "attribute declaration");
1132: case XML_SCHEMA_TYPE_GROUP:
1133: return(BAD_CAST "model group definition");
1134: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1135: return(BAD_CAST "attribute group definition");
1136: case XML_SCHEMA_TYPE_NOTATION:
1137: return(BAD_CAST "notation declaration");
1138: case XML_SCHEMA_TYPE_SEQUENCE:
1139: return(BAD_CAST "model group (sequence)");
1140: case XML_SCHEMA_TYPE_CHOICE:
1141: return(BAD_CAST "model group (choice)");
1142: case XML_SCHEMA_TYPE_ALL:
1143: return(BAD_CAST "model group (all)");
1144: case XML_SCHEMA_TYPE_PARTICLE:
1145: return(BAD_CAST "particle");
1146: case XML_SCHEMA_TYPE_IDC_UNIQUE:
1147: return(BAD_CAST "unique identity-constraint");
1148: /* return(BAD_CAST "IDC (unique)"); */
1149: case XML_SCHEMA_TYPE_IDC_KEY:
1150: return(BAD_CAST "key identity-constraint");
1151: /* return(BAD_CAST "IDC (key)"); */
1152: case XML_SCHEMA_TYPE_IDC_KEYREF:
1153: return(BAD_CAST "keyref identity-constraint");
1154: /* return(BAD_CAST "IDC (keyref)"); */
1155: case XML_SCHEMA_TYPE_ANY:
1156: return(BAD_CAST "wildcard (any)");
1157: case XML_SCHEMA_EXTRA_QNAMEREF:
1158: return(BAD_CAST "[helper component] QName reference");
1159: case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1160: return(BAD_CAST "[helper component] attribute use prohibition");
1161: default:
1162: return(BAD_CAST "Not a schema component");
1163: }
1164: }
1165:
1166: /**
1167: * xmlSchemaGetComponentTypeStr:
1168: * @type: the type of the schema item
1169: *
1170: * Returns the component name of a schema item.
1171: */
1172: static const xmlChar *
1173: xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1174: {
1175: switch (item->type) {
1176: case XML_SCHEMA_TYPE_BASIC:
1177: if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1178: return(BAD_CAST "complex type definition");
1179: else
1180: return(BAD_CAST "simple type definition");
1181: default:
1182: return(xmlSchemaItemTypeToStr(item->type));
1183: }
1184: }
1185:
1186: /**
1187: * xmlSchemaGetComponentNode:
1188: * @item: a schema component
1189: *
1190: * Returns node associated with the schema component.
1191: * NOTE that such a node need not be available; plus, a component's
1192: * node need not to reflect the component directly, since there is no
1193: * one-to-one relationship between the XML Schema representation and
1194: * the component representation.
1195: */
1196: static xmlNodePtr
1197: xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1198: {
1199: switch (item->type) {
1200: case XML_SCHEMA_TYPE_ELEMENT:
1201: return (((xmlSchemaElementPtr) item)->node);
1202: case XML_SCHEMA_TYPE_ATTRIBUTE:
1203: return (((xmlSchemaAttributePtr) item)->node);
1204: case XML_SCHEMA_TYPE_COMPLEX:
1205: case XML_SCHEMA_TYPE_SIMPLE:
1206: return (((xmlSchemaTypePtr) item)->node);
1207: case XML_SCHEMA_TYPE_ANY:
1208: case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1209: return (((xmlSchemaWildcardPtr) item)->node);
1210: case XML_SCHEMA_TYPE_PARTICLE:
1211: return (((xmlSchemaParticlePtr) item)->node);
1212: case XML_SCHEMA_TYPE_SEQUENCE:
1213: case XML_SCHEMA_TYPE_CHOICE:
1214: case XML_SCHEMA_TYPE_ALL:
1215: return (((xmlSchemaModelGroupPtr) item)->node);
1216: case XML_SCHEMA_TYPE_GROUP:
1217: return (((xmlSchemaModelGroupDefPtr) item)->node);
1218: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1219: return (((xmlSchemaAttributeGroupPtr) item)->node);
1220: case XML_SCHEMA_TYPE_IDC_UNIQUE:
1221: case XML_SCHEMA_TYPE_IDC_KEY:
1222: case XML_SCHEMA_TYPE_IDC_KEYREF:
1223: return (((xmlSchemaIDCPtr) item)->node);
1224: case XML_SCHEMA_EXTRA_QNAMEREF:
1225: return(((xmlSchemaQNameRefPtr) item)->node);
1226: /* TODO: What to do with NOTATIONs?
1227: case XML_SCHEMA_TYPE_NOTATION:
1228: return (((xmlSchemaNotationPtr) item)->node);
1229: */
1230: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1231: return (((xmlSchemaAttributeUsePtr) item)->node);
1232: default:
1233: return (NULL);
1234: }
1235: }
1236:
1237: #if 0
1238: /**
1239: * xmlSchemaGetNextComponent:
1240: * @item: a schema component
1241: *
1242: * Returns the next sibling of the schema component.
1243: */
1244: static xmlSchemaBasicItemPtr
1245: xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1246: {
1247: switch (item->type) {
1248: case XML_SCHEMA_TYPE_ELEMENT:
1249: return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1250: case XML_SCHEMA_TYPE_ATTRIBUTE:
1251: return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1252: case XML_SCHEMA_TYPE_COMPLEX:
1253: case XML_SCHEMA_TYPE_SIMPLE:
1254: return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1255: case XML_SCHEMA_TYPE_ANY:
1256: case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1257: return (NULL);
1258: case XML_SCHEMA_TYPE_PARTICLE:
1259: return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1260: case XML_SCHEMA_TYPE_SEQUENCE:
1261: case XML_SCHEMA_TYPE_CHOICE:
1262: case XML_SCHEMA_TYPE_ALL:
1263: return (NULL);
1264: case XML_SCHEMA_TYPE_GROUP:
1265: return (NULL);
1266: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1267: return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1268: case XML_SCHEMA_TYPE_IDC_UNIQUE:
1269: case XML_SCHEMA_TYPE_IDC_KEY:
1270: case XML_SCHEMA_TYPE_IDC_KEYREF:
1271: return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1272: default:
1273: return (NULL);
1274: }
1275: }
1276: #endif
1277:
1278:
1279: /**
1280: * xmlSchemaFormatQName:
1281: * @buf: the string buffer
1282: * @namespaceName: the namespace name
1283: * @localName: the local name
1284: *
1285: * Returns the given QName in the format "{namespaceName}localName" or
1286: * just "localName" if @namespaceName is NULL.
1287: *
1288: * Returns the localName if @namespaceName is NULL, a formatted
1289: * string otherwise.
1290: */
1291: static const xmlChar*
1292: xmlSchemaFormatQName(xmlChar **buf,
1293: const xmlChar *namespaceName,
1294: const xmlChar *localName)
1295: {
1296: FREE_AND_NULL(*buf)
1297: if (namespaceName != NULL) {
1298: *buf = xmlStrdup(BAD_CAST "{");
1299: *buf = xmlStrcat(*buf, namespaceName);
1300: *buf = xmlStrcat(*buf, BAD_CAST "}");
1301: }
1302: if (localName != NULL) {
1303: if (namespaceName == NULL)
1304: return(localName);
1305: *buf = xmlStrcat(*buf, localName);
1306: } else {
1307: *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1308: }
1309: return ((const xmlChar *) *buf);
1310: }
1311:
1312: static const xmlChar*
1313: xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1314: {
1315: if (ns != NULL)
1316: return (xmlSchemaFormatQName(buf, ns->href, localName));
1317: else
1318: return (xmlSchemaFormatQName(buf, NULL, localName));
1319: }
1320:
1321: static const xmlChar *
1322: xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1323: {
1324: switch (item->type) {
1325: case XML_SCHEMA_TYPE_ELEMENT:
1326: return (((xmlSchemaElementPtr) item)->name);
1327: case XML_SCHEMA_TYPE_ATTRIBUTE:
1328: return (((xmlSchemaAttributePtr) item)->name);
1329: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1330: return (((xmlSchemaAttributeGroupPtr) item)->name);
1331: case XML_SCHEMA_TYPE_BASIC:
1332: case XML_SCHEMA_TYPE_SIMPLE:
1333: case XML_SCHEMA_TYPE_COMPLEX:
1334: return (((xmlSchemaTypePtr) item)->name);
1335: case XML_SCHEMA_TYPE_GROUP:
1336: return (((xmlSchemaModelGroupDefPtr) item)->name);
1337: case XML_SCHEMA_TYPE_IDC_KEY:
1338: case XML_SCHEMA_TYPE_IDC_UNIQUE:
1339: case XML_SCHEMA_TYPE_IDC_KEYREF:
1340: return (((xmlSchemaIDCPtr) item)->name);
1341: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1342: if (WXS_ATTRUSE_DECL(item) != NULL) {
1343: return(xmlSchemaGetComponentName(
1344: WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1345: } else
1346: return(NULL);
1347: case XML_SCHEMA_EXTRA_QNAMEREF:
1348: return (((xmlSchemaQNameRefPtr) item)->name);
1349: case XML_SCHEMA_TYPE_NOTATION:
1350: return (((xmlSchemaNotationPtr) item)->name);
1351: default:
1352: /*
1353: * Other components cannot have names.
1354: */
1355: break;
1356: }
1357: return (NULL);
1358: }
1359:
1360: #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1361: #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1362: /*
1363: static const xmlChar *
1364: xmlSchemaGetQNameRefName(void *ref)
1365: {
1366: return(((xmlSchemaQNameRefPtr) ref)->name);
1367: }
1368:
1369: static const xmlChar *
1370: xmlSchemaGetQNameRefTargetNs(void *ref)
1371: {
1372: return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1373: }
1374: */
1375:
1376: static const xmlChar *
1377: xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1378: {
1379: switch (item->type) {
1380: case XML_SCHEMA_TYPE_ELEMENT:
1381: return (((xmlSchemaElementPtr) item)->targetNamespace);
1382: case XML_SCHEMA_TYPE_ATTRIBUTE:
1383: return (((xmlSchemaAttributePtr) item)->targetNamespace);
1384: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1385: return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1386: case XML_SCHEMA_TYPE_BASIC:
1387: return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1388: case XML_SCHEMA_TYPE_SIMPLE:
1389: case XML_SCHEMA_TYPE_COMPLEX:
1390: return (((xmlSchemaTypePtr) item)->targetNamespace);
1391: case XML_SCHEMA_TYPE_GROUP:
1392: return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1393: case XML_SCHEMA_TYPE_IDC_KEY:
1394: case XML_SCHEMA_TYPE_IDC_UNIQUE:
1395: case XML_SCHEMA_TYPE_IDC_KEYREF:
1396: return (((xmlSchemaIDCPtr) item)->targetNamespace);
1397: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1398: if (WXS_ATTRUSE_DECL(item) != NULL) {
1399: return(xmlSchemaGetComponentTargetNs(
1400: WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1401: }
1402: /* TODO: Will returning NULL break something? */
1403: break;
1404: case XML_SCHEMA_EXTRA_QNAMEREF:
1405: return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1406: case XML_SCHEMA_TYPE_NOTATION:
1407: return (((xmlSchemaNotationPtr) item)->targetNamespace);
1408: default:
1409: /*
1410: * Other components cannot have names.
1411: */
1412: break;
1413: }
1414: return (NULL);
1415: }
1416:
1417: static const xmlChar*
1418: xmlSchemaGetComponentQName(xmlChar **buf,
1419: void *item)
1420: {
1421: return (xmlSchemaFormatQName(buf,
1422: xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1423: xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1424: }
1425:
1426: static const xmlChar*
1427: xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1428: {
1429: xmlChar *str = NULL;
1430:
1431: *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1432: *buf = xmlStrcat(*buf, BAD_CAST " '");
1433: *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1434: (xmlSchemaBasicItemPtr) item));
1435: *buf = xmlStrcat(*buf, BAD_CAST "'");
1436: FREE_AND_NULL(str);
1437: return(*buf);
1438: }
1439:
1440: static const xmlChar*
1441: xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1442: {
1443: return(xmlSchemaGetComponentDesignation(buf, idc));
1444: }
1445:
1446: /**
1447: * xmlSchemaWildcardPCToString:
1448: * @pc: the type of processContents
1449: *
1450: * Returns a string representation of the type of
1451: * processContents.
1452: */
1453: static const xmlChar *
1454: xmlSchemaWildcardPCToString(int pc)
1455: {
1456: switch (pc) {
1457: case XML_SCHEMAS_ANY_SKIP:
1458: return (BAD_CAST "skip");
1459: case XML_SCHEMAS_ANY_LAX:
1460: return (BAD_CAST "lax");
1461: case XML_SCHEMAS_ANY_STRICT:
1462: return (BAD_CAST "strict");
1463: default:
1464: return (BAD_CAST "invalid process contents");
1465: }
1466: }
1467:
1468: /**
1469: * xmlSchemaGetCanonValueWhtspExt:
1470: * @val: the precomputed value
1471: * @retValue: the returned value
1472: * @ws: the whitespace type of the value
1473: *
1474: * Get a the cononical representation of the value.
1475: * The caller has to free the returned retValue.
1476: *
1477: * Returns 0 if the value could be built and -1 in case of
1478: * API errors or if the value type is not supported yet.
1479: */
1480: static int
1481: xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1482: xmlSchemaWhitespaceValueType ws,
1483: xmlChar **retValue)
1484: {
1485: int list;
1486: xmlSchemaValType valType;
1487: const xmlChar *value, *value2 = NULL;
1488:
1489:
1490: if ((retValue == NULL) || (val == NULL))
1491: return (-1);
1492: list = xmlSchemaValueGetNext(val) ? 1 : 0;
1493: *retValue = NULL;
1494: do {
1495: value = NULL;
1496: valType = xmlSchemaGetValType(val);
1497: switch (valType) {
1498: case XML_SCHEMAS_STRING:
1499: case XML_SCHEMAS_NORMSTRING:
1500: case XML_SCHEMAS_ANYSIMPLETYPE:
1501: value = xmlSchemaValueGetAsString(val);
1502: if (value != NULL) {
1503: if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1504: value2 = xmlSchemaCollapseString(value);
1505: else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1506: value2 = xmlSchemaWhiteSpaceReplace(value);
1507: if (value2 != NULL)
1508: value = value2;
1509: }
1510: break;
1511: default:
1512: if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1513: if (value2 != NULL)
1514: xmlFree((xmlChar *) value2);
1515: goto internal_error;
1516: }
1517: value = value2;
1518: }
1519: if (*retValue == NULL)
1520: if (value == NULL) {
1521: if (! list)
1522: *retValue = xmlStrdup(BAD_CAST "");
1523: } else
1524: *retValue = xmlStrdup(value);
1525: else if (value != NULL) {
1526: /* List. */
1527: *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1528: *retValue = xmlStrcat((xmlChar *) *retValue, value);
1529: }
1530: FREE_AND_NULL(value2)
1531: val = xmlSchemaValueGetNext(val);
1532: } while (val != NULL);
1533:
1534: return (0);
1535: internal_error:
1536: if (*retValue != NULL)
1537: xmlFree((xmlChar *) (*retValue));
1538: if (value2 != NULL)
1539: xmlFree((xmlChar *) value2);
1540: return (-1);
1541: }
1542:
1543: /**
1544: * xmlSchemaFormatItemForReport:
1545: * @buf: the string buffer
1546: * @itemDes: the designation of the item
1547: * @itemName: the name of the item
1548: * @item: the item as an object
1549: * @itemNode: the node of the item
1550: * @local: the local name
1551: * @parsing: if the function is used during the parse
1552: *
1553: * Returns a representation of the given item used
1554: * for error reports.
1555: *
1556: * The following order is used to build the resulting
1557: * designation if the arguments are not NULL:
1558: * 1a. If itemDes not NULL -> itemDes
1559: * 1b. If (itemDes not NULL) and (itemName not NULL)
1560: * -> itemDes + itemName
1561: * 2. If the preceding was NULL and (item not NULL) -> item
1562: * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1563: *
1564: * If the itemNode is an attribute node, the name of the attribute
1565: * will be appended to the result.
1566: *
1567: * Returns the formatted string and sets @buf to the resulting value.
1568: */
1569: static xmlChar*
1570: xmlSchemaFormatItemForReport(xmlChar **buf,
1571: const xmlChar *itemDes,
1572: xmlSchemaBasicItemPtr item,
1573: xmlNodePtr itemNode)
1574: {
1575: xmlChar *str = NULL;
1576: int named = 1;
1577:
1578: if (*buf != NULL) {
1579: xmlFree(*buf);
1580: *buf = NULL;
1581: }
1582:
1583: if (itemDes != NULL) {
1584: *buf = xmlStrdup(itemDes);
1585: } else if (item != NULL) {
1586: switch (item->type) {
1587: case XML_SCHEMA_TYPE_BASIC: {
1588: xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1589:
1590: if (WXS_IS_ATOMIC(type))
1591: *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1592: else if (WXS_IS_LIST(type))
1593: *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1594: else if (WXS_IS_UNION(type))
1595: *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1596: else
1597: *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1598: *buf = xmlStrcat(*buf, type->name);
1599: *buf = xmlStrcat(*buf, BAD_CAST "'");
1600: }
1601: break;
1602: case XML_SCHEMA_TYPE_SIMPLE: {
1603: xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1604:
1605: if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1606: *buf = xmlStrdup(BAD_CAST"");
1607: } else {
1608: *buf = xmlStrdup(BAD_CAST "local ");
1609: }
1610: if (WXS_IS_ATOMIC(type))
1611: *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1612: else if (WXS_IS_LIST(type))
1613: *buf = xmlStrcat(*buf, BAD_CAST "list type");
1614: else if (WXS_IS_UNION(type))
1615: *buf = xmlStrcat(*buf, BAD_CAST "union type");
1616: else
1617: *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1618: if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1619: *buf = xmlStrcat(*buf, BAD_CAST " '");
1620: *buf = xmlStrcat(*buf, type->name);
1621: *buf = xmlStrcat(*buf, BAD_CAST "'");
1622: }
1623: }
1624: break;
1625: case XML_SCHEMA_TYPE_COMPLEX: {
1626: xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1627:
1628: if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1629: *buf = xmlStrdup(BAD_CAST "");
1630: else
1631: *buf = xmlStrdup(BAD_CAST "local ");
1632: *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1633: if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1634: *buf = xmlStrcat(*buf, BAD_CAST " '");
1635: *buf = xmlStrcat(*buf, type->name);
1636: *buf = xmlStrcat(*buf, BAD_CAST "'");
1637: }
1638: }
1639: break;
1640: case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1641: xmlSchemaAttributeUsePtr ause;
1642:
1643: ause = WXS_ATTR_USE_CAST item;
1644: *buf = xmlStrdup(BAD_CAST "attribute use ");
1645: if (WXS_ATTRUSE_DECL(ause) != NULL) {
1646: *buf = xmlStrcat(*buf, BAD_CAST "'");
1647: *buf = xmlStrcat(*buf,
1648: xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1649: FREE_AND_NULL(str)
1650: *buf = xmlStrcat(*buf, BAD_CAST "'");
1651: } else {
1652: *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1653: }
1654: }
1655: break;
1656: case XML_SCHEMA_TYPE_ATTRIBUTE: {
1657: xmlSchemaAttributePtr attr;
1658:
1659: attr = (xmlSchemaAttributePtr) item;
1660: *buf = xmlStrdup(BAD_CAST "attribute decl.");
1661: *buf = xmlStrcat(*buf, BAD_CAST " '");
1662: *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1663: attr->targetNamespace, attr->name));
1664: FREE_AND_NULL(str)
1665: *buf = xmlStrcat(*buf, BAD_CAST "'");
1666: }
1667: break;
1668: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1669: xmlSchemaGetComponentDesignation(buf, item);
1670: break;
1671: case XML_SCHEMA_TYPE_ELEMENT: {
1672: xmlSchemaElementPtr elem;
1673:
1674: elem = (xmlSchemaElementPtr) item;
1675: *buf = xmlStrdup(BAD_CAST "element decl.");
1676: *buf = xmlStrcat(*buf, BAD_CAST " '");
1677: *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1678: elem->targetNamespace, elem->name));
1679: *buf = xmlStrcat(*buf, BAD_CAST "'");
1680: }
1681: break;
1682: case XML_SCHEMA_TYPE_IDC_UNIQUE:
1683: case XML_SCHEMA_TYPE_IDC_KEY:
1684: case XML_SCHEMA_TYPE_IDC_KEYREF:
1685: if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1686: *buf = xmlStrdup(BAD_CAST "unique '");
1687: else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1688: *buf = xmlStrdup(BAD_CAST "key '");
1689: else
1690: *buf = xmlStrdup(BAD_CAST "keyRef '");
1691: *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1692: *buf = xmlStrcat(*buf, BAD_CAST "'");
1693: break;
1694: case XML_SCHEMA_TYPE_ANY:
1695: case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1696: *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1697: ((xmlSchemaWildcardPtr) item)->processContents));
1698: *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1699: break;
1700: case XML_SCHEMA_FACET_MININCLUSIVE:
1701: case XML_SCHEMA_FACET_MINEXCLUSIVE:
1702: case XML_SCHEMA_FACET_MAXINCLUSIVE:
1703: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1704: case XML_SCHEMA_FACET_TOTALDIGITS:
1705: case XML_SCHEMA_FACET_FRACTIONDIGITS:
1706: case XML_SCHEMA_FACET_PATTERN:
1707: case XML_SCHEMA_FACET_ENUMERATION:
1708: case XML_SCHEMA_FACET_WHITESPACE:
1709: case XML_SCHEMA_FACET_LENGTH:
1710: case XML_SCHEMA_FACET_MAXLENGTH:
1711: case XML_SCHEMA_FACET_MINLENGTH:
1712: *buf = xmlStrdup(BAD_CAST "facet '");
1713: *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1714: *buf = xmlStrcat(*buf, BAD_CAST "'");
1715: break;
1716: case XML_SCHEMA_TYPE_GROUP: {
1717: *buf = xmlStrdup(BAD_CAST "model group def.");
1718: *buf = xmlStrcat(*buf, BAD_CAST " '");
1719: *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1720: *buf = xmlStrcat(*buf, BAD_CAST "'");
1721: FREE_AND_NULL(str)
1722: }
1723: break;
1724: case XML_SCHEMA_TYPE_SEQUENCE:
1725: case XML_SCHEMA_TYPE_CHOICE:
1726: case XML_SCHEMA_TYPE_ALL:
1727: case XML_SCHEMA_TYPE_PARTICLE:
1728: *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1729: break;
1730: case XML_SCHEMA_TYPE_NOTATION: {
1731: *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1732: *buf = xmlStrcat(*buf, BAD_CAST " '");
1733: *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1734: *buf = xmlStrcat(*buf, BAD_CAST "'");
1735: FREE_AND_NULL(str);
1736: }
1737: default:
1738: named = 0;
1739: }
1740: } else
1741: named = 0;
1742:
1743: if ((named == 0) && (itemNode != NULL)) {
1744: xmlNodePtr elem;
1745:
1746: if (itemNode->type == XML_ATTRIBUTE_NODE)
1747: elem = itemNode->parent;
1748: else
1749: elem = itemNode;
1750: *buf = xmlStrdup(BAD_CAST "Element '");
1751: if (elem->ns != NULL) {
1752: *buf = xmlStrcat(*buf,
1753: xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1754: FREE_AND_NULL(str)
1755: } else
1756: *buf = xmlStrcat(*buf, elem->name);
1757: *buf = xmlStrcat(*buf, BAD_CAST "'");
1758:
1759: }
1760: if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1761: *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1762: if (itemNode->ns != NULL) {
1763: *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1764: itemNode->ns->href, itemNode->name));
1765: FREE_AND_NULL(str)
1766: } else
1767: *buf = xmlStrcat(*buf, itemNode->name);
1768: *buf = xmlStrcat(*buf, BAD_CAST "'");
1769: }
1770: FREE_AND_NULL(str)
1771:
1772: return (*buf);
1773: }
1774:
1775: /**
1776: * xmlSchemaFormatFacetEnumSet:
1777: * @buf: the string buffer
1778: * @type: the type holding the enumeration facets
1779: *
1780: * Builds a string consisting of all enumeration elements.
1781: *
1782: * Returns a string of all enumeration elements.
1783: */
1784: static const xmlChar *
1785: xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1786: xmlChar **buf, xmlSchemaTypePtr type)
1787: {
1788: xmlSchemaFacetPtr facet;
1789: xmlSchemaWhitespaceValueType ws;
1790: xmlChar *value = NULL;
1791: int res, found = 0;
1792:
1793: if (*buf != NULL)
1794: xmlFree(*buf);
1795: *buf = NULL;
1796:
1797: do {
1798: /*
1799: * Use the whitespace type of the base type.
1800: */
1801: ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1802: for (facet = type->facets; facet != NULL; facet = facet->next) {
1803: if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1804: continue;
1805: found = 1;
1806: res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1807: ws, &value);
1808: if (res == -1) {
1809: xmlSchemaInternalErr(actxt,
1810: "xmlSchemaFormatFacetEnumSet",
1811: "compute the canonical lexical representation");
1812: if (*buf != NULL)
1813: xmlFree(*buf);
1814: *buf = NULL;
1815: return (NULL);
1816: }
1817: if (*buf == NULL)
1818: *buf = xmlStrdup(BAD_CAST "'");
1819: else
1820: *buf = xmlStrcat(*buf, BAD_CAST ", '");
1821: *buf = xmlStrcat(*buf, BAD_CAST value);
1822: *buf = xmlStrcat(*buf, BAD_CAST "'");
1823: if (value != NULL) {
1824: xmlFree((xmlChar *)value);
1825: value = NULL;
1826: }
1827: }
1828: /*
1829: * The enumeration facet of a type restricts the enumeration
1830: * facet of the ancestor type; i.e., such restricted enumerations
1831: * do not belong to the set of the given type. Thus we break
1832: * on the first found enumeration.
1833: */
1834: if (found)
1835: break;
1836: type = type->baseType;
1837: } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1838:
1839: return ((const xmlChar *) *buf);
1840: }
1841:
1842: /************************************************************************
1843: * *
1.1.1.3 ! misho 1844: * Error functions *
1.1 misho 1845: * *
1846: ************************************************************************/
1847:
1848: #if 0
1849: static void
1850: xmlSchemaErrMemory(const char *msg)
1851: {
1852: __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1853: msg);
1854: }
1855: #endif
1856:
1857: static void
1858: xmlSchemaPSimpleErr(const char *msg)
1859: {
1860: __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1861: msg);
1862: }
1863:
1864: /**
1865: * xmlSchemaPErrMemory:
1866: * @node: a context node
1867: * @extra: extra informations
1868: *
1869: * Handle an out of memory condition
1870: */
1871: static void
1872: xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1873: const char *extra, xmlNodePtr node)
1874: {
1875: if (ctxt != NULL)
1876: ctxt->nberrors++;
1877: __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1878: extra);
1879: }
1880:
1881: /**
1882: * xmlSchemaPErr:
1883: * @ctxt: the parsing context
1884: * @node: the context node
1885: * @error: the error code
1886: * @msg: the error message
1887: * @str1: extra data
1888: * @str2: extra data
1889: *
1890: * Handle a parser error
1891: */
1892: static void
1893: xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1894: const char *msg, const xmlChar * str1, const xmlChar * str2)
1895: {
1896: xmlGenericErrorFunc channel = NULL;
1897: xmlStructuredErrorFunc schannel = NULL;
1898: void *data = NULL;
1899:
1900: if (ctxt != NULL) {
1901: ctxt->nberrors++;
1902: ctxt->err = error;
1903: channel = ctxt->error;
1904: data = ctxt->errCtxt;
1905: schannel = ctxt->serror;
1906: }
1907: __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1908: error, XML_ERR_ERROR, NULL, 0,
1909: (const char *) str1, (const char *) str2, NULL, 0, 0,
1910: msg, str1, str2);
1911: }
1912:
1913: /**
1914: * xmlSchemaPErr2:
1915: * @ctxt: the parsing context
1916: * @node: the context node
1917: * @node: the current child
1918: * @error: the error code
1919: * @msg: the error message
1920: * @str1: extra data
1921: * @str2: extra data
1922: *
1923: * Handle a parser error
1924: */
1925: static void
1926: xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1927: xmlNodePtr child, int error,
1928: const char *msg, const xmlChar * str1, const xmlChar * str2)
1929: {
1930: if (child != NULL)
1931: xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1932: else
1933: xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1934: }
1935:
1936:
1937: /**
1938: * xmlSchemaPErrExt:
1939: * @ctxt: the parsing context
1940: * @node: the context node
1941: * @error: the error code
1942: * @strData1: extra data
1943: * @strData2: extra data
1944: * @strData3: extra data
1945: * @msg: the message
1946: * @str1: extra parameter for the message display
1947: * @str2: extra parameter for the message display
1948: * @str3: extra parameter for the message display
1949: * @str4: extra parameter for the message display
1950: * @str5: extra parameter for the message display
1951: *
1952: * Handle a parser error
1953: */
1954: static void
1955: xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1956: const xmlChar * strData1, const xmlChar * strData2,
1957: const xmlChar * strData3, const char *msg, const xmlChar * str1,
1958: const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1959: const xmlChar * str5)
1960: {
1961:
1962: xmlGenericErrorFunc channel = NULL;
1963: xmlStructuredErrorFunc schannel = NULL;
1964: void *data = NULL;
1965:
1966: if (ctxt != NULL) {
1967: ctxt->nberrors++;
1968: ctxt->err = error;
1969: channel = ctxt->error;
1970: data = ctxt->errCtxt;
1971: schannel = ctxt->serror;
1972: }
1973: __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1974: error, XML_ERR_ERROR, NULL, 0,
1975: (const char *) strData1, (const char *) strData2,
1976: (const char *) strData3, 0, 0, msg, str1, str2,
1977: str3, str4, str5);
1978: }
1979:
1980: /************************************************************************
1981: * *
1.1.1.3 ! misho 1982: * Allround error functions *
1.1 misho 1983: * *
1984: ************************************************************************/
1985:
1986: /**
1987: * xmlSchemaVTypeErrMemory:
1988: * @node: a context node
1989: * @extra: extra informations
1990: *
1991: * Handle an out of memory condition
1992: */
1993: static void
1994: xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1995: const char *extra, xmlNodePtr node)
1996: {
1997: if (ctxt != NULL) {
1998: ctxt->nberrors++;
1999: ctxt->err = XML_SCHEMAV_INTERNAL;
2000: }
2001: __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2002: extra);
2003: }
2004:
2005: static void
2006: xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2007: const char *msg, const xmlChar *str)
2008: {
2009: __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2010: msg, (const char *) str);
2011: }
2012:
2013: #define WXS_ERROR_TYPE_ERROR 1
2014: #define WXS_ERROR_TYPE_WARNING 2
2015: /**
2016: * xmlSchemaErr3:
2017: * @ctxt: the validation context
2018: * @node: the context node
2019: * @error: the error code
2020: * @msg: the error message
2021: * @str1: extra data
2022: * @str2: extra data
2023: * @str3: extra data
2024: *
2025: * Handle a validation error
2026: */
2027: static void
2028: xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2029: xmlErrorLevel errorLevel,
2030: int error, xmlNodePtr node, int line, const char *msg,
2031: const xmlChar *str1, const xmlChar *str2,
2032: const xmlChar *str3, const xmlChar *str4)
2033: {
2034: xmlStructuredErrorFunc schannel = NULL;
2035: xmlGenericErrorFunc channel = NULL;
2036: void *data = NULL;
2037:
2038: if (ctxt != NULL) {
2039: if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2040: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2041: const char *file = NULL;
2042: if (errorLevel != XML_ERR_WARNING) {
2043: vctxt->nberrors++;
2044: vctxt->err = error;
2045: channel = vctxt->error;
2046: } else {
2047: channel = vctxt->warning;
2048: }
2049: schannel = vctxt->serror;
2050: data = vctxt->errCtxt;
2051:
2052: /*
2053: * Error node. If we specify a line number, then
2054: * do not channel any node to the error function.
2055: */
2056: if (line == 0) {
2057: if ((node == NULL) &&
2058: (vctxt->depth >= 0) &&
2059: (vctxt->inode != NULL)) {
2060: node = vctxt->inode->node;
2061: }
2062: /*
2063: * Get filename and line if no node-tree.
2064: */
2065: if ((node == NULL) &&
2066: (vctxt->parserCtxt != NULL) &&
2067: (vctxt->parserCtxt->input != NULL)) {
2068: file = vctxt->parserCtxt->input->filename;
2069: line = vctxt->parserCtxt->input->line;
2070: }
2071: } else {
2072: /*
2073: * Override the given node's (if any) position
2074: * and channel only the given line number.
2075: */
2076: node = NULL;
2077: /*
2078: * Get filename.
2079: */
2080: if (vctxt->doc != NULL)
2081: file = (const char *) vctxt->doc->URL;
2082: else if ((vctxt->parserCtxt != NULL) &&
2083: (vctxt->parserCtxt->input != NULL))
2084: file = vctxt->parserCtxt->input->filename;
2085: }
1.1.1.3 ! misho 2086: if (vctxt->locFunc != NULL) {
! 2087: if ((file == NULL) || (line == 0)) {
! 2088: unsigned long l;
! 2089: const char *f;
! 2090: vctxt->locFunc(vctxt->locCtxt, &f, &l);
! 2091: if (file == NULL)
! 2092: file = f;
! 2093: if (line == 0)
! 2094: line = (int) l;
! 2095: }
! 2096: }
! 2097: if ((file == NULL) && (vctxt->filename != NULL))
! 2098: file = vctxt->filename;
! 2099:
1.1 misho 2100: __xmlRaiseError(schannel, channel, data, ctxt,
2101: node, XML_FROM_SCHEMASV,
2102: error, errorLevel, file, line,
2103: (const char *) str1, (const char *) str2,
2104: (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2105:
2106: } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2107: xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2108: if (errorLevel != XML_ERR_WARNING) {
2109: pctxt->nberrors++;
2110: pctxt->err = error;
2111: channel = pctxt->error;
2112: } else {
2113: channel = pctxt->warning;
2114: }
2115: schannel = pctxt->serror;
2116: data = pctxt->errCtxt;
2117: __xmlRaiseError(schannel, channel, data, ctxt,
2118: node, XML_FROM_SCHEMASP, error,
2119: errorLevel, NULL, 0,
2120: (const char *) str1, (const char *) str2,
2121: (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2122: } else {
2123: TODO
2124: }
2125: }
2126: }
2127:
2128: /**
2129: * xmlSchemaErr3:
2130: * @ctxt: the validation context
2131: * @node: the context node
2132: * @error: the error code
2133: * @msg: the error message
2134: * @str1: extra data
2135: * @str2: extra data
2136: * @str3: extra data
2137: *
2138: * Handle a validation error
2139: */
2140: static void
2141: xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2142: int error, xmlNodePtr node, const char *msg,
2143: const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2144: {
2145: xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2146: msg, str1, str2, str3, NULL);
2147: }
2148:
2149: static void
2150: xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2151: int error, xmlNodePtr node, const char *msg,
2152: const xmlChar *str1, const xmlChar *str2,
2153: const xmlChar *str3, const xmlChar *str4)
2154: {
2155: xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2156: msg, str1, str2, str3, str4);
2157: }
2158:
2159: static void
2160: xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2161: int error, xmlNodePtr node, const char *msg,
2162: const xmlChar *str1, const xmlChar *str2)
2163: {
2164: xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2165: }
2166:
2167: static xmlChar *
2168: xmlSchemaFormatNodeForError(xmlChar ** msg,
2169: xmlSchemaAbstractCtxtPtr actxt,
2170: xmlNodePtr node)
2171: {
2172: xmlChar *str = NULL;
2173:
2174: *msg = NULL;
2175: if ((node != NULL) &&
2176: (node->type != XML_ELEMENT_NODE) &&
2177: (node->type != XML_ATTRIBUTE_NODE))
2178: {
2179: /*
2180: * Don't try to format other nodes than element and
2181: * attribute nodes.
2182: * Play save and return an empty string.
2183: */
2184: *msg = xmlStrdup(BAD_CAST "");
2185: return(*msg);
2186: }
2187: if (node != NULL) {
2188: /*
2189: * Work on tree nodes.
2190: */
2191: if (node->type == XML_ATTRIBUTE_NODE) {
2192: xmlNodePtr elem = node->parent;
2193:
2194: *msg = xmlStrdup(BAD_CAST "Element '");
2195: if (elem->ns != NULL)
2196: *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2197: elem->ns->href, elem->name));
2198: else
2199: *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2200: NULL, elem->name));
2201: FREE_AND_NULL(str);
2202: *msg = xmlStrcat(*msg, BAD_CAST "', ");
2203: *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2204: } else {
2205: *msg = xmlStrdup(BAD_CAST "Element '");
2206: }
2207: if (node->ns != NULL)
2208: *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2209: node->ns->href, node->name));
2210: else
2211: *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2212: NULL, node->name));
2213: FREE_AND_NULL(str);
2214: *msg = xmlStrcat(*msg, BAD_CAST "': ");
2215: } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2216: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2217: /*
2218: * Work on node infos.
2219: */
2220: if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2221: xmlSchemaNodeInfoPtr ielem =
2222: vctxt->elemInfos[vctxt->depth];
2223:
2224: *msg = xmlStrdup(BAD_CAST "Element '");
2225: *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2226: ielem->nsName, ielem->localName));
2227: FREE_AND_NULL(str);
2228: *msg = xmlStrcat(*msg, BAD_CAST "', ");
2229: *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2230: } else {
2231: *msg = xmlStrdup(BAD_CAST "Element '");
2232: }
2233: *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2234: vctxt->inode->nsName, vctxt->inode->localName));
2235: FREE_AND_NULL(str);
2236: *msg = xmlStrcat(*msg, BAD_CAST "': ");
2237: } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2238: /*
2239: * Hmm, no node while parsing?
2240: * Return an empty string, in case NULL will break something.
2241: */
2242: *msg = xmlStrdup(BAD_CAST "");
2243: } else {
2244: TODO
2245: return (NULL);
2246: }
2247: /*
2248: * VAL TODO: The output of the given schema component is currently
2249: * disabled.
2250: */
2251: #if 0
2252: if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2253: *msg = xmlStrcat(*msg, BAD_CAST " [");
2254: *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2255: NULL, type, NULL, 0));
2256: FREE_AND_NULL(str)
2257: *msg = xmlStrcat(*msg, BAD_CAST "]");
2258: }
2259: #endif
2260: return (*msg);
2261: }
2262:
2263: static void
2264: xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2265: const char *funcName,
2266: const char *message,
2267: const xmlChar *str1,
2268: const xmlChar *str2)
2269: {
2270: xmlChar *msg = NULL;
2271:
2272: if (actxt == NULL)
2273: return;
2274: msg = xmlStrdup(BAD_CAST "Internal error: ");
2275: msg = xmlStrcat(msg, BAD_CAST funcName);
2276: msg = xmlStrcat(msg, BAD_CAST ", ");
2277: msg = xmlStrcat(msg, BAD_CAST message);
2278: msg = xmlStrcat(msg, BAD_CAST ".\n");
2279:
2280: if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2281: xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
2282: (const char *) msg, str1, str2);
2283:
2284: else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2285: xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
2286: (const char *) msg, str1, str2);
2287:
2288: FREE_AND_NULL(msg)
2289: }
2290:
2291: static void
2292: xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2293: const char *funcName,
2294: const char *message)
2295: {
2296: xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2297: }
2298:
2299: #if 0
2300: static void
2301: xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2302: const char *funcName,
2303: const char *message,
2304: const xmlChar *str1,
2305: const xmlChar *str2)
2306: {
2307: xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2308: str1, str2);
2309: }
2310: #endif
2311:
2312: static void
2313: xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2314: xmlParserErrors error,
2315: xmlNodePtr node,
2316: xmlSchemaBasicItemPtr item,
2317: const char *message,
2318: const xmlChar *str1, const xmlChar *str2,
2319: const xmlChar *str3, const xmlChar *str4)
2320: {
2321: xmlChar *msg = NULL;
2322:
2323: if ((node == NULL) && (item != NULL) &&
2324: (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2325: node = WXS_ITEM_NODE(item);
2326: xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2327: msg = xmlStrcat(msg, BAD_CAST ": ");
2328: } else
2329: xmlSchemaFormatNodeForError(&msg, actxt, node);
2330: msg = xmlStrcat(msg, (const xmlChar *) message);
2331: msg = xmlStrcat(msg, BAD_CAST ".\n");
2332: xmlSchemaErr4(actxt, error, node,
2333: (const char *) msg, str1, str2, str3, str4);
2334: FREE_AND_NULL(msg)
2335: }
2336:
2337: static void
2338: xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2339: xmlParserErrors error,
2340: xmlNodePtr node,
2341: xmlSchemaBasicItemPtr item,
2342: const char *message,
2343: const xmlChar *str1,
2344: const xmlChar *str2)
2345: {
2346: xmlSchemaCustomErr4(actxt, error, node, item,
2347: message, str1, str2, NULL, NULL);
2348: }
2349:
2350:
2351:
2352: static void
2353: xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2354: xmlParserErrors error,
2355: xmlNodePtr node,
2356: xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2357: const char *message,
2358: const xmlChar *str1,
2359: const xmlChar *str2,
2360: const xmlChar *str3)
2361: {
2362: xmlChar *msg = NULL;
2363:
2364: xmlSchemaFormatNodeForError(&msg, actxt, node);
2365: msg = xmlStrcat(msg, (const xmlChar *) message);
2366: msg = xmlStrcat(msg, BAD_CAST ".\n");
2367:
2368: /* URGENT TODO: Set the error code to something sane. */
2369: xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2370: (const char *) msg, str1, str2, str3, NULL);
2371:
2372: FREE_AND_NULL(msg)
2373: }
2374:
2375:
2376:
2377: static void
2378: xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2379: xmlParserErrors error,
2380: xmlSchemaPSVIIDCNodePtr idcNode,
2381: xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2382: const char *message,
2383: const xmlChar *str1,
2384: const xmlChar *str2)
2385: {
2386: xmlChar *msg = NULL, *qname = NULL;
2387:
2388: msg = xmlStrdup(BAD_CAST "Element '%s': ");
2389: msg = xmlStrcat(msg, (const xmlChar *) message);
2390: msg = xmlStrcat(msg, BAD_CAST ".\n");
2391: xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2392: error, NULL, idcNode->nodeLine, (const char *) msg,
2393: xmlSchemaFormatQName(&qname,
2394: vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2395: vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2396: str1, str2, NULL);
2397: FREE_AND_NULL(qname);
2398: FREE_AND_NULL(msg);
2399: }
2400:
2401: static int
2402: xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2403: xmlNodePtr node)
2404: {
2405: if (node != NULL)
2406: return (node->type);
2407: if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2408: (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2409: return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2410: return (-1);
2411: }
2412:
2413: static int
2414: xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2415: {
2416: switch (item->type) {
2417: case XML_SCHEMA_TYPE_COMPLEX:
2418: case XML_SCHEMA_TYPE_SIMPLE:
2419: if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2420: return(1);
2421: break;
2422: case XML_SCHEMA_TYPE_GROUP:
2423: return (1);
2424: case XML_SCHEMA_TYPE_ELEMENT:
2425: if ( ((xmlSchemaElementPtr) item)->flags &
2426: XML_SCHEMAS_ELEM_GLOBAL)
2427: return(1);
2428: break;
2429: case XML_SCHEMA_TYPE_ATTRIBUTE:
2430: if ( ((xmlSchemaAttributePtr) item)->flags &
2431: XML_SCHEMAS_ATTR_GLOBAL)
2432: return(1);
2433: break;
2434: /* Note that attribute groups are always global. */
2435: default:
2436: return(1);
2437: }
2438: return (0);
2439: }
2440:
2441: static void
2442: xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2443: xmlParserErrors error,
2444: xmlNodePtr node,
2445: const xmlChar *value,
2446: xmlSchemaTypePtr type,
2447: int displayValue)
2448: {
2449: xmlChar *msg = NULL;
2450:
2451: xmlSchemaFormatNodeForError(&msg, actxt, node);
2452:
2453: if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2454: XML_ATTRIBUTE_NODE))
2455: msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2456: else
2457: msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2458: "value of ");
2459:
2460: if (! xmlSchemaIsGlobalItem(type))
2461: msg = xmlStrcat(msg, BAD_CAST "the local ");
2462: else
2463: msg = xmlStrcat(msg, BAD_CAST "the ");
2464:
2465: if (WXS_IS_ATOMIC(type))
2466: msg = xmlStrcat(msg, BAD_CAST "atomic type");
2467: else if (WXS_IS_LIST(type))
2468: msg = xmlStrcat(msg, BAD_CAST "list type");
2469: else if (WXS_IS_UNION(type))
2470: msg = xmlStrcat(msg, BAD_CAST "union type");
2471:
2472: if (xmlSchemaIsGlobalItem(type)) {
2473: xmlChar *str = NULL;
2474: msg = xmlStrcat(msg, BAD_CAST " '");
2475: if (type->builtInType != 0) {
2476: msg = xmlStrcat(msg, BAD_CAST "xs:");
2477: msg = xmlStrcat(msg, type->name);
2478: } else
2479: msg = xmlStrcat(msg,
2480: xmlSchemaFormatQName(&str,
2481: type->targetNamespace, type->name));
2482: msg = xmlStrcat(msg, BAD_CAST "'");
2483: FREE_AND_NULL(str);
2484: }
2485: msg = xmlStrcat(msg, BAD_CAST ".\n");
2486: if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2487: XML_ATTRIBUTE_NODE))
2488: xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2489: else
2490: xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2491: FREE_AND_NULL(msg)
2492: }
2493:
2494: static const xmlChar *
2495: xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2496: xmlSchemaNodeInfoPtr ni,
2497: xmlNodePtr node)
2498: {
2499: if (node != NULL) {
2500: if (node->ns != NULL)
2501: return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2502: else
2503: return (xmlSchemaFormatQName(str, NULL, node->name));
2504: } else if (ni != NULL)
2505: return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2506: return (NULL);
2507: }
2508:
2509: static void
2510: xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2511: xmlParserErrors error,
2512: xmlSchemaAttrInfoPtr ni,
2513: xmlNodePtr node)
2514: {
2515: xmlChar *msg = NULL, *str = NULL;
2516:
2517: xmlSchemaFormatNodeForError(&msg, actxt, node);
2518: msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2519: xmlSchemaErr(actxt, error, node, (const char *) msg,
2520: xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2521: NULL);
2522: FREE_AND_NULL(str)
2523: FREE_AND_NULL(msg)
2524: }
2525:
2526: static void
2527: xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2528: xmlParserErrors error,
2529: xmlNodePtr node,
2530: xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2531: const char *message,
2532: int nbval,
2533: int nbneg,
2534: xmlChar **values)
2535: {
2536: xmlChar *str = NULL, *msg = NULL;
2537: xmlChar *localName, *nsName;
2538: const xmlChar *cur, *end;
2539: int i;
2540:
2541: xmlSchemaFormatNodeForError(&msg, actxt, node);
2542: msg = xmlStrcat(msg, (const xmlChar *) message);
2543: msg = xmlStrcat(msg, BAD_CAST ".");
2544: /*
2545: * Note that is does not make sense to report that we have a
2546: * wildcard here, since the wildcard might be unfolded into
2547: * multiple transitions.
2548: */
2549: if (nbval + nbneg > 0) {
2550: if (nbval + nbneg > 1) {
2551: str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2552: } else
2553: str = xmlStrdup(BAD_CAST " Expected is ( ");
2554: nsName = NULL;
2555:
2556: for (i = 0; i < nbval + nbneg; i++) {
2557: cur = values[i];
2558: if (cur == NULL)
2559: continue;
2560: if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2561: (cur[3] == ' ')) {
2562: cur += 4;
2563: str = xmlStrcat(str, BAD_CAST "##other");
2564: }
2565: /*
2566: * Get the local name.
2567: */
2568: localName = NULL;
2569:
2570: end = cur;
2571: if (*end == '*') {
2572: localName = xmlStrdup(BAD_CAST "*");
2573: end++;
2574: } else {
2575: while ((*end != 0) && (*end != '|'))
2576: end++;
2577: localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2578: }
2579: if (*end != 0) {
2580: end++;
2581: /*
2582: * Skip "*|*" if they come with negated expressions, since
2583: * they represent the same negated wildcard.
2584: */
2585: if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2586: /*
2587: * Get the namespace name.
2588: */
2589: cur = end;
2590: if (*end == '*') {
2591: nsName = xmlStrdup(BAD_CAST "{*}");
2592: } else {
2593: while (*end != 0)
2594: end++;
2595:
2596: if (i >= nbval)
2597: nsName = xmlStrdup(BAD_CAST "{##other:");
2598: else
2599: nsName = xmlStrdup(BAD_CAST "{");
2600:
2601: nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2602: nsName = xmlStrcat(nsName, BAD_CAST "}");
2603: }
2604: str = xmlStrcat(str, BAD_CAST nsName);
2605: FREE_AND_NULL(nsName)
2606: } else {
2607: FREE_AND_NULL(localName);
2608: continue;
2609: }
2610: }
2611: str = xmlStrcat(str, BAD_CAST localName);
2612: FREE_AND_NULL(localName);
2613:
2614: if (i < nbval + nbneg -1)
2615: str = xmlStrcat(str, BAD_CAST ", ");
2616: }
2617: str = xmlStrcat(str, BAD_CAST " ).\n");
2618: msg = xmlStrcat(msg, BAD_CAST str);
2619: FREE_AND_NULL(str)
2620: } else
2621: msg = xmlStrcat(msg, BAD_CAST "\n");
2622: xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2623: xmlFree(msg);
2624: }
2625:
2626: static void
2627: xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2628: xmlParserErrors error,
2629: xmlNodePtr node,
2630: const xmlChar *value,
2631: unsigned long length,
2632: xmlSchemaTypePtr type,
2633: xmlSchemaFacetPtr facet,
2634: const char *message,
2635: const xmlChar *str1,
2636: const xmlChar *str2)
2637: {
2638: xmlChar *str = NULL, *msg = NULL;
2639: xmlSchemaTypeType facetType;
2640: int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2641:
2642: xmlSchemaFormatNodeForError(&msg, actxt, node);
2643: if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2644: facetType = XML_SCHEMA_FACET_ENUMERATION;
2645: /*
2646: * If enumerations are validated, one must not expect the
2647: * facet to be given.
2648: */
2649: } else
2650: facetType = facet->type;
2651: msg = xmlStrcat(msg, BAD_CAST "[");
2652: msg = xmlStrcat(msg, BAD_CAST "facet '");
2653: msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2654: msg = xmlStrcat(msg, BAD_CAST "'] ");
2655: if (message == NULL) {
2656: /*
2657: * Use a default message.
2658: */
2659: if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2660: (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2661: (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2662:
2663: char len[25], actLen[25];
2664:
2665: /* FIXME, TODO: What is the max expected string length of the
2666: * this value?
2667: */
2668: if (nodeType == XML_ATTRIBUTE_NODE)
2669: msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2670: else
2671: msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2672:
2673: snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2674: snprintf(actLen, 24, "%lu", length);
2675:
2676: if (facetType == XML_SCHEMA_FACET_LENGTH)
2677: msg = xmlStrcat(msg,
2678: BAD_CAST "this differs from the allowed length of '%s'.\n");
2679: else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2680: msg = xmlStrcat(msg,
2681: BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2682: else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2683: msg = xmlStrcat(msg,
2684: BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2685:
2686: if (nodeType == XML_ATTRIBUTE_NODE)
2687: xmlSchemaErr3(actxt, error, node, (const char *) msg,
2688: value, (const xmlChar *) actLen, (const xmlChar *) len);
2689: else
2690: xmlSchemaErr(actxt, error, node, (const char *) msg,
2691: (const xmlChar *) actLen, (const xmlChar *) len);
2692:
2693: } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2694: msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2695: "of the set {%s}.\n");
2696: xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2697: xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2698: } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2699: msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2700: "by the pattern '%s'.\n");
2701: xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2702: facet->value);
2703: } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2704: msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2705: "minimum value allowed ('%s').\n");
2706: xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2707: facet->value);
2708: } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2709: msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2710: "maximum value allowed ('%s').\n");
2711: xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2712: facet->value);
2713: } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2714: msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2715: "'%s'.\n");
2716: xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2717: facet->value);
2718: } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2719: msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2720: "'%s'.\n");
2721: xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2722: facet->value);
2723: } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2724: msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2725: "digits than are allowed ('%s').\n");
2726: xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2727: facet->value);
2728: } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2729: msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2730: "digits than are allowed ('%s').\n");
2731: xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2732: facet->value);
2733: } else if (nodeType == XML_ATTRIBUTE_NODE) {
2734: msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2735: xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2736: } else {
2737: msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2738: xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2739: }
2740: } else {
2741: msg = xmlStrcat(msg, (const xmlChar *) message);
2742: msg = xmlStrcat(msg, BAD_CAST ".\n");
2743: xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2744: }
2745: FREE_AND_NULL(str)
2746: xmlFree(msg);
2747: }
2748:
2749: #define VERROR(err, type, msg) \
2750: xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2751:
2752: #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2753:
2754: #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2755: #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2756:
2757: #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2758:
2759:
2760: /**
2761: * xmlSchemaPMissingAttrErr:
2762: * @ctxt: the schema validation context
2763: * @ownerDes: the designation of the owner
2764: * @ownerName: the name of the owner
2765: * @ownerItem: the owner as a schema object
2766: * @ownerElem: the owner as an element node
2767: * @node: the parent element node of the missing attribute node
2768: * @type: the corresponding type of the attribute node
2769: *
2770: * Reports an illegal attribute.
2771: */
2772: static void
2773: xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2774: xmlParserErrors error,
2775: xmlSchemaBasicItemPtr ownerItem,
2776: xmlNodePtr ownerElem,
2777: const char *name,
2778: const char *message)
2779: {
2780: xmlChar *des = NULL;
2781:
2782: xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2783:
2784: if (message != NULL)
2785: xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2786: else
2787: xmlSchemaPErr(ctxt, ownerElem, error,
2788: "%s: The attribute '%s' is required but missing.\n",
2789: BAD_CAST des, BAD_CAST name);
2790: FREE_AND_NULL(des);
2791: }
2792:
2793:
2794: /**
2795: * xmlSchemaPResCompAttrErr:
2796: * @ctxt: the schema validation context
2797: * @error: the error code
2798: * @ownerDes: the designation of the owner
2799: * @ownerItem: the owner as a schema object
2800: * @ownerElem: the owner as an element node
2801: * @name: the name of the attribute holding the QName
2802: * @refName: the referenced local name
2803: * @refURI: the referenced namespace URI
2804: * @message: optional message
2805: *
2806: * Used to report QName attribute values that failed to resolve
2807: * to schema components.
2808: */
2809: static void
2810: xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2811: xmlParserErrors error,
2812: xmlSchemaBasicItemPtr ownerItem,
2813: xmlNodePtr ownerElem,
2814: const char *name,
2815: const xmlChar *refName,
2816: const xmlChar *refURI,
2817: xmlSchemaTypeType refType,
2818: const char *refTypeStr)
2819: {
2820: xmlChar *des = NULL, *strA = NULL;
2821:
2822: xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2823: if (refTypeStr == NULL)
2824: refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2825: xmlSchemaPErrExt(ctxt, ownerElem, error,
2826: NULL, NULL, NULL,
2827: "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2828: "%s.\n", BAD_CAST des, BAD_CAST name,
2829: xmlSchemaFormatQName(&strA, refURI, refName),
2830: BAD_CAST refTypeStr, NULL);
2831: FREE_AND_NULL(des)
2832: FREE_AND_NULL(strA)
2833: }
2834:
2835: /**
2836: * xmlSchemaPCustomAttrErr:
2837: * @ctxt: the schema parser context
2838: * @error: the error code
2839: * @ownerDes: the designation of the owner
2840: * @ownerItem: the owner as a schema object
2841: * @attr: the illegal attribute node
2842: *
2843: * Reports an illegal attribute during the parse.
2844: */
2845: static void
2846: xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2847: xmlParserErrors error,
2848: xmlChar **ownerDes,
2849: xmlSchemaBasicItemPtr ownerItem,
2850: xmlAttrPtr attr,
2851: const char *msg)
2852: {
2853: xmlChar *des = NULL;
2854:
2855: if (ownerDes == NULL)
2856: xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2857: else if (*ownerDes == NULL) {
2858: xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2859: des = *ownerDes;
2860: } else
2861: des = *ownerDes;
2862: if (attr == NULL) {
2863: xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2864: "%s, attribute '%s': %s.\n",
2865: BAD_CAST des, (const xmlChar *) "Unknown",
2866: (const xmlChar *) msg, NULL, NULL);
2867: } else {
2868: xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2869: "%s, attribute '%s': %s.\n",
2870: BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2871: }
2872: if (ownerDes == NULL)
2873: FREE_AND_NULL(des);
2874: }
2875:
2876: /**
2877: * xmlSchemaPIllegalAttrErr:
2878: * @ctxt: the schema parser context
2879: * @error: the error code
2880: * @ownerDes: the designation of the attribute's owner
2881: * @ownerItem: the attribute's owner item
2882: * @attr: the illegal attribute node
2883: *
2884: * Reports an illegal attribute during the parse.
2885: */
2886: static void
2887: xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2888: xmlParserErrors error,
2889: xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2890: xmlAttrPtr attr)
2891: {
2892: xmlChar *strA = NULL, *strB = NULL;
2893:
2894: xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2895: xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2896: "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2897: xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2898: NULL, NULL);
2899: FREE_AND_NULL(strA);
2900: FREE_AND_NULL(strB);
2901: }
2902:
2903: /**
2904: * xmlSchemaPCustomErr:
2905: * @ctxt: the schema parser context
2906: * @error: the error code
2907: * @itemDes: the designation of the schema item
2908: * @item: the schema item
2909: * @itemElem: the node of the schema item
2910: * @message: the error message
2911: * @str1: an optional param for the error message
2912: * @str2: an optional param for the error message
2913: * @str3: an optional param for the error message
2914: *
2915: * Reports an error during parsing.
2916: */
2917: static void
2918: xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2919: xmlParserErrors error,
2920: xmlSchemaBasicItemPtr item,
2921: xmlNodePtr itemElem,
2922: const char *message,
2923: const xmlChar *str1,
2924: const xmlChar *str2,
2925: const xmlChar *str3)
2926: {
2927: xmlChar *des = NULL, *msg = NULL;
2928:
2929: xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2930: msg = xmlStrdup(BAD_CAST "%s: ");
2931: msg = xmlStrcat(msg, (const xmlChar *) message);
2932: msg = xmlStrcat(msg, BAD_CAST ".\n");
2933: if ((itemElem == NULL) && (item != NULL))
2934: itemElem = WXS_ITEM_NODE(item);
2935: xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2936: (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2937: FREE_AND_NULL(des);
2938: FREE_AND_NULL(msg);
2939: }
2940:
2941: /**
2942: * xmlSchemaPCustomErr:
2943: * @ctxt: the schema parser context
2944: * @error: the error code
2945: * @itemDes: the designation of the schema item
2946: * @item: the schema item
2947: * @itemElem: the node of the schema item
2948: * @message: the error message
2949: * @str1: the optional param for the error message
2950: *
2951: * Reports an error during parsing.
2952: */
2953: static void
2954: xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2955: xmlParserErrors error,
2956: xmlSchemaBasicItemPtr item,
2957: xmlNodePtr itemElem,
2958: const char *message,
2959: const xmlChar *str1)
2960: {
2961: xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2962: str1, NULL, NULL);
2963: }
2964:
2965: /**
2966: * xmlSchemaPAttrUseErr:
2967: * @ctxt: the schema parser context
2968: * @error: the error code
2969: * @itemDes: the designation of the schema type
2970: * @item: the schema type
2971: * @itemElem: the node of the schema type
2972: * @attr: the invalid schema attribute
2973: * @message: the error message
2974: * @str1: the optional param for the error message
2975: *
2976: * Reports an attribute use error during parsing.
2977: */
2978: static void
2979: xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
2980: xmlParserErrors error,
2981: xmlNodePtr node,
2982: xmlSchemaBasicItemPtr ownerItem,
2983: const xmlSchemaAttributeUsePtr attruse,
2984: const char *message,
2985: const xmlChar *str1, const xmlChar *str2,
2986: const xmlChar *str3,const xmlChar *str4)
2987: {
2988: xmlChar *str = NULL, *msg = NULL;
2989:
2990: xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2991: msg = xmlStrcat(msg, BAD_CAST ", ");
2992: msg = xmlStrcat(msg,
2993: BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2994: WXS_BASIC_CAST attruse, NULL));
2995: FREE_AND_NULL(str);
2996: msg = xmlStrcat(msg, BAD_CAST ": ");
2997: msg = xmlStrcat(msg, (const xmlChar *) message);
2998: msg = xmlStrcat(msg, BAD_CAST ".\n");
2999: xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3000: (const char *) msg, str1, str2, str3, str4);
3001: xmlFree(msg);
3002: }
3003:
3004: /**
3005: * xmlSchemaPIllegalFacetAtomicErr:
3006: * @ctxt: the schema parser context
3007: * @error: the error code
3008: * @type: the schema type
3009: * @baseType: the base type of type
3010: * @facet: the illegal facet
3011: *
3012: * Reports an illegal facet for atomic simple types.
3013: */
3014: static void
3015: xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3016: xmlParserErrors error,
3017: xmlSchemaTypePtr type,
3018: xmlSchemaTypePtr baseType,
3019: xmlSchemaFacetPtr facet)
3020: {
3021: xmlChar *des = NULL, *strT = NULL;
3022:
3023: xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3024: xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3025: "%s: The facet '%s' is not allowed on types derived from the "
3026: "type %s.\n",
3027: BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3028: xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3029: NULL, NULL);
3030: FREE_AND_NULL(des);
3031: FREE_AND_NULL(strT);
3032: }
3033:
3034: /**
3035: * xmlSchemaPIllegalFacetListUnionErr:
3036: * @ctxt: the schema parser context
3037: * @error: the error code
3038: * @itemDes: the designation of the schema item involved
3039: * @item: the schema item involved
3040: * @facet: the illegal facet
3041: *
3042: * Reports an illegal facet for <list> and <union>.
3043: */
3044: static void
3045: xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3046: xmlParserErrors error,
3047: xmlSchemaTypePtr type,
3048: xmlSchemaFacetPtr facet)
3049: {
3050: xmlChar *des = NULL;
3051:
3052: xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3053: type->node);
3054: xmlSchemaPErr(ctxt, type->node, error,
3055: "%s: The facet '%s' is not allowed.\n",
3056: BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3057: FREE_AND_NULL(des);
3058: }
3059:
3060: /**
3061: * xmlSchemaPMutualExclAttrErr:
3062: * @ctxt: the schema validation context
3063: * @error: the error code
3064: * @elemDes: the designation of the parent element node
3065: * @attr: the bad attribute node
3066: * @type: the corresponding type of the attribute node
3067: *
3068: * Reports an illegal attribute.
3069: */
3070: static void
3071: xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3072: xmlParserErrors error,
3073: xmlSchemaBasicItemPtr ownerItem,
3074: xmlAttrPtr attr,
3075: const char *name1,
3076: const char *name2)
3077: {
3078: xmlChar *des = NULL;
3079:
3080: xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3081: xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3082: "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3083: BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3084: FREE_AND_NULL(des);
3085: }
3086:
3087: /**
3088: * xmlSchemaPSimpleTypeErr:
3089: * @ctxt: the schema validation context
3090: * @error: the error code
3091: * @type: the type specifier
3092: * @ownerDes: the designation of the owner
3093: * @ownerItem: the schema object if existent
3094: * @node: the validated node
3095: * @value: the validated value
3096: *
3097: * Reports a simple type validation error.
3098: * TODO: Should this report the value of an element as well?
3099: */
3100: static void
3101: xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3102: xmlParserErrors error,
3103: xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3104: xmlNodePtr node,
3105: xmlSchemaTypePtr type,
3106: const char *expected,
3107: const xmlChar *value,
3108: const char *message,
3109: const xmlChar *str1,
3110: const xmlChar *str2)
3111: {
3112: xmlChar *msg = NULL;
3113:
3114: xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3115: if (message == NULL) {
3116: /*
3117: * Use default messages.
3118: */
3119: if (type != NULL) {
3120: if (node->type == XML_ATTRIBUTE_NODE)
3121: msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3122: else
3123: msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3124: "valid value of ");
3125: if (! xmlSchemaIsGlobalItem(type))
3126: msg = xmlStrcat(msg, BAD_CAST "the local ");
3127: else
3128: msg = xmlStrcat(msg, BAD_CAST "the ");
3129:
3130: if (WXS_IS_ATOMIC(type))
3131: msg = xmlStrcat(msg, BAD_CAST "atomic type");
3132: else if (WXS_IS_LIST(type))
3133: msg = xmlStrcat(msg, BAD_CAST "list type");
3134: else if (WXS_IS_UNION(type))
3135: msg = xmlStrcat(msg, BAD_CAST "union type");
3136:
3137: if (xmlSchemaIsGlobalItem(type)) {
3138: xmlChar *str = NULL;
3139: msg = xmlStrcat(msg, BAD_CAST " '");
3140: if (type->builtInType != 0) {
3141: msg = xmlStrcat(msg, BAD_CAST "xs:");
3142: msg = xmlStrcat(msg, type->name);
3143: } else
3144: msg = xmlStrcat(msg,
3145: xmlSchemaFormatQName(&str,
3146: type->targetNamespace, type->name));
3147: msg = xmlStrcat(msg, BAD_CAST "'.");
3148: FREE_AND_NULL(str);
3149: }
3150: } else {
3151: if (node->type == XML_ATTRIBUTE_NODE)
3152: msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3153: else
3154: msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3155: "valid.");
3156: }
3157: if (expected) {
3158: msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3159: msg = xmlStrcat(msg, BAD_CAST expected);
3160: msg = xmlStrcat(msg, BAD_CAST "'.\n");
3161: } else
3162: msg = xmlStrcat(msg, BAD_CAST "\n");
3163: if (node->type == XML_ATTRIBUTE_NODE)
3164: xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3165: else
3166: xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3167: } else {
3168: msg = xmlStrcat(msg, BAD_CAST message);
3169: msg = xmlStrcat(msg, BAD_CAST ".\n");
3170: xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3171: (const char*) msg, str1, str2, NULL, NULL, NULL);
3172: }
3173: /* Cleanup. */
3174: FREE_AND_NULL(msg)
3175: }
3176:
3177: /**
3178: * xmlSchemaPContentErr:
3179: * @ctxt: the schema parser context
3180: * @error: the error code
3181: * @onwerDes: the designation of the holder of the content
3182: * @ownerItem: the owner item of the holder of the content
3183: * @ownerElem: the node of the holder of the content
3184: * @child: the invalid child node
3185: * @message: the optional error message
3186: * @content: the optional string describing the correct content
3187: *
3188: * Reports an error concerning the content of a schema element.
3189: */
3190: static void
3191: xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3192: xmlParserErrors error,
3193: xmlSchemaBasicItemPtr ownerItem,
3194: xmlNodePtr ownerElem,
3195: xmlNodePtr child,
3196: const char *message,
3197: const char *content)
3198: {
3199: xmlChar *des = NULL;
3200:
3201: xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3202: if (message != NULL)
3203: xmlSchemaPErr2(ctxt, ownerElem, child, error,
3204: "%s: %s.\n",
3205: BAD_CAST des, BAD_CAST message);
3206: else {
3207: if (content != NULL) {
3208: xmlSchemaPErr2(ctxt, ownerElem, child, error,
3209: "%s: The content is not valid. Expected is %s.\n",
3210: BAD_CAST des, BAD_CAST content);
3211: } else {
3212: xmlSchemaPErr2(ctxt, ownerElem, child, error,
3213: "%s: The content is not valid.\n",
3214: BAD_CAST des, NULL);
3215: }
3216: }
3217: FREE_AND_NULL(des)
3218: }
3219:
3220: /************************************************************************
1.1.1.3 ! misho 3221: * *
! 3222: * Streamable error functions *
! 3223: * *
1.1 misho 3224: ************************************************************************/
3225:
3226:
3227:
3228:
3229: /************************************************************************
1.1.1.3 ! misho 3230: * *
! 3231: * Validation helper functions *
! 3232: * *
1.1 misho 3233: ************************************************************************/
3234:
3235:
3236: /************************************************************************
1.1.1.3 ! misho 3237: * *
! 3238: * Allocation functions *
! 3239: * *
1.1 misho 3240: ************************************************************************/
3241:
3242: /**
3243: * xmlSchemaNewSchemaForParserCtxt:
3244: * @ctxt: a schema validation context
3245: *
3246: * Allocate a new Schema structure.
3247: *
3248: * Returns the newly allocated structure or NULL in case or error
3249: */
3250: static xmlSchemaPtr
3251: xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3252: {
3253: xmlSchemaPtr ret;
3254:
3255: ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3256: if (ret == NULL) {
3257: xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3258: return (NULL);
3259: }
3260: memset(ret, 0, sizeof(xmlSchema));
3261: ret->dict = ctxt->dict;
3262: xmlDictReference(ret->dict);
3263:
3264: return (ret);
3265: }
3266:
3267: /**
3268: * xmlSchemaNewFacet:
3269: *
3270: * Allocate a new Facet structure.
3271: *
3272: * Returns the newly allocated structure or NULL in case or error
3273: */
3274: xmlSchemaFacetPtr
3275: xmlSchemaNewFacet(void)
3276: {
3277: xmlSchemaFacetPtr ret;
3278:
3279: ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3280: if (ret == NULL) {
3281: return (NULL);
3282: }
3283: memset(ret, 0, sizeof(xmlSchemaFacet));
3284:
3285: return (ret);
3286: }
3287:
3288: /**
3289: * xmlSchemaNewAnnot:
3290: * @ctxt: a schema validation context
3291: * @node: a node
3292: *
3293: * Allocate a new annotation structure.
3294: *
3295: * Returns the newly allocated structure or NULL in case or error
3296: */
3297: static xmlSchemaAnnotPtr
3298: xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3299: {
3300: xmlSchemaAnnotPtr ret;
3301:
3302: ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3303: if (ret == NULL) {
3304: xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3305: return (NULL);
3306: }
3307: memset(ret, 0, sizeof(xmlSchemaAnnot));
3308: ret->content = node;
3309: return (ret);
3310: }
3311:
3312: static xmlSchemaItemListPtr
3313: xmlSchemaItemListCreate(void)
3314: {
3315: xmlSchemaItemListPtr ret;
3316:
3317: ret = xmlMalloc(sizeof(xmlSchemaItemList));
3318: if (ret == NULL) {
3319: xmlSchemaPErrMemory(NULL,
3320: "allocating an item list structure", NULL);
3321: return (NULL);
3322: }
3323: memset(ret, 0, sizeof(xmlSchemaItemList));
3324: return (ret);
3325: }
3326:
3327: static void
3328: xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3329: {
3330: if (list->items != NULL) {
3331: xmlFree(list->items);
3332: list->items = NULL;
3333: }
3334: list->nbItems = 0;
3335: list->sizeItems = 0;
3336: }
3337:
3338: static int
3339: xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3340: {
3341: if (list->items == NULL) {
3342: list->items = (void **) xmlMalloc(
3343: 20 * sizeof(void *));
3344: if (list->items == NULL) {
3345: xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3346: return(-1);
3347: }
3348: list->sizeItems = 20;
3349: } else if (list->sizeItems <= list->nbItems) {
3350: list->sizeItems *= 2;
3351: list->items = (void **) xmlRealloc(list->items,
3352: list->sizeItems * sizeof(void *));
3353: if (list->items == NULL) {
3354: xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3355: list->sizeItems = 0;
3356: return(-1);
3357: }
3358: }
3359: list->items[list->nbItems++] = item;
3360: return(0);
3361: }
3362:
3363: static int
3364: xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3365: int initialSize,
3366: void *item)
3367: {
3368: if (list->items == NULL) {
3369: if (initialSize <= 0)
3370: initialSize = 1;
3371: list->items = (void **) xmlMalloc(
3372: initialSize * sizeof(void *));
3373: if (list->items == NULL) {
3374: xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3375: return(-1);
3376: }
3377: list->sizeItems = initialSize;
3378: } else if (list->sizeItems <= list->nbItems) {
3379: list->sizeItems *= 2;
3380: list->items = (void **) xmlRealloc(list->items,
3381: list->sizeItems * sizeof(void *));
3382: if (list->items == NULL) {
3383: xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3384: list->sizeItems = 0;
3385: return(-1);
3386: }
3387: }
3388: list->items[list->nbItems++] = item;
3389: return(0);
3390: }
3391:
3392: static int
3393: xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3394: {
3395: if (list->items == NULL) {
3396: list->items = (void **) xmlMalloc(
3397: 20 * sizeof(void *));
3398: if (list->items == NULL) {
3399: xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3400: return(-1);
3401: }
3402: list->sizeItems = 20;
3403: } else if (list->sizeItems <= list->nbItems) {
3404: list->sizeItems *= 2;
3405: list->items = (void **) xmlRealloc(list->items,
3406: list->sizeItems * sizeof(void *));
3407: if (list->items == NULL) {
3408: xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3409: list->sizeItems = 0;
3410: return(-1);
3411: }
3412: }
3413: /*
3414: * Just append if the index is greater/equal than the item count.
3415: */
3416: if (idx >= list->nbItems) {
3417: list->items[list->nbItems++] = item;
3418: } else {
3419: int i;
3420: for (i = list->nbItems; i > idx; i--)
3421: list->items[i] = list->items[i-1];
3422: list->items[idx] = item;
3423: list->nbItems++;
3424: }
3425: return(0);
3426: }
3427:
3428: #if 0 /* enable if ever needed */
3429: static int
3430: xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3431: int initialSize,
3432: void *item,
3433: int idx)
3434: {
3435: if (list->items == NULL) {
3436: if (initialSize <= 0)
3437: initialSize = 1;
3438: list->items = (void **) xmlMalloc(
3439: initialSize * sizeof(void *));
3440: if (list->items == NULL) {
3441: xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3442: return(-1);
3443: }
3444: list->sizeItems = initialSize;
3445: } else if (list->sizeItems <= list->nbItems) {
3446: list->sizeItems *= 2;
3447: list->items = (void **) xmlRealloc(list->items,
3448: list->sizeItems * sizeof(void *));
3449: if (list->items == NULL) {
3450: xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3451: list->sizeItems = 0;
3452: return(-1);
3453: }
3454: }
3455: /*
3456: * Just append if the index is greater/equal than the item count.
3457: */
3458: if (idx >= list->nbItems) {
3459: list->items[list->nbItems++] = item;
3460: } else {
3461: int i;
3462: for (i = list->nbItems; i > idx; i--)
3463: list->items[i] = list->items[i-1];
3464: list->items[idx] = item;
3465: list->nbItems++;
3466: }
3467: return(0);
3468: }
3469: #endif
3470:
3471: static int
3472: xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3473: {
3474: int i;
3475: if ((list->items == NULL) || (idx >= list->nbItems)) {
3476: xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3477: "index error.\n");
3478: return(-1);
3479: }
3480:
3481: if (list->nbItems == 1) {
3482: /* TODO: Really free the list? */
3483: xmlFree(list->items);
3484: list->items = NULL;
3485: list->nbItems = 0;
3486: list->sizeItems = 0;
3487: } else if (list->nbItems -1 == idx) {
3488: list->nbItems--;
3489: } else {
3490: for (i = idx; i < list->nbItems -1; i++)
3491: list->items[i] = list->items[i+1];
3492: list->nbItems--;
3493: }
3494: return(0);
3495: }
3496:
3497: /**
3498: * xmlSchemaItemListFree:
3499: * @annot: a schema type structure
3500: *
3501: * Deallocate a annotation structure
3502: */
3503: static void
3504: xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3505: {
3506: if (list == NULL)
3507: return;
3508: if (list->items != NULL)
3509: xmlFree(list->items);
3510: xmlFree(list);
3511: }
3512:
3513: static void
3514: xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3515: {
3516: if (bucket == NULL)
3517: return;
3518: if (bucket->globals != NULL) {
3519: xmlSchemaComponentListFree(bucket->globals);
3520: xmlSchemaItemListFree(bucket->globals);
3521: }
3522: if (bucket->locals != NULL) {
3523: xmlSchemaComponentListFree(bucket->locals);
3524: xmlSchemaItemListFree(bucket->locals);
3525: }
3526: if (bucket->relations != NULL) {
3527: xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3528: do {
3529: prev = cur;
3530: cur = cur->next;
3531: xmlFree(prev);
3532: } while (cur != NULL);
3533: }
3534: if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3535: xmlFreeDoc(bucket->doc);
3536: }
3537: if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3538: if (WXS_IMPBUCKET(bucket)->schema != NULL)
3539: xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3540: }
3541: xmlFree(bucket);
3542: }
3543:
3544: static xmlSchemaBucketPtr
3545: xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3546: int type, const xmlChar *targetNamespace)
3547: {
3548: xmlSchemaBucketPtr ret;
3549: int size;
3550: xmlSchemaPtr mainSchema;
3551:
3552: if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3553: PERROR_INT("xmlSchemaBucketCreate",
3554: "no main schema on constructor");
3555: return(NULL);
3556: }
3557: mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3558: /* Create the schema bucket. */
3559: if (WXS_IS_BUCKET_INCREDEF(type))
3560: size = sizeof(xmlSchemaInclude);
3561: else
3562: size = sizeof(xmlSchemaImport);
3563: ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3564: if (ret == NULL) {
3565: xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3566: return(NULL);
3567: }
3568: memset(ret, 0, size);
3569: ret->targetNamespace = targetNamespace;
3570: ret->type = type;
3571: ret->globals = xmlSchemaItemListCreate();
3572: if (ret->globals == NULL) {
3573: xmlFree(ret);
3574: return(NULL);
3575: }
3576: ret->locals = xmlSchemaItemListCreate();
3577: if (ret->locals == NULL) {
3578: xmlFree(ret);
3579: return(NULL);
3580: }
3581: /*
3582: * The following will assure that only the first bucket is marked as
3583: * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3584: * For each following import buckets an xmlSchema will be created.
3585: * An xmlSchema will be created for every distinct targetNamespace.
3586: * We assign the targetNamespace to the schemata here.
3587: */
3588: if (! WXS_HAS_BUCKETS(pctxt)) {
3589: if (WXS_IS_BUCKET_INCREDEF(type)) {
3590: PERROR_INT("xmlSchemaBucketCreate",
3591: "first bucket but it's an include or redefine");
3592: xmlSchemaBucketFree(ret);
3593: return(NULL);
3594: }
3595: /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3596: ret->type = XML_SCHEMA_SCHEMA_MAIN;
3597: /* Point to the *main* schema. */
3598: WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3599: WXS_IMPBUCKET(ret)->schema = mainSchema;
3600: /*
3601: * Ensure that the main schema gets a targetNamespace.
3602: */
3603: mainSchema->targetNamespace = targetNamespace;
3604: } else {
3605: if (type == XML_SCHEMA_SCHEMA_MAIN) {
3606: PERROR_INT("xmlSchemaBucketCreate",
3607: "main bucket but it's not the first one");
3608: xmlSchemaBucketFree(ret);
3609: return(NULL);
3610: } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3611: /*
3612: * Create a schema for imports and assign the
3613: * targetNamespace.
3614: */
3615: WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3616: if (WXS_IMPBUCKET(ret)->schema == NULL) {
3617: xmlSchemaBucketFree(ret);
3618: return(NULL);
3619: }
3620: WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3621: }
3622: }
3623: if (WXS_IS_BUCKET_IMPMAIN(type)) {
3624: int res;
3625: /*
3626: * Imports go into the "schemasImports" slot of the main *schema*.
3627: * Note that we create an import entry for the main schema as well; i.e.,
3628: * even if there's only one schema, we'll get an import.
3629: */
3630: if (mainSchema->schemasImports == NULL) {
3631: mainSchema->schemasImports = xmlHashCreateDict(5,
3632: WXS_CONSTRUCTOR(pctxt)->dict);
3633: if (mainSchema->schemasImports == NULL) {
3634: xmlSchemaBucketFree(ret);
3635: return(NULL);
3636: }
3637: }
3638: if (targetNamespace == NULL)
3639: res = xmlHashAddEntry(mainSchema->schemasImports,
3640: XML_SCHEMAS_NO_NAMESPACE, ret);
3641: else
3642: res = xmlHashAddEntry(mainSchema->schemasImports,
3643: targetNamespace, ret);
3644: if (res != 0) {
3645: PERROR_INT("xmlSchemaBucketCreate",
3646: "failed to add the schema bucket to the hash");
3647: xmlSchemaBucketFree(ret);
3648: return(NULL);
3649: }
3650: } else {
3651: /* Set the @ownerImport of an include bucket. */
3652: if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3653: WXS_INCBUCKET(ret)->ownerImport =
3654: WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3655: else
3656: WXS_INCBUCKET(ret)->ownerImport =
3657: WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3658:
3659: /* Includes got into the "includes" slot of the *main* schema. */
3660: if (mainSchema->includes == NULL) {
3661: mainSchema->includes = xmlSchemaItemListCreate();
3662: if (mainSchema->includes == NULL) {
3663: xmlSchemaBucketFree(ret);
3664: return(NULL);
3665: }
3666: }
3667: xmlSchemaItemListAdd(mainSchema->includes, ret);
3668: }
3669: /*
3670: * Add to list of all buckets; this is used for lookup
3671: * during schema construction time only.
3672: */
3673: if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3674: return(NULL);
3675: return(ret);
3676: }
3677:
3678: static int
3679: xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3680: {
3681: if (*list == NULL) {
3682: *list = xmlSchemaItemListCreate();
3683: if (*list == NULL)
3684: return(-1);
3685: }
3686: xmlSchemaItemListAddSize(*list, initialSize, item);
3687: return(0);
3688: }
3689:
3690: /**
3691: * xmlSchemaFreeAnnot:
3692: * @annot: a schema type structure
3693: *
3694: * Deallocate a annotation structure
3695: */
3696: static void
3697: xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3698: {
3699: if (annot == NULL)
3700: return;
3701: if (annot->next == NULL) {
3702: xmlFree(annot);
3703: } else {
3704: xmlSchemaAnnotPtr prev;
3705:
3706: do {
3707: prev = annot;
3708: annot = annot->next;
3709: xmlFree(prev);
3710: } while (annot != NULL);
3711: }
3712: }
3713:
3714: /**
3715: * xmlSchemaFreeNotation:
3716: * @schema: a schema notation structure
3717: *
3718: * Deallocate a Schema Notation structure.
3719: */
3720: static void
3721: xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3722: {
3723: if (nota == NULL)
3724: return;
3725: xmlFree(nota);
3726: }
3727:
3728: /**
3729: * xmlSchemaFreeAttribute:
3730: * @attr: an attribute declaration
3731: *
3732: * Deallocates an attribute declaration structure.
3733: */
3734: static void
3735: xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3736: {
3737: if (attr == NULL)
3738: return;
3739: if (attr->annot != NULL)
3740: xmlSchemaFreeAnnot(attr->annot);
3741: if (attr->defVal != NULL)
3742: xmlSchemaFreeValue(attr->defVal);
3743: xmlFree(attr);
3744: }
3745:
3746: /**
3747: * xmlSchemaFreeAttributeUse:
3748: * @use: an attribute use
3749: *
3750: * Deallocates an attribute use structure.
3751: */
3752: static void
3753: xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3754: {
3755: if (use == NULL)
3756: return;
3757: if (use->annot != NULL)
3758: xmlSchemaFreeAnnot(use->annot);
3759: if (use->defVal != NULL)
3760: xmlSchemaFreeValue(use->defVal);
3761: xmlFree(use);
3762: }
3763:
3764: /**
3765: * xmlSchemaFreeAttributeUseProhib:
3766: * @prohib: an attribute use prohibition
3767: *
3768: * Deallocates an attribute use structure.
3769: */
3770: static void
3771: xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3772: {
3773: if (prohib == NULL)
3774: return;
3775: xmlFree(prohib);
3776: }
3777:
3778: /**
3779: * xmlSchemaFreeWildcardNsSet:
3780: * set: a schema wildcard namespace
3781: *
3782: * Deallocates a list of wildcard constraint structures.
3783: */
3784: static void
3785: xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3786: {
3787: xmlSchemaWildcardNsPtr next;
3788:
3789: while (set != NULL) {
3790: next = set->next;
3791: xmlFree(set);
3792: set = next;
3793: }
3794: }
3795:
3796: /**
3797: * xmlSchemaFreeWildcard:
3798: * @wildcard: a wildcard structure
3799: *
3800: * Deallocates a wildcard structure.
3801: */
3802: void
3803: xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3804: {
3805: if (wildcard == NULL)
3806: return;
3807: if (wildcard->annot != NULL)
3808: xmlSchemaFreeAnnot(wildcard->annot);
3809: if (wildcard->nsSet != NULL)
3810: xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3811: if (wildcard->negNsSet != NULL)
3812: xmlFree(wildcard->negNsSet);
3813: xmlFree(wildcard);
3814: }
3815:
3816: /**
3817: * xmlSchemaFreeAttributeGroup:
3818: * @schema: a schema attribute group structure
3819: *
3820: * Deallocate a Schema Attribute Group structure.
3821: */
3822: static void
3823: xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3824: {
3825: if (attrGr == NULL)
3826: return;
3827: if (attrGr->annot != NULL)
3828: xmlSchemaFreeAnnot(attrGr->annot);
3829: if (attrGr->attrUses != NULL)
3830: xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3831: xmlFree(attrGr);
3832: }
3833:
3834: /**
3835: * xmlSchemaFreeQNameRef:
3836: * @item: a QName reference structure
3837: *
3838: * Deallocatea a QName reference structure.
3839: */
3840: static void
3841: xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3842: {
3843: xmlFree(item);
3844: }
3845:
3846: /**
3847: * xmlSchemaFreeTypeLinkList:
3848: * @alink: a type link
3849: *
3850: * Deallocate a list of types.
3851: */
3852: static void
3853: xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3854: {
3855: xmlSchemaTypeLinkPtr next;
3856:
3857: while (link != NULL) {
3858: next = link->next;
3859: xmlFree(link);
3860: link = next;
3861: }
3862: }
3863:
3864: static void
3865: xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3866: {
3867: xmlSchemaIDCStateObjPtr next;
3868: while (sto != NULL) {
3869: next = sto->next;
3870: if (sto->history != NULL)
3871: xmlFree(sto->history);
3872: if (sto->xpathCtxt != NULL)
3873: xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3874: xmlFree(sto);
3875: sto = next;
3876: }
3877: }
3878:
3879: /**
3880: * xmlSchemaFreeIDC:
3881: * @idc: a identity-constraint definition
3882: *
3883: * Deallocates an identity-constraint definition.
3884: */
3885: static void
3886: xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3887: {
3888: xmlSchemaIDCSelectPtr cur, prev;
3889:
3890: if (idcDef == NULL)
3891: return;
3892: if (idcDef->annot != NULL)
3893: xmlSchemaFreeAnnot(idcDef->annot);
3894: /* Selector */
3895: if (idcDef->selector != NULL) {
3896: if (idcDef->selector->xpathComp != NULL)
3897: xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3898: xmlFree(idcDef->selector);
3899: }
3900: /* Fields */
3901: if (idcDef->fields != NULL) {
3902: cur = idcDef->fields;
3903: do {
3904: prev = cur;
3905: cur = cur->next;
3906: if (prev->xpathComp != NULL)
3907: xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3908: xmlFree(prev);
3909: } while (cur != NULL);
3910: }
3911: xmlFree(idcDef);
3912: }
3913:
3914: /**
3915: * xmlSchemaFreeElement:
3916: * @schema: a schema element structure
3917: *
3918: * Deallocate a Schema Element structure.
3919: */
3920: static void
3921: xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3922: {
3923: if (elem == NULL)
3924: return;
3925: if (elem->annot != NULL)
3926: xmlSchemaFreeAnnot(elem->annot);
3927: if (elem->contModel != NULL)
3928: xmlRegFreeRegexp(elem->contModel);
3929: if (elem->defVal != NULL)
3930: xmlSchemaFreeValue(elem->defVal);
3931: xmlFree(elem);
3932: }
3933:
3934: /**
3935: * xmlSchemaFreeFacet:
3936: * @facet: a schema facet structure
3937: *
3938: * Deallocate a Schema Facet structure.
3939: */
3940: void
3941: xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3942: {
3943: if (facet == NULL)
3944: return;
3945: if (facet->val != NULL)
3946: xmlSchemaFreeValue(facet->val);
3947: if (facet->regexp != NULL)
3948: xmlRegFreeRegexp(facet->regexp);
3949: if (facet->annot != NULL)
3950: xmlSchemaFreeAnnot(facet->annot);
3951: xmlFree(facet);
3952: }
3953:
3954: /**
3955: * xmlSchemaFreeType:
3956: * @type: a schema type structure
3957: *
3958: * Deallocate a Schema Type structure.
3959: */
3960: void
3961: xmlSchemaFreeType(xmlSchemaTypePtr type)
3962: {
3963: if (type == NULL)
3964: return;
3965: if (type->annot != NULL)
3966: xmlSchemaFreeAnnot(type->annot);
3967: if (type->facets != NULL) {
3968: xmlSchemaFacetPtr facet, next;
3969:
3970: facet = type->facets;
3971: while (facet != NULL) {
3972: next = facet->next;
3973: xmlSchemaFreeFacet(facet);
3974: facet = next;
3975: }
3976: }
3977: if (type->attrUses != NULL)
3978: xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
3979: if (type->memberTypes != NULL)
3980: xmlSchemaFreeTypeLinkList(type->memberTypes);
3981: if (type->facetSet != NULL) {
3982: xmlSchemaFacetLinkPtr next, link;
3983:
3984: link = type->facetSet;
3985: do {
3986: next = link->next;
3987: xmlFree(link);
3988: link = next;
3989: } while (link != NULL);
3990: }
3991: if (type->contModel != NULL)
3992: xmlRegFreeRegexp(type->contModel);
3993: xmlFree(type);
3994: }
3995:
3996: /**
3997: * xmlSchemaFreeModelGroupDef:
3998: * @item: a schema model group definition
3999: *
4000: * Deallocates a schema model group definition.
4001: */
4002: static void
4003: xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4004: {
4005: if (item->annot != NULL)
4006: xmlSchemaFreeAnnot(item->annot);
4007: xmlFree(item);
4008: }
4009:
4010: /**
4011: * xmlSchemaFreeModelGroup:
4012: * @item: a schema model group
4013: *
4014: * Deallocates a schema model group structure.
4015: */
4016: static void
4017: xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4018: {
4019: if (item->annot != NULL)
4020: xmlSchemaFreeAnnot(item->annot);
4021: xmlFree(item);
4022: }
4023:
4024: static void
4025: xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4026: {
4027: if ((list == NULL) || (list->nbItems == 0))
4028: return;
4029: {
4030: xmlSchemaTreeItemPtr item;
4031: xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4032: int i;
4033:
4034: for (i = 0; i < list->nbItems; i++) {
4035: item = items[i];
4036: if (item == NULL)
4037: continue;
4038: switch (item->type) {
4039: case XML_SCHEMA_TYPE_SIMPLE:
4040: case XML_SCHEMA_TYPE_COMPLEX:
4041: xmlSchemaFreeType((xmlSchemaTypePtr) item);
4042: break;
4043: case XML_SCHEMA_TYPE_ATTRIBUTE:
4044: xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4045: break;
4046: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4047: xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4048: break;
4049: case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4050: xmlSchemaFreeAttributeUseProhib(
4051: (xmlSchemaAttributeUseProhibPtr) item);
4052: break;
4053: case XML_SCHEMA_TYPE_ELEMENT:
4054: xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4055: break;
4056: case XML_SCHEMA_TYPE_PARTICLE:
4057: if (item->annot != NULL)
4058: xmlSchemaFreeAnnot(item->annot);
4059: xmlFree(item);
4060: break;
4061: case XML_SCHEMA_TYPE_SEQUENCE:
4062: case XML_SCHEMA_TYPE_CHOICE:
4063: case XML_SCHEMA_TYPE_ALL:
4064: xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4065: break;
4066: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4067: xmlSchemaFreeAttributeGroup(
4068: (xmlSchemaAttributeGroupPtr) item);
4069: break;
4070: case XML_SCHEMA_TYPE_GROUP:
4071: xmlSchemaFreeModelGroupDef(
4072: (xmlSchemaModelGroupDefPtr) item);
4073: break;
4074: case XML_SCHEMA_TYPE_ANY:
4075: case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4076: xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4077: break;
4078: case XML_SCHEMA_TYPE_IDC_KEY:
4079: case XML_SCHEMA_TYPE_IDC_UNIQUE:
4080: case XML_SCHEMA_TYPE_IDC_KEYREF:
4081: xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4082: break;
4083: case XML_SCHEMA_TYPE_NOTATION:
4084: xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4085: break;
4086: case XML_SCHEMA_EXTRA_QNAMEREF:
4087: xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4088: break;
4089: default: {
4090: /* TODO: This should never be hit. */
4091: xmlSchemaPSimpleInternalErr(NULL,
4092: "Internal error: xmlSchemaComponentListFree, "
4093: "unexpected component type '%s'\n",
4094: (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4095: }
4096: break;
4097: }
4098: }
4099: list->nbItems = 0;
4100: }
4101: }
4102:
4103: /**
4104: * xmlSchemaFree:
4105: * @schema: a schema structure
4106: *
4107: * Deallocate a Schema structure.
4108: */
4109: void
4110: xmlSchemaFree(xmlSchemaPtr schema)
4111: {
4112: if (schema == NULL)
4113: return;
4114: /* @volatiles is not used anymore :-/ */
4115: if (schema->volatiles != NULL)
4116: TODO
4117: /*
4118: * Note that those slots are not responsible for freeing
4119: * schema components anymore; this will now be done by
4120: * the schema buckets.
4121: */
4122: if (schema->notaDecl != NULL)
4123: xmlHashFree(schema->notaDecl, NULL);
4124: if (schema->attrDecl != NULL)
4125: xmlHashFree(schema->attrDecl, NULL);
4126: if (schema->attrgrpDecl != NULL)
4127: xmlHashFree(schema->attrgrpDecl, NULL);
4128: if (schema->elemDecl != NULL)
4129: xmlHashFree(schema->elemDecl, NULL);
4130: if (schema->typeDecl != NULL)
4131: xmlHashFree(schema->typeDecl, NULL);
4132: if (schema->groupDecl != NULL)
4133: xmlHashFree(schema->groupDecl, NULL);
4134: if (schema->idcDef != NULL)
4135: xmlHashFree(schema->idcDef, NULL);
4136:
4137: if (schema->schemasImports != NULL)
4138: xmlHashFree(schema->schemasImports,
4139: (xmlHashDeallocator) xmlSchemaBucketFree);
4140: if (schema->includes != NULL) {
4141: xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4142: int i;
4143: for (i = 0; i < list->nbItems; i++) {
4144: xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4145: }
4146: xmlSchemaItemListFree(list);
4147: }
4148: if (schema->annot != NULL)
4149: xmlSchemaFreeAnnot(schema->annot);
4150: /* Never free the doc here, since this will be done by the buckets. */
4151:
4152: xmlDictFree(schema->dict);
4153: xmlFree(schema);
4154: }
4155:
4156: /************************************************************************
1.1.1.3 ! misho 4157: * *
! 4158: * Debug functions *
! 4159: * *
1.1 misho 4160: ************************************************************************/
4161:
4162: #ifdef LIBXML_OUTPUT_ENABLED
4163:
4164: static void
4165: xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4166:
4167: /**
4168: * xmlSchemaElementDump:
4169: * @elem: an element
4170: * @output: the file output
4171: *
4172: * Dump the element
4173: */
4174: static void
4175: xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
4176: const xmlChar * name ATTRIBUTE_UNUSED,
4177: const xmlChar * namespace ATTRIBUTE_UNUSED,
4178: const xmlChar * context ATTRIBUTE_UNUSED)
4179: {
4180: if (elem == NULL)
4181: return;
4182:
4183:
4184: fprintf(output, "Element");
4185: if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4186: fprintf(output, " (global)");
4187: fprintf(output, ": '%s' ", elem->name);
4188: if (namespace != NULL)
4189: fprintf(output, "ns '%s'", namespace);
4190: fprintf(output, "\n");
4191: #if 0
4192: if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4193: fprintf(output, " min %d ", elem->minOccurs);
4194: if (elem->maxOccurs >= UNBOUNDED)
4195: fprintf(output, "max: unbounded\n");
4196: else if (elem->maxOccurs != 1)
4197: fprintf(output, "max: %d\n", elem->maxOccurs);
4198: else
4199: fprintf(output, "\n");
4200: }
4201: #endif
4202: /*
4203: * Misc other properties.
4204: */
4205: if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4206: (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4207: (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4208: (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4209: fprintf(output, " props: ");
4210: if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4211: fprintf(output, "[fixed] ");
4212: if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4213: fprintf(output, "[default] ");
4214: if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4215: fprintf(output, "[abstract] ");
4216: if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4217: fprintf(output, "[nillable] ");
4218: fprintf(output, "\n");
4219: }
4220: /*
4221: * Default/fixed value.
4222: */
4223: if (elem->value != NULL)
4224: fprintf(output, " value: '%s'\n", elem->value);
4225: /*
4226: * Type.
4227: */
4228: if (elem->namedType != NULL) {
4229: fprintf(output, " type: '%s' ", elem->namedType);
4230: if (elem->namedTypeNs != NULL)
4231: fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4232: else
4233: fprintf(output, "\n");
4234: } else if (elem->subtypes != NULL) {
4235: /*
4236: * Dump local types.
4237: */
4238: xmlSchemaTypeDump(elem->subtypes, output);
4239: }
4240: /*
4241: * Substitution group.
4242: */
4243: if (elem->substGroup != NULL) {
4244: fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
4245: if (elem->substGroupNs != NULL)
4246: fprintf(output, "ns '%s'\n", elem->substGroupNs);
4247: else
4248: fprintf(output, "\n");
4249: }
4250: }
4251:
4252: /**
4253: * xmlSchemaAnnotDump:
4254: * @output: the file output
4255: * @annot: a annotation
4256: *
4257: * Dump the annotation
4258: */
4259: static void
4260: xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4261: {
4262: xmlChar *content;
4263:
4264: if (annot == NULL)
4265: return;
4266:
4267: content = xmlNodeGetContent(annot->content);
4268: if (content != NULL) {
4269: fprintf(output, " Annot: %s\n", content);
4270: xmlFree(content);
4271: } else
4272: fprintf(output, " Annot: empty\n");
4273: }
4274:
4275: /**
4276: * xmlSchemaContentModelDump:
4277: * @particle: the schema particle
4278: * @output: the file output
4279: * @depth: the depth used for intentation
4280: *
4281: * Dump a SchemaType structure
4282: */
4283: static void
4284: xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4285: {
4286: xmlChar *str = NULL;
4287: xmlSchemaTreeItemPtr term;
4288: char shift[100];
4289: int i;
4290:
4291: if (particle == NULL)
4292: return;
4293: for (i = 0;((i < depth) && (i < 25));i++)
4294: shift[2 * i] = shift[2 * i + 1] = ' ';
4295: shift[2 * i] = shift[2 * i + 1] = 0;
4296: fprintf(output, "%s", shift);
4297: if (particle->children == NULL) {
4298: fprintf(output, "MISSING particle term\n");
4299: return;
4300: }
4301: term = particle->children;
4302: if (term == NULL) {
4303: fprintf(output, "(NULL)");
4304: } else {
4305: switch (term->type) {
4306: case XML_SCHEMA_TYPE_ELEMENT:
4307: fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4308: ((xmlSchemaElementPtr)term)->targetNamespace,
4309: ((xmlSchemaElementPtr)term)->name));
4310: FREE_AND_NULL(str);
4311: break;
4312: case XML_SCHEMA_TYPE_SEQUENCE:
4313: fprintf(output, "SEQUENCE");
4314: break;
4315: case XML_SCHEMA_TYPE_CHOICE:
4316: fprintf(output, "CHOICE");
4317: break;
4318: case XML_SCHEMA_TYPE_ALL:
4319: fprintf(output, "ALL");
4320: break;
4321: case XML_SCHEMA_TYPE_ANY:
4322: fprintf(output, "ANY");
4323: break;
4324: default:
4325: fprintf(output, "UNKNOWN\n");
4326: return;
4327: }
4328: }
4329: if (particle->minOccurs != 1)
4330: fprintf(output, " min: %d", particle->minOccurs);
4331: if (particle->maxOccurs >= UNBOUNDED)
4332: fprintf(output, " max: unbounded");
4333: else if (particle->maxOccurs != 1)
4334: fprintf(output, " max: %d", particle->maxOccurs);
4335: fprintf(output, "\n");
4336: if (term &&
4337: ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4338: (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4339: (term->type == XML_SCHEMA_TYPE_ALL)) &&
4340: (term->children != NULL)) {
4341: xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4342: output, depth +1);
4343: }
4344: if (particle->next != NULL)
4345: xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4346: output, depth);
4347: }
4348:
4349: /**
4350: * xmlSchemaAttrUsesDump:
4351: * @uses: attribute uses list
4352: * @output: the file output
4353: *
4354: * Dumps a list of attribute use components.
4355: */
4356: static void
4357: xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4358: {
4359: xmlSchemaAttributeUsePtr use;
4360: xmlSchemaAttributeUseProhibPtr prohib;
4361: xmlSchemaQNameRefPtr ref;
4362: const xmlChar *name, *tns;
4363: xmlChar *str = NULL;
4364: int i;
4365:
4366: if ((uses == NULL) || (uses->nbItems == 0))
4367: return;
4368:
4369: fprintf(output, " attributes:\n");
4370: for (i = 0; i < uses->nbItems; i++) {
4371: use = uses->items[i];
4372: if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4373: fprintf(output, " [prohibition] ");
4374: prohib = (xmlSchemaAttributeUseProhibPtr) use;
4375: name = prohib->name;
4376: tns = prohib->targetNamespace;
4377: } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4378: fprintf(output, " [reference] ");
4379: ref = (xmlSchemaQNameRefPtr) use;
4380: name = ref->name;
4381: tns = ref->targetNamespace;
4382: } else {
4383: fprintf(output, " [use] ");
4384: name = WXS_ATTRUSE_DECL_NAME(use);
4385: tns = WXS_ATTRUSE_DECL_TNS(use);
4386: }
4387: fprintf(output, "'%s'\n",
4388: (const char *) xmlSchemaFormatQName(&str, tns, name));
4389: FREE_AND_NULL(str);
4390: }
4391: }
4392:
4393: /**
4394: * xmlSchemaTypeDump:
4395: * @output: the file output
4396: * @type: a type structure
4397: *
4398: * Dump a SchemaType structure
4399: */
4400: static void
4401: xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4402: {
4403: if (type == NULL) {
4404: fprintf(output, "Type: NULL\n");
4405: return;
4406: }
4407: fprintf(output, "Type: ");
4408: if (type->name != NULL)
4409: fprintf(output, "'%s' ", type->name);
4410: else
4411: fprintf(output, "(no name) ");
4412: if (type->targetNamespace != NULL)
4413: fprintf(output, "ns '%s' ", type->targetNamespace);
4414: switch (type->type) {
4415: case XML_SCHEMA_TYPE_BASIC:
4416: fprintf(output, "[basic] ");
4417: break;
4418: case XML_SCHEMA_TYPE_SIMPLE:
4419: fprintf(output, "[simple] ");
4420: break;
4421: case XML_SCHEMA_TYPE_COMPLEX:
4422: fprintf(output, "[complex] ");
4423: break;
4424: case XML_SCHEMA_TYPE_SEQUENCE:
4425: fprintf(output, "[sequence] ");
4426: break;
4427: case XML_SCHEMA_TYPE_CHOICE:
4428: fprintf(output, "[choice] ");
4429: break;
4430: case XML_SCHEMA_TYPE_ALL:
4431: fprintf(output, "[all] ");
4432: break;
4433: case XML_SCHEMA_TYPE_UR:
4434: fprintf(output, "[ur] ");
4435: break;
4436: case XML_SCHEMA_TYPE_RESTRICTION:
4437: fprintf(output, "[restriction] ");
4438: break;
4439: case XML_SCHEMA_TYPE_EXTENSION:
4440: fprintf(output, "[extension] ");
4441: break;
4442: default:
4443: fprintf(output, "[unknown type %d] ", type->type);
4444: break;
4445: }
4446: fprintf(output, "content: ");
4447: switch (type->contentType) {
4448: case XML_SCHEMA_CONTENT_UNKNOWN:
4449: fprintf(output, "[unknown] ");
4450: break;
4451: case XML_SCHEMA_CONTENT_EMPTY:
4452: fprintf(output, "[empty] ");
4453: break;
4454: case XML_SCHEMA_CONTENT_ELEMENTS:
4455: fprintf(output, "[element] ");
4456: break;
4457: case XML_SCHEMA_CONTENT_MIXED:
4458: fprintf(output, "[mixed] ");
4459: break;
4460: case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4461: /* not used. */
4462: break;
4463: case XML_SCHEMA_CONTENT_BASIC:
4464: fprintf(output, "[basic] ");
4465: break;
4466: case XML_SCHEMA_CONTENT_SIMPLE:
4467: fprintf(output, "[simple] ");
4468: break;
4469: case XML_SCHEMA_CONTENT_ANY:
4470: fprintf(output, "[any] ");
4471: break;
4472: }
4473: fprintf(output, "\n");
4474: if (type->base != NULL) {
4475: fprintf(output, " base type: '%s'", type->base);
4476: if (type->baseNs != NULL)
4477: fprintf(output, " ns '%s'\n", type->baseNs);
4478: else
4479: fprintf(output, "\n");
4480: }
4481: if (type->attrUses != NULL)
4482: xmlSchemaAttrUsesDump(type->attrUses, output);
4483: if (type->annot != NULL)
4484: xmlSchemaAnnotDump(output, type->annot);
4485: #ifdef DUMP_CONTENT_MODEL
4486: if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4487: (type->subtypes != NULL)) {
4488: xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4489: output, 1);
4490: }
4491: #endif
4492: }
4493:
4494: /**
4495: * xmlSchemaDump:
4496: * @output: the file output
4497: * @schema: a schema structure
4498: *
4499: * Dump a Schema structure.
4500: */
4501: void
4502: xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4503: {
4504: if (output == NULL)
4505: return;
4506: if (schema == NULL) {
4507: fprintf(output, "Schemas: NULL\n");
4508: return;
4509: }
4510: fprintf(output, "Schemas: ");
4511: if (schema->name != NULL)
4512: fprintf(output, "%s, ", schema->name);
4513: else
4514: fprintf(output, "no name, ");
4515: if (schema->targetNamespace != NULL)
4516: fprintf(output, "%s", (const char *) schema->targetNamespace);
4517: else
4518: fprintf(output, "no target namespace");
4519: fprintf(output, "\n");
4520: if (schema->annot != NULL)
4521: xmlSchemaAnnotDump(output, schema->annot);
4522: xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4523: output);
4524: xmlHashScanFull(schema->elemDecl,
4525: (xmlHashScannerFull) xmlSchemaElementDump, output);
4526: }
4527:
4528: #ifdef DEBUG_IDC_NODE_TABLE
4529: /**
4530: * xmlSchemaDebugDumpIDCTable:
4531: * @vctxt: the WXS validation context
4532: *
4533: * Displays the current IDC table for debug purposes.
4534: */
4535: static void
4536: xmlSchemaDebugDumpIDCTable(FILE * output,
4537: const xmlChar *namespaceName,
4538: const xmlChar *localName,
4539: xmlSchemaPSVIIDCBindingPtr bind)
4540: {
4541: xmlChar *str = NULL;
4542: const xmlChar *value;
4543: xmlSchemaPSVIIDCNodePtr tab;
4544: xmlSchemaPSVIIDCKeyPtr key;
4545: int i, j, res;
4546:
4547: fprintf(output, "IDC: TABLES on '%s'\n",
4548: xmlSchemaFormatQName(&str, namespaceName, localName));
4549: FREE_AND_NULL(str)
4550:
4551: if (bind == NULL)
4552: return;
4553: do {
4554: fprintf(output, "IDC: BINDING '%s' (%d)\n",
4555: xmlSchemaGetComponentQName(&str,
4556: bind->definition), bind->nbNodes);
4557: FREE_AND_NULL(str)
4558: for (i = 0; i < bind->nbNodes; i++) {
4559: tab = bind->nodeTable[i];
4560: fprintf(output, " ( ");
4561: for (j = 0; j < bind->definition->nbFields; j++) {
4562: key = tab->keys[j];
4563: if ((key != NULL) && (key->val != NULL)) {
4564: res = xmlSchemaGetCanonValue(key->val, &value);
4565: if (res >= 0)
4566: fprintf(output, "'%s' ", value);
4567: else
4568: fprintf(output, "CANON-VALUE-FAILED ");
4569: if (res == 0)
4570: FREE_AND_NULL(value)
4571: } else if (key != NULL)
4572: fprintf(output, "(no val), ");
4573: else
4574: fprintf(output, "(key missing), ");
4575: }
4576: fprintf(output, ")\n");
4577: }
4578: if (bind->dupls && bind->dupls->nbItems) {
4579: fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
4580: for (i = 0; i < bind->dupls->nbItems; i++) {
4581: tab = bind->dupls->items[i];
4582: fprintf(output, " ( ");
4583: for (j = 0; j < bind->definition->nbFields; j++) {
4584: key = tab->keys[j];
4585: if ((key != NULL) && (key->val != NULL)) {
4586: res = xmlSchemaGetCanonValue(key->val, &value);
4587: if (res >= 0)
4588: fprintf(output, "'%s' ", value);
4589: else
4590: fprintf(output, "CANON-VALUE-FAILED ");
4591: if (res == 0)
4592: FREE_AND_NULL(value)
4593: } else if (key != NULL)
4594: fprintf(output, "(no val), ");
4595: else
4596: fprintf(output, "(key missing), ");
4597: }
4598: fprintf(output, ")\n");
4599: }
4600: }
4601: bind = bind->next;
4602: } while (bind != NULL);
4603: }
4604: #endif /* DEBUG_IDC */
4605: #endif /* LIBXML_OUTPUT_ENABLED */
4606:
4607: /************************************************************************
4608: * *
1.1.1.3 ! misho 4609: * Utilities *
1.1 misho 4610: * *
4611: ************************************************************************/
4612:
4613: /**
4614: * xmlSchemaGetPropNode:
4615: * @node: the element node
4616: * @name: the name of the attribute
4617: *
4618: * Seeks an attribute with a name of @name in
4619: * no namespace.
4620: *
4621: * Returns the attribute or NULL if not present.
4622: */
4623: static xmlAttrPtr
4624: xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4625: {
4626: xmlAttrPtr prop;
4627:
4628: if ((node == NULL) || (name == NULL))
4629: return(NULL);
4630: prop = node->properties;
4631: while (prop != NULL) {
4632: if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4633: return(prop);
4634: prop = prop->next;
4635: }
4636: return (NULL);
4637: }
4638:
4639: /**
4640: * xmlSchemaGetPropNodeNs:
4641: * @node: the element node
4642: * @uri: the uri
4643: * @name: the name of the attribute
4644: *
4645: * Seeks an attribute with a local name of @name and
4646: * a namespace URI of @uri.
4647: *
4648: * Returns the attribute or NULL if not present.
4649: */
4650: static xmlAttrPtr
4651: xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4652: {
4653: xmlAttrPtr prop;
4654:
4655: if ((node == NULL) || (name == NULL))
4656: return(NULL);
4657: prop = node->properties;
4658: while (prop != NULL) {
4659: if ((prop->ns != NULL) &&
4660: xmlStrEqual(prop->name, BAD_CAST name) &&
4661: xmlStrEqual(prop->ns->href, BAD_CAST uri))
4662: return(prop);
4663: prop = prop->next;
4664: }
4665: return (NULL);
4666: }
4667:
4668: static const xmlChar *
4669: xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4670: {
4671: xmlChar *val;
4672: const xmlChar *ret;
4673:
4674: val = xmlNodeGetContent(node);
4675: if (val == NULL)
4676: val = xmlStrdup((xmlChar *)"");
4677: ret = xmlDictLookup(ctxt->dict, val, -1);
4678: xmlFree(val);
4679: return(ret);
4680: }
4681:
4682: static const xmlChar *
4683: xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4684: {
4685: return((const xmlChar*) xmlNodeGetContent(node));
4686: }
4687:
4688: /**
4689: * xmlSchemaGetProp:
4690: * @ctxt: the parser context
4691: * @node: the node
4692: * @name: the property name
4693: *
4694: * Read a attribute value and internalize the string
4695: *
4696: * Returns the string or NULL if not present.
4697: */
4698: static const xmlChar *
4699: xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4700: const char *name)
4701: {
4702: xmlChar *val;
4703: const xmlChar *ret;
4704:
4705: val = xmlGetNoNsProp(node, BAD_CAST name);
4706: if (val == NULL)
4707: return(NULL);
4708: ret = xmlDictLookup(ctxt->dict, val, -1);
4709: xmlFree(val);
4710: return(ret);
4711: }
4712:
4713: /************************************************************************
1.1.1.3 ! misho 4714: * *
! 4715: * Parsing functions *
! 4716: * *
1.1 misho 4717: ************************************************************************/
4718:
4719: #define WXS_FIND_GLOBAL_ITEM(slot) \
4720: if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4721: ret = xmlHashLookup(schema->slot, name); \
4722: if (ret != NULL) goto exit; \
4723: } \
4724: if (xmlHashSize(schema->schemasImports) > 1) { \
4725: xmlSchemaImportPtr import; \
4726: if (nsName == NULL) \
4727: import = xmlHashLookup(schema->schemasImports, \
4728: XML_SCHEMAS_NO_NAMESPACE); \
4729: else \
4730: import = xmlHashLookup(schema->schemasImports, nsName); \
4731: if (import == NULL) \
4732: goto exit; \
4733: ret = xmlHashLookup(import->schema->slot, name); \
4734: }
4735:
4736: /**
4737: * xmlSchemaGetElem:
4738: * @schema: the schema context
4739: * @name: the element name
4740: * @ns: the element namespace
4741: *
4742: * Lookup a global element declaration in the schema.
4743: *
4744: * Returns the element declaration or NULL if not found.
4745: */
4746: static xmlSchemaElementPtr
4747: xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4748: const xmlChar * nsName)
4749: {
4750: xmlSchemaElementPtr ret = NULL;
4751:
4752: if ((name == NULL) || (schema == NULL))
4753: return(NULL);
4754: if (schema != NULL) {
4755: WXS_FIND_GLOBAL_ITEM(elemDecl)
4756: }
4757: exit:
4758: #ifdef DEBUG
4759: if (ret == NULL) {
4760: if (nsName == NULL)
4761: fprintf(stderr, "Unable to lookup element decl. %s", name);
4762: else
4763: fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4764: nsName);
4765: }
4766: #endif
4767: return (ret);
4768: }
4769:
4770: /**
4771: * xmlSchemaGetType:
4772: * @schema: the main schema
4773: * @name: the type's name
4774: * nsName: the type's namespace
4775: *
4776: * Lookup a type in the schemas or the predefined types
4777: *
4778: * Returns the group definition or NULL if not found.
4779: */
4780: static xmlSchemaTypePtr
4781: xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4782: const xmlChar * nsName)
4783: {
4784: xmlSchemaTypePtr ret = NULL;
4785:
4786: if (name == NULL)
4787: return (NULL);
4788: /* First try the built-in types. */
4789: if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4790: ret = xmlSchemaGetPredefinedType(name, nsName);
4791: if (ret != NULL)
4792: goto exit;
4793: /*
4794: * Note that we try the parsed schemas as well here
4795: * since one might have parsed the S4S, which contain more
4796: * than the built-in types.
4797: * TODO: Can we optimize this?
4798: */
4799: }
4800: if (schema != NULL) {
4801: WXS_FIND_GLOBAL_ITEM(typeDecl)
4802: }
4803: exit:
4804:
4805: #ifdef DEBUG
4806: if (ret == NULL) {
4807: if (nsName == NULL)
4808: fprintf(stderr, "Unable to lookup type %s", name);
4809: else
4810: fprintf(stderr, "Unable to lookup type %s:%s", name,
4811: nsName);
4812: }
4813: #endif
4814: return (ret);
4815: }
4816:
4817: /**
4818: * xmlSchemaGetAttributeDecl:
4819: * @schema: the context of the schema
4820: * @name: the name of the attribute
4821: * @ns: the target namespace of the attribute
4822: *
4823: * Lookup a an attribute in the schema or imported schemas
4824: *
4825: * Returns the attribute declaration or NULL if not found.
4826: */
4827: static xmlSchemaAttributePtr
4828: xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4829: const xmlChar * nsName)
4830: {
4831: xmlSchemaAttributePtr ret = NULL;
4832:
4833: if ((name == NULL) || (schema == NULL))
4834: return (NULL);
4835: if (schema != NULL) {
4836: WXS_FIND_GLOBAL_ITEM(attrDecl)
4837: }
4838: exit:
4839: #ifdef DEBUG
4840: if (ret == NULL) {
4841: if (nsName == NULL)
4842: fprintf(stderr, "Unable to lookup attribute %s", name);
4843: else
4844: fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4845: nsName);
4846: }
4847: #endif
4848: return (ret);
4849: }
4850:
4851: /**
4852: * xmlSchemaGetAttributeGroup:
4853: * @schema: the context of the schema
4854: * @name: the name of the attribute group
4855: * @ns: the target namespace of the attribute group
4856: *
4857: * Lookup a an attribute group in the schema or imported schemas
4858: *
4859: * Returns the attribute group definition or NULL if not found.
4860: */
4861: static xmlSchemaAttributeGroupPtr
4862: xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4863: const xmlChar * nsName)
4864: {
4865: xmlSchemaAttributeGroupPtr ret = NULL;
4866:
4867: if ((name == NULL) || (schema == NULL))
4868: return (NULL);
4869: if (schema != NULL) {
4870: WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4871: }
4872: exit:
4873: /* TODO:
4874: if ((ret != NULL) && (ret->redef != NULL)) {
4875: * Return the last redefinition. *
4876: ret = ret->redef;
4877: }
4878: */
4879: #ifdef DEBUG
4880: if (ret == NULL) {
4881: if (nsName == NULL)
4882: fprintf(stderr, "Unable to lookup attribute group %s", name);
4883: else
4884: fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4885: nsName);
4886: }
4887: #endif
4888: return (ret);
4889: }
4890:
4891: /**
4892: * xmlSchemaGetGroup:
4893: * @schema: the context of the schema
4894: * @name: the name of the group
4895: * @ns: the target namespace of the group
4896: *
4897: * Lookup a group in the schema or imported schemas
4898: *
4899: * Returns the group definition or NULL if not found.
4900: */
4901: static xmlSchemaModelGroupDefPtr
4902: xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4903: const xmlChar * nsName)
4904: {
4905: xmlSchemaModelGroupDefPtr ret = NULL;
4906:
4907: if ((name == NULL) || (schema == NULL))
4908: return (NULL);
4909: if (schema != NULL) {
4910: WXS_FIND_GLOBAL_ITEM(groupDecl)
4911: }
4912: exit:
4913:
4914: #ifdef DEBUG
4915: if (ret == NULL) {
4916: if (nsName == NULL)
4917: fprintf(stderr, "Unable to lookup group %s", name);
4918: else
4919: fprintf(stderr, "Unable to lookup group %s:%s", name,
4920: nsName);
4921: }
4922: #endif
4923: return (ret);
4924: }
4925:
4926: static xmlSchemaNotationPtr
4927: xmlSchemaGetNotation(xmlSchemaPtr schema,
4928: const xmlChar *name,
4929: const xmlChar *nsName)
4930: {
4931: xmlSchemaNotationPtr ret = NULL;
4932:
4933: if ((name == NULL) || (schema == NULL))
4934: return (NULL);
4935: if (schema != NULL) {
4936: WXS_FIND_GLOBAL_ITEM(notaDecl)
4937: }
4938: exit:
4939: return (ret);
4940: }
4941:
4942: static xmlSchemaIDCPtr
4943: xmlSchemaGetIDC(xmlSchemaPtr schema,
4944: const xmlChar *name,
4945: const xmlChar *nsName)
4946: {
4947: xmlSchemaIDCPtr ret = NULL;
4948:
4949: if ((name == NULL) || (schema == NULL))
4950: return (NULL);
4951: if (schema != NULL) {
4952: WXS_FIND_GLOBAL_ITEM(idcDef)
4953: }
4954: exit:
4955: return (ret);
4956: }
4957:
4958: /**
4959: * xmlSchemaGetNamedComponent:
4960: * @schema: the schema
4961: * @name: the name of the group
4962: * @ns: the target namespace of the group
4963: *
4964: * Lookup a group in the schema or imported schemas
4965: *
4966: * Returns the group definition or NULL if not found.
4967: */
4968: static xmlSchemaBasicItemPtr
4969: xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4970: xmlSchemaTypeType itemType,
4971: const xmlChar *name,
4972: const xmlChar *targetNs)
4973: {
4974: switch (itemType) {
4975: case XML_SCHEMA_TYPE_GROUP:
4976: return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4977: name, targetNs));
4978: case XML_SCHEMA_TYPE_ELEMENT:
4979: return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4980: name, targetNs));
4981: default:
4982: TODO
4983: return (NULL);
4984: }
4985: }
4986:
4987: /************************************************************************
1.1.1.3 ! misho 4988: * *
! 4989: * Parsing functions *
! 4990: * *
1.1 misho 4991: ************************************************************************/
4992:
4993: #define IS_BLANK_NODE(n) \
4994: (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4995:
4996: /**
4997: * xmlSchemaIsBlank:
4998: * @str: a string
4999: * @len: the length of the string or -1
5000: *
5001: * Check if a string is ignorable
5002: *
5003: * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5004: */
5005: static int
5006: xmlSchemaIsBlank(xmlChar * str, int len)
5007: {
5008: if (str == NULL)
5009: return (1);
5010: if (len < 0) {
5011: while (*str != 0) {
5012: if (!(IS_BLANK_CH(*str)))
5013: return (0);
5014: str++;
5015: }
5016: } else while ((*str != 0) && (len != 0)) {
5017: if (!(IS_BLANK_CH(*str)))
5018: return (0);
5019: str++;
5020: len--;
5021: }
5022:
5023: return (1);
5024: }
5025:
5026: #define WXS_COMP_NAME(c, t) ((t) (c))->name
5027: #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5028: /*
5029: * xmlSchemaFindRedefCompInGraph:
5030: * ATTENTION TODO: This uses pointer comp. for strings.
5031: */
5032: static xmlSchemaBasicItemPtr
5033: xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5034: xmlSchemaTypeType type,
5035: const xmlChar *name,
5036: const xmlChar *nsName)
5037: {
5038: xmlSchemaBasicItemPtr ret;
5039: int i;
5040:
5041: if ((bucket == NULL) || (name == NULL))
5042: return(NULL);
5043: if ((bucket->globals == NULL) ||
5044: (bucket->globals->nbItems == 0))
5045: goto subschemas;
5046: /*
5047: * Search in global components.
5048: */
5049: for (i = 0; i < bucket->globals->nbItems; i++) {
5050: ret = bucket->globals->items[i];
5051: if (ret->type == type) {
5052: switch (type) {
5053: case XML_SCHEMA_TYPE_COMPLEX:
5054: case XML_SCHEMA_TYPE_SIMPLE:
5055: if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5056: (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5057: nsName))
5058: {
5059: return(ret);
5060: }
5061: break;
5062: case XML_SCHEMA_TYPE_GROUP:
5063: if ((WXS_COMP_NAME(ret,
5064: xmlSchemaModelGroupDefPtr) == name) &&
5065: (WXS_COMP_TNS(ret,
5066: xmlSchemaModelGroupDefPtr) == nsName))
5067: {
5068: return(ret);
5069: }
5070: break;
5071: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5072: if ((WXS_COMP_NAME(ret,
5073: xmlSchemaAttributeGroupPtr) == name) &&
5074: (WXS_COMP_TNS(ret,
5075: xmlSchemaAttributeGroupPtr) == nsName))
5076: {
5077: return(ret);
5078: }
5079: break;
5080: default:
5081: /* Should not be hit. */
5082: return(NULL);
5083: }
5084: }
5085: }
5086: subschemas:
5087: /*
5088: * Process imported/included schemas.
5089: */
5090: if (bucket->relations != NULL) {
5091: xmlSchemaSchemaRelationPtr rel = bucket->relations;
5092:
5093: /*
5094: * TODO: Marking the bucket will not avoid multiple searches
5095: * in the same schema, but avoids at least circularity.
5096: */
5097: bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5098: do {
5099: if ((rel->bucket != NULL) &&
5100: ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5101: ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5102: type, name, nsName);
5103: if (ret != NULL)
5104: return(ret);
5105: }
5106: rel = rel->next;
5107: } while (rel != NULL);
5108: bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5109: }
5110: return(NULL);
5111: }
5112:
5113: /**
5114: * xmlSchemaAddNotation:
5115: * @ctxt: a schema parser context
5116: * @schema: the schema being built
5117: * @name: the item name
5118: *
5119: * Add an XML schema annotation declaration
5120: * *WARNING* this interface is highly subject to change
5121: *
5122: * Returns the new struture or NULL in case of error
5123: */
5124: static xmlSchemaNotationPtr
5125: xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5126: const xmlChar *name, const xmlChar *nsName,
5127: xmlNodePtr node ATTRIBUTE_UNUSED)
5128: {
5129: xmlSchemaNotationPtr ret = NULL;
5130:
5131: if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5132: return (NULL);
5133:
5134: ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5135: if (ret == NULL) {
5136: xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5137: return (NULL);
5138: }
5139: memset(ret, 0, sizeof(xmlSchemaNotation));
5140: ret->type = XML_SCHEMA_TYPE_NOTATION;
5141: ret->name = name;
5142: ret->targetNamespace = nsName;
5143: /* TODO: do we need the node to be set?
5144: * ret->node = node;*/
5145: WXS_ADD_GLOBAL(ctxt, ret);
5146: return (ret);
5147: }
5148:
5149: /**
5150: * xmlSchemaAddAttribute:
5151: * @ctxt: a schema parser context
5152: * @schema: the schema being built
5153: * @name: the item name
5154: * @namespace: the namespace
5155: *
5156: * Add an XML schema Attrribute declaration
5157: * *WARNING* this interface is highly subject to change
5158: *
5159: * Returns the new struture or NULL in case of error
5160: */
5161: static xmlSchemaAttributePtr
5162: xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5163: const xmlChar * name, const xmlChar * nsName,
5164: xmlNodePtr node, int topLevel)
5165: {
5166: xmlSchemaAttributePtr ret = NULL;
5167:
5168: if ((ctxt == NULL) || (schema == NULL))
5169: return (NULL);
5170:
5171: ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5172: if (ret == NULL) {
5173: xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5174: return (NULL);
5175: }
5176: memset(ret, 0, sizeof(xmlSchemaAttribute));
5177: ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5178: ret->node = node;
5179: ret->name = name;
5180: ret->targetNamespace = nsName;
5181:
5182: if (topLevel)
5183: WXS_ADD_GLOBAL(ctxt, ret);
5184: else
5185: WXS_ADD_LOCAL(ctxt, ret);
5186: WXS_ADD_PENDING(ctxt, ret);
5187: return (ret);
5188: }
5189:
5190: /**
5191: * xmlSchemaAddAttributeUse:
5192: * @ctxt: a schema parser context
5193: * @schema: the schema being built
5194: * @name: the item name
5195: * @namespace: the namespace
5196: *
5197: * Add an XML schema Attrribute declaration
5198: * *WARNING* this interface is highly subject to change
5199: *
5200: * Returns the new struture or NULL in case of error
5201: */
5202: static xmlSchemaAttributeUsePtr
5203: xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5204: xmlNodePtr node)
5205: {
5206: xmlSchemaAttributeUsePtr ret = NULL;
5207:
5208: if (pctxt == NULL)
5209: return (NULL);
5210:
5211: ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5212: if (ret == NULL) {
5213: xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5214: return (NULL);
5215: }
5216: memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5217: ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5218: ret->node = node;
5219:
5220: WXS_ADD_LOCAL(pctxt, ret);
5221: return (ret);
5222: }
5223:
5224: /*
5225: * xmlSchemaAddRedef:
5226: *
5227: * Adds a redefinition information. This is used at a later stage to:
5228: * resolve references to the redefined components and to check constraints.
5229: */
5230: static xmlSchemaRedefPtr
5231: xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5232: xmlSchemaBucketPtr targetBucket,
5233: void *item,
5234: const xmlChar *refName,
5235: const xmlChar *refTargetNs)
5236: {
5237: xmlSchemaRedefPtr ret;
5238:
5239: ret = (xmlSchemaRedefPtr)
5240: xmlMalloc(sizeof(xmlSchemaRedef));
5241: if (ret == NULL) {
5242: xmlSchemaPErrMemory(pctxt,
5243: "allocating redefinition info", NULL);
5244: return (NULL);
5245: }
5246: memset(ret, 0, sizeof(xmlSchemaRedef));
5247: ret->item = item;
5248: ret->targetBucket = targetBucket;
5249: ret->refName = refName;
5250: ret->refTargetNs = refTargetNs;
5251: if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5252: WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5253: else
5254: WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5255: WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5256:
5257: return (ret);
5258: }
5259:
5260: /**
5261: * xmlSchemaAddAttributeGroupDefinition:
5262: * @ctxt: a schema parser context
5263: * @schema: the schema being built
5264: * @name: the item name
5265: * @nsName: the target namespace
5266: * @node: the corresponding node
5267: *
5268: * Add an XML schema Attrribute Group definition.
5269: *
5270: * Returns the new struture or NULL in case of error
5271: */
5272: static xmlSchemaAttributeGroupPtr
5273: xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5274: xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5275: const xmlChar *name,
5276: const xmlChar *nsName,
5277: xmlNodePtr node)
5278: {
5279: xmlSchemaAttributeGroupPtr ret = NULL;
5280:
5281: if ((pctxt == NULL) || (name == NULL))
5282: return (NULL);
5283:
5284: ret = (xmlSchemaAttributeGroupPtr)
5285: xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5286: if (ret == NULL) {
5287: xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5288: return (NULL);
5289: }
5290: memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5291: ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5292: ret->name = name;
5293: ret->targetNamespace = nsName;
5294: ret->node = node;
5295:
5296: /* TODO: Remove the flag. */
5297: ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5298: if (pctxt->isRedefine) {
5299: pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5300: ret, name, nsName);
5301: if (pctxt->redef == NULL) {
5302: xmlFree(ret);
5303: return(NULL);
5304: }
5305: pctxt->redefCounter = 0;
5306: }
5307: WXS_ADD_GLOBAL(pctxt, ret);
5308: WXS_ADD_PENDING(pctxt, ret);
5309: return (ret);
5310: }
5311:
5312: /**
5313: * xmlSchemaAddElement:
5314: * @ctxt: a schema parser context
5315: * @schema: the schema being built
5316: * @name: the type name
5317: * @namespace: the type namespace
5318: *
5319: * Add an XML schema Element declaration
5320: * *WARNING* this interface is highly subject to change
5321: *
5322: * Returns the new struture or NULL in case of error
5323: */
5324: static xmlSchemaElementPtr
5325: xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5326: const xmlChar * name, const xmlChar * nsName,
5327: xmlNodePtr node, int topLevel)
5328: {
5329: xmlSchemaElementPtr ret = NULL;
5330:
5331: if ((ctxt == NULL) || (name == NULL))
5332: return (NULL);
5333:
5334: ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5335: if (ret == NULL) {
5336: xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5337: return (NULL);
5338: }
5339: memset(ret, 0, sizeof(xmlSchemaElement));
5340: ret->type = XML_SCHEMA_TYPE_ELEMENT;
5341: ret->name = name;
5342: ret->targetNamespace = nsName;
5343: ret->node = node;
5344:
5345: if (topLevel)
5346: WXS_ADD_GLOBAL(ctxt, ret);
5347: else
5348: WXS_ADD_LOCAL(ctxt, ret);
5349: WXS_ADD_PENDING(ctxt, ret);
5350: return (ret);
5351: }
5352:
5353: /**
5354: * xmlSchemaAddType:
5355: * @ctxt: a schema parser context
5356: * @schema: the schema being built
5357: * @name: the item name
5358: * @namespace: the namespace
5359: *
5360: * Add an XML schema item
5361: * *WARNING* this interface is highly subject to change
5362: *
5363: * Returns the new struture or NULL in case of error
5364: */
5365: static xmlSchemaTypePtr
5366: xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5367: xmlSchemaTypeType type,
5368: const xmlChar * name, const xmlChar * nsName,
5369: xmlNodePtr node, int topLevel)
5370: {
5371: xmlSchemaTypePtr ret = NULL;
5372:
5373: if ((ctxt == NULL) || (schema == NULL))
5374: return (NULL);
5375:
5376: ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5377: if (ret == NULL) {
5378: xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5379: return (NULL);
5380: }
5381: memset(ret, 0, sizeof(xmlSchemaType));
5382: ret->type = type;
5383: ret->name = name;
5384: ret->targetNamespace = nsName;
5385: ret->node = node;
5386: if (topLevel) {
5387: if (ctxt->isRedefine) {
5388: ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5389: ret, name, nsName);
5390: if (ctxt->redef == NULL) {
5391: xmlFree(ret);
5392: return(NULL);
5393: }
5394: ctxt->redefCounter = 0;
5395: }
5396: WXS_ADD_GLOBAL(ctxt, ret);
5397: } else
5398: WXS_ADD_LOCAL(ctxt, ret);
5399: WXS_ADD_PENDING(ctxt, ret);
5400: return (ret);
5401: }
5402:
5403: static xmlSchemaQNameRefPtr
5404: xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5405: xmlSchemaTypeType refType,
5406: const xmlChar *refName,
5407: const xmlChar *refNs)
5408: {
5409: xmlSchemaQNameRefPtr ret;
5410:
5411: ret = (xmlSchemaQNameRefPtr)
5412: xmlMalloc(sizeof(xmlSchemaQNameRef));
5413: if (ret == NULL) {
5414: xmlSchemaPErrMemory(pctxt,
5415: "allocating QName reference item", NULL);
5416: return (NULL);
5417: }
5418: ret->node = NULL;
5419: ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5420: ret->name = refName;
5421: ret->targetNamespace = refNs;
5422: ret->item = NULL;
5423: ret->itemType = refType;
5424: /*
5425: * Store the reference item in the schema.
5426: */
5427: WXS_ADD_LOCAL(pctxt, ret);
5428: return (ret);
5429: }
5430:
5431: static xmlSchemaAttributeUseProhibPtr
5432: xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5433: {
5434: xmlSchemaAttributeUseProhibPtr ret;
5435:
5436: ret = (xmlSchemaAttributeUseProhibPtr)
5437: xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5438: if (ret == NULL) {
5439: xmlSchemaPErrMemory(pctxt,
5440: "allocating attribute use prohibition", NULL);
5441: return (NULL);
5442: }
5443: memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5444: ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5445: WXS_ADD_LOCAL(pctxt, ret);
5446: return (ret);
5447: }
5448:
5449:
5450: /**
5451: * xmlSchemaAddModelGroup:
5452: * @ctxt: a schema parser context
5453: * @schema: the schema being built
5454: * @type: the "compositor" type of the model group
5455: * @node: the node in the schema doc
5456: *
5457: * Adds a schema model group
5458: * *WARNING* this interface is highly subject to change
5459: *
5460: * Returns the new struture or NULL in case of error
5461: */
5462: static xmlSchemaModelGroupPtr
5463: xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5464: xmlSchemaPtr schema,
5465: xmlSchemaTypeType type,
5466: xmlNodePtr node)
5467: {
5468: xmlSchemaModelGroupPtr ret = NULL;
5469:
5470: if ((ctxt == NULL) || (schema == NULL))
5471: return (NULL);
5472:
5473: ret = (xmlSchemaModelGroupPtr)
5474: xmlMalloc(sizeof(xmlSchemaModelGroup));
5475: if (ret == NULL) {
5476: xmlSchemaPErrMemory(ctxt, "allocating model group component",
5477: NULL);
5478: return (NULL);
5479: }
5480: memset(ret, 0, sizeof(xmlSchemaModelGroup));
5481: ret->type = type;
5482: ret->node = node;
5483: WXS_ADD_LOCAL(ctxt, ret);
5484: if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5485: (type == XML_SCHEMA_TYPE_CHOICE))
5486: WXS_ADD_PENDING(ctxt, ret);
5487: return (ret);
5488: }
5489:
5490:
5491: /**
5492: * xmlSchemaAddParticle:
5493: * @ctxt: a schema parser context
5494: * @schema: the schema being built
5495: * @node: the corresponding node in the schema doc
5496: * @min: the minOccurs
5497: * @max: the maxOccurs
5498: *
5499: * Adds an XML schema particle component.
5500: * *WARNING* this interface is highly subject to change
5501: *
5502: * Returns the new struture or NULL in case of error
5503: */
5504: static xmlSchemaParticlePtr
5505: xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5506: xmlNodePtr node, int min, int max)
5507: {
5508: xmlSchemaParticlePtr ret = NULL;
5509: if (ctxt == NULL)
5510: return (NULL);
5511:
5512: #ifdef DEBUG
5513: fprintf(stderr, "Adding particle component\n");
5514: #endif
5515: ret = (xmlSchemaParticlePtr)
5516: xmlMalloc(sizeof(xmlSchemaParticle));
5517: if (ret == NULL) {
5518: xmlSchemaPErrMemory(ctxt, "allocating particle component",
5519: NULL);
5520: return (NULL);
5521: }
5522: ret->type = XML_SCHEMA_TYPE_PARTICLE;
5523: ret->annot = NULL;
5524: ret->node = node;
5525: ret->minOccurs = min;
5526: ret->maxOccurs = max;
5527: ret->next = NULL;
5528: ret->children = NULL;
5529:
5530: WXS_ADD_LOCAL(ctxt, ret);
5531: /*
5532: * Note that addition to pending components will be done locally
5533: * to the specific parsing function, since the most particles
5534: * need not to be fixed up (i.e. the reference to be resolved).
5535: * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5536: */
5537: return (ret);
5538: }
5539:
5540: /**
5541: * xmlSchemaAddModelGroupDefinition:
5542: * @ctxt: a schema validation context
5543: * @schema: the schema being built
5544: * @name: the group name
5545: *
5546: * Add an XML schema Group definition
5547: *
5548: * Returns the new struture or NULL in case of error
5549: */
5550: static xmlSchemaModelGroupDefPtr
5551: xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5552: xmlSchemaPtr schema,
5553: const xmlChar *name,
5554: const xmlChar *nsName,
5555: xmlNodePtr node)
5556: {
5557: xmlSchemaModelGroupDefPtr ret = NULL;
5558:
5559: if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5560: return (NULL);
5561:
5562: ret = (xmlSchemaModelGroupDefPtr)
5563: xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5564: if (ret == NULL) {
5565: xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5566: return (NULL);
5567: }
5568: memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5569: ret->name = name;
5570: ret->type = XML_SCHEMA_TYPE_GROUP;
5571: ret->node = node;
5572: ret->targetNamespace = nsName;
5573:
5574: if (ctxt->isRedefine) {
5575: ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5576: ret, name, nsName);
5577: if (ctxt->redef == NULL) {
5578: xmlFree(ret);
5579: return(NULL);
5580: }
5581: ctxt->redefCounter = 0;
5582: }
5583: WXS_ADD_GLOBAL(ctxt, ret);
5584: WXS_ADD_PENDING(ctxt, ret);
5585: return (ret);
5586: }
5587:
5588: /**
5589: * xmlSchemaNewWildcardNs:
5590: * @ctxt: a schema validation context
5591: *
5592: * Creates a new wildcard namespace constraint.
5593: *
5594: * Returns the new struture or NULL in case of error
5595: */
5596: static xmlSchemaWildcardNsPtr
5597: xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5598: {
5599: xmlSchemaWildcardNsPtr ret;
5600:
5601: ret = (xmlSchemaWildcardNsPtr)
5602: xmlMalloc(sizeof(xmlSchemaWildcardNs));
5603: if (ret == NULL) {
5604: xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5605: return (NULL);
5606: }
5607: ret->value = NULL;
5608: ret->next = NULL;
5609: return (ret);
5610: }
5611:
5612: static xmlSchemaIDCPtr
5613: xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5614: const xmlChar *name, const xmlChar *nsName,
5615: int category, xmlNodePtr node)
5616: {
5617: xmlSchemaIDCPtr ret = NULL;
5618:
5619: if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5620: return (NULL);
5621:
5622: ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5623: if (ret == NULL) {
5624: xmlSchemaPErrMemory(ctxt,
5625: "allocating an identity-constraint definition", NULL);
5626: return (NULL);
5627: }
5628: memset(ret, 0, sizeof(xmlSchemaIDC));
5629: /* The target namespace of the parent element declaration. */
5630: ret->targetNamespace = nsName;
5631: ret->name = name;
5632: ret->type = category;
5633: ret->node = node;
5634:
5635: WXS_ADD_GLOBAL(ctxt, ret);
5636: /*
5637: * Only keyrefs need to be fixup up.
5638: */
5639: if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5640: WXS_ADD_PENDING(ctxt, ret);
5641: return (ret);
5642: }
5643:
5644: /**
5645: * xmlSchemaAddWildcard:
5646: * @ctxt: a schema validation context
5647: * @schema: a schema
5648: *
5649: * Adds a wildcard.
5650: * It corresponds to a xsd:anyAttribute and xsd:any.
5651: *
5652: * Returns the new struture or NULL in case of error
5653: */
5654: static xmlSchemaWildcardPtr
5655: xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5656: xmlSchemaTypeType type, xmlNodePtr node)
5657: {
5658: xmlSchemaWildcardPtr ret = NULL;
5659:
5660: if ((ctxt == NULL) || (schema == NULL))
5661: return (NULL);
5662:
5663: ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5664: if (ret == NULL) {
5665: xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5666: return (NULL);
5667: }
5668: memset(ret, 0, sizeof(xmlSchemaWildcard));
5669: ret->type = type;
5670: ret->node = node;
5671: WXS_ADD_LOCAL(ctxt, ret);
5672: return (ret);
5673: }
5674:
5675: static void
5676: xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5677: {
5678: if (group == NULL)
5679: return;
5680: if (group->members != NULL)
5681: xmlSchemaItemListFree(group->members);
5682: xmlFree(group);
5683: }
5684:
5685: static xmlSchemaSubstGroupPtr
5686: xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5687: xmlSchemaElementPtr head)
5688: {
5689: xmlSchemaSubstGroupPtr ret;
5690:
5691: /* Init subst group hash. */
5692: if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5693: WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5694: if (WXS_SUBST_GROUPS(pctxt) == NULL)
5695: return(NULL);
5696: }
5697: /* Create a new substitution group. */
5698: ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5699: if (ret == NULL) {
5700: xmlSchemaPErrMemory(NULL,
5701: "allocating a substitution group container", NULL);
5702: return(NULL);
5703: }
5704: memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5705: ret->head = head;
5706: /* Create list of members. */
5707: ret->members = xmlSchemaItemListCreate();
5708: if (ret->members == NULL) {
5709: xmlSchemaSubstGroupFree(ret);
5710: return(NULL);
5711: }
5712: /* Add subst group to hash. */
5713: if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5714: head->name, head->targetNamespace, ret) != 0) {
5715: PERROR_INT("xmlSchemaSubstGroupAdd",
5716: "failed to add a new substitution container");
5717: xmlSchemaSubstGroupFree(ret);
5718: return(NULL);
5719: }
5720: return(ret);
5721: }
5722:
5723: static xmlSchemaSubstGroupPtr
5724: xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5725: xmlSchemaElementPtr head)
5726: {
5727: if (WXS_SUBST_GROUPS(pctxt) == NULL)
5728: return(NULL);
5729: return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5730: head->name, head->targetNamespace));
5731:
5732: }
5733:
5734: /**
5735: * xmlSchemaAddElementSubstitutionMember:
5736: * @pctxt: a schema parser context
5737: * @head: the head of the substitution group
5738: * @member: the new member of the substitution group
5739: *
5740: * Allocate a new annotation structure.
5741: *
5742: * Returns the newly allocated structure or NULL in case or error
5743: */
5744: static int
5745: xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5746: xmlSchemaElementPtr head,
5747: xmlSchemaElementPtr member)
5748: {
5749: xmlSchemaSubstGroupPtr substGroup = NULL;
5750:
5751: if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5752: return (-1);
5753:
5754: substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5755: if (substGroup == NULL)
5756: substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5757: if (substGroup == NULL)
5758: return(-1);
5759: if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5760: return(-1);
5761: return(0);
5762: }
5763:
5764: /************************************************************************
1.1.1.3 ! misho 5765: * *
1.1 misho 5766: * Utilities for parsing *
1.1.1.3 ! misho 5767: * *
1.1 misho 5768: ************************************************************************/
5769:
5770: /**
5771: * xmlSchemaPValAttrNodeQNameValue:
5772: * @ctxt: a schema parser context
5773: * @schema: the schema context
5774: * @ownerDes: the designation of the parent element
5775: * @ownerItem: the parent as a schema object
5776: * @value: the QName value
5777: * @local: the resulting local part if found, the attribute value otherwise
5778: * @uri: the resulting namespace URI if found
5779: *
5780: * Extracts the local name and the URI of a QName value and validates it.
5781: * This one is intended to be used on attribute values that
5782: * should resolve to schema components.
5783: *
5784: * Returns 0, in case the QName is valid, a positive error code
5785: * if not valid and -1 if an internal error occurs.
5786: */
5787: static int
5788: xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5789: xmlSchemaPtr schema,
5790: xmlSchemaBasicItemPtr ownerItem,
5791: xmlAttrPtr attr,
5792: const xmlChar *value,
5793: const xmlChar **uri,
5794: const xmlChar **local)
5795: {
5796: const xmlChar *pref;
5797: xmlNsPtr ns;
5798: int len, ret;
5799:
5800: *uri = NULL;
5801: *local = NULL;
5802: ret = xmlValidateQName(value, 1);
5803: if (ret > 0) {
5804: xmlSchemaPSimpleTypeErr(ctxt,
5805: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5806: ownerItem, (xmlNodePtr) attr,
5807: xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5808: NULL, value, NULL, NULL, NULL);
5809: *local = value;
5810: return (ctxt->err);
5811: } else if (ret < 0)
5812: return (-1);
5813:
5814: if (!strchr((char *) value, ':')) {
5815: ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5816: if (ns)
5817: *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5818: else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5819: /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5820: * parser context. */
5821: /*
5822: * This one takes care of included schemas with no
5823: * target namespace.
5824: */
5825: *uri = ctxt->targetNamespace;
5826: }
5827: *local = xmlDictLookup(ctxt->dict, value, -1);
5828: return (0);
5829: }
5830: /*
5831: * At this point xmlSplitQName3 has to return a local name.
5832: */
5833: *local = xmlSplitQName3(value, &len);
5834: *local = xmlDictLookup(ctxt->dict, *local, -1);
5835: pref = xmlDictLookup(ctxt->dict, value, len);
5836: ns = xmlSearchNs(attr->doc, attr->parent, pref);
5837: if (ns == NULL) {
5838: xmlSchemaPSimpleTypeErr(ctxt,
5839: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5840: ownerItem, (xmlNodePtr) attr,
5841: xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5842: "The value '%s' of simple type 'xs:QName' has no "
5843: "corresponding namespace declaration in scope", value, NULL);
5844: return (ctxt->err);
5845: } else {
5846: *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5847: }
5848: return (0);
5849: }
5850:
5851: /**
5852: * xmlSchemaPValAttrNodeQName:
5853: * @ctxt: a schema parser context
5854: * @schema: the schema context
5855: * @ownerDes: the designation of the owner element
5856: * @ownerItem: the owner as a schema object
5857: * @attr: the attribute node
5858: * @local: the resulting local part if found, the attribute value otherwise
5859: * @uri: the resulting namespace URI if found
5860: *
5861: * Extracts and validates the QName of an attribute value.
5862: * This one is intended to be used on attribute values that
5863: * should resolve to schema components.
5864: *
5865: * Returns 0, in case the QName is valid, a positive error code
5866: * if not valid and -1 if an internal error occurs.
5867: */
5868: static int
5869: xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5870: xmlSchemaPtr schema,
5871: xmlSchemaBasicItemPtr ownerItem,
5872: xmlAttrPtr attr,
5873: const xmlChar **uri,
5874: const xmlChar **local)
5875: {
5876: const xmlChar *value;
5877:
5878: value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5879: return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5880: ownerItem, attr, value, uri, local));
5881: }
5882:
5883: /**
5884: * xmlSchemaPValAttrQName:
5885: * @ctxt: a schema parser context
5886: * @schema: the schema context
5887: * @ownerDes: the designation of the parent element
5888: * @ownerItem: the owner as a schema object
5889: * @ownerElem: the parent node of the attribute
5890: * @name: the name of the attribute
5891: * @local: the resulting local part if found, the attribute value otherwise
5892: * @uri: the resulting namespace URI if found
5893: *
5894: * Extracts and validates the QName of an attribute value.
5895: *
5896: * Returns 0, in case the QName is valid, a positive error code
5897: * if not valid and -1 if an internal error occurs.
5898: */
5899: static int
5900: xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5901: xmlSchemaPtr schema,
5902: xmlSchemaBasicItemPtr ownerItem,
5903: xmlNodePtr ownerElem,
5904: const char *name,
5905: const xmlChar **uri,
5906: const xmlChar **local)
5907: {
5908: xmlAttrPtr attr;
5909:
5910: attr = xmlSchemaGetPropNode(ownerElem, name);
5911: if (attr == NULL) {
5912: *local = NULL;
5913: *uri = NULL;
5914: return (0);
5915: }
5916: return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5917: ownerItem, attr, uri, local));
5918: }
5919:
5920: /**
5921: * xmlSchemaPValAttrID:
5922: * @ctxt: a schema parser context
5923: * @schema: the schema context
5924: * @ownerDes: the designation of the parent element
5925: * @ownerItem: the owner as a schema object
5926: * @ownerElem: the parent node of the attribute
5927: * @name: the name of the attribute
5928: *
5929: * Extracts and validates the ID of an attribute value.
5930: *
5931: * Returns 0, in case the ID is valid, a positive error code
5932: * if not valid and -1 if an internal error occurs.
5933: */
5934: static int
5935: xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5936: {
5937: int ret;
5938: const xmlChar *value;
5939:
5940: if (attr == NULL)
5941: return(0);
5942: value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5943: ret = xmlValidateNCName(value, 1);
5944: if (ret == 0) {
5945: /*
5946: * NOTE: the IDness might have already be declared in the DTD
5947: */
5948: if (attr->atype != XML_ATTRIBUTE_ID) {
5949: xmlIDPtr res;
5950: xmlChar *strip;
5951:
5952: /*
5953: * TODO: Use xmlSchemaStrip here; it's not exported at this
5954: * moment.
5955: */
5956: strip = xmlSchemaCollapseString(value);
5957: if (strip != NULL) {
5958: xmlFree((xmlChar *) value);
5959: value = strip;
5960: }
1.1.1.3 ! misho 5961: res = xmlAddID(NULL, attr->doc, value, attr);
1.1 misho 5962: if (res == NULL) {
5963: ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5964: xmlSchemaPSimpleTypeErr(ctxt,
5965: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5966: NULL, (xmlNodePtr) attr,
5967: xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5968: NULL, NULL, "Duplicate value '%s' of simple "
5969: "type 'xs:ID'", value, NULL);
5970: } else
5971: attr->atype = XML_ATTRIBUTE_ID;
5972: }
5973: } else if (ret > 0) {
5974: ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5975: xmlSchemaPSimpleTypeErr(ctxt,
5976: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5977: NULL, (xmlNodePtr) attr,
5978: xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5979: NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5980: "not a valid 'xs:NCName'",
5981: value, NULL);
5982: }
5983: if (value != NULL)
5984: xmlFree((xmlChar *)value);
5985:
5986: return (ret);
5987: }
5988:
5989: static int
5990: xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5991: xmlNodePtr ownerElem,
5992: const xmlChar *name)
5993: {
5994: xmlAttrPtr attr;
5995:
5996: attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5997: if (attr == NULL)
5998: return(0);
5999: return(xmlSchemaPValAttrNodeID(ctxt, attr));
6000:
6001: }
6002:
6003: /**
6004: * xmlGetMaxOccurs:
6005: * @ctxt: a schema validation context
6006: * @node: a subtree containing XML Schema informations
6007: *
6008: * Get the maxOccurs property
6009: *
6010: * Returns the default if not found, or the value
6011: */
6012: static int
6013: xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6014: int min, int max, int def, const char *expected)
6015: {
6016: const xmlChar *val, *cur;
6017: int ret = 0;
6018: xmlAttrPtr attr;
6019:
6020: attr = xmlSchemaGetPropNode(node, "maxOccurs");
6021: if (attr == NULL)
6022: return (def);
6023: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6024:
6025: if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6026: if (max != UNBOUNDED) {
6027: xmlSchemaPSimpleTypeErr(ctxt,
6028: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6029: /* XML_SCHEMAP_INVALID_MINOCCURS, */
6030: NULL, (xmlNodePtr) attr, NULL, expected,
6031: val, NULL, NULL, NULL);
6032: return (def);
6033: } else
6034: return (UNBOUNDED); /* encoding it with -1 might be another option */
6035: }
6036:
6037: cur = val;
6038: while (IS_BLANK_CH(*cur))
6039: cur++;
6040: if (*cur == 0) {
6041: xmlSchemaPSimpleTypeErr(ctxt,
6042: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6043: /* XML_SCHEMAP_INVALID_MINOCCURS, */
6044: NULL, (xmlNodePtr) attr, NULL, expected,
6045: val, NULL, NULL, NULL);
6046: return (def);
6047: }
6048: while ((*cur >= '0') && (*cur <= '9')) {
6049: ret = ret * 10 + (*cur - '0');
6050: cur++;
6051: }
6052: while (IS_BLANK_CH(*cur))
6053: cur++;
6054: /*
6055: * TODO: Restrict the maximal value to Integer.
6056: */
6057: if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6058: xmlSchemaPSimpleTypeErr(ctxt,
6059: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6060: /* XML_SCHEMAP_INVALID_MINOCCURS, */
6061: NULL, (xmlNodePtr) attr, NULL, expected,
6062: val, NULL, NULL, NULL);
6063: return (def);
6064: }
6065: return (ret);
6066: }
6067:
6068: /**
6069: * xmlGetMinOccurs:
6070: * @ctxt: a schema validation context
6071: * @node: a subtree containing XML Schema informations
6072: *
6073: * Get the minOccurs property
6074: *
6075: * Returns the default if not found, or the value
6076: */
6077: static int
6078: xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6079: int min, int max, int def, const char *expected)
6080: {
6081: const xmlChar *val, *cur;
6082: int ret = 0;
6083: xmlAttrPtr attr;
6084:
6085: attr = xmlSchemaGetPropNode(node, "minOccurs");
6086: if (attr == NULL)
6087: return (def);
6088: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6089: cur = val;
6090: while (IS_BLANK_CH(*cur))
6091: cur++;
6092: if (*cur == 0) {
6093: xmlSchemaPSimpleTypeErr(ctxt,
6094: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6095: /* XML_SCHEMAP_INVALID_MINOCCURS, */
6096: NULL, (xmlNodePtr) attr, NULL, expected,
6097: val, NULL, NULL, NULL);
6098: return (def);
6099: }
6100: while ((*cur >= '0') && (*cur <= '9')) {
6101: ret = ret * 10 + (*cur - '0');
6102: cur++;
6103: }
6104: while (IS_BLANK_CH(*cur))
6105: cur++;
6106: /*
6107: * TODO: Restrict the maximal value to Integer.
6108: */
6109: if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6110: xmlSchemaPSimpleTypeErr(ctxt,
6111: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6112: /* XML_SCHEMAP_INVALID_MINOCCURS, */
6113: NULL, (xmlNodePtr) attr, NULL, expected,
6114: val, NULL, NULL, NULL);
6115: return (def);
6116: }
6117: return (ret);
6118: }
6119:
6120: /**
6121: * xmlSchemaPGetBoolNodeValue:
6122: * @ctxt: a schema validation context
6123: * @ownerDes: owner designation
6124: * @ownerItem: the owner as a schema item
6125: * @node: the node holding the value
6126: *
6127: * Converts a boolean string value into 1 or 0.
6128: *
6129: * Returns 0 or 1.
6130: */
6131: static int
6132: xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6133: xmlSchemaBasicItemPtr ownerItem,
6134: xmlNodePtr node)
6135: {
6136: xmlChar *value = NULL;
6137: int res = 0;
6138:
6139: value = xmlNodeGetContent(node);
6140: /*
6141: * 3.2.2.1 Lexical representation
6142: * An instance of a datatype that is defined as �boolean�
6143: * can have the following legal literals {true, false, 1, 0}.
6144: */
6145: if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6146: res = 1;
6147: else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6148: res = 0;
6149: else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6150: res = 1;
6151: else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6152: res = 0;
6153: else {
6154: xmlSchemaPSimpleTypeErr(ctxt,
6155: XML_SCHEMAP_INVALID_BOOLEAN,
6156: ownerItem, node,
6157: xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6158: NULL, BAD_CAST value,
6159: NULL, NULL, NULL);
6160: }
6161: if (value != NULL)
6162: xmlFree(value);
6163: return (res);
6164: }
6165:
6166: /**
6167: * xmlGetBooleanProp:
6168: * @ctxt: a schema validation context
6169: * @node: a subtree containing XML Schema informations
6170: * @name: the attribute name
6171: * @def: the default value
6172: *
6173: * Evaluate if a boolean property is set
6174: *
6175: * Returns the default if not found, 0 if found to be false,
6176: * 1 if found to be true
6177: */
6178: static int
6179: xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6180: xmlNodePtr node,
6181: const char *name, int def)
6182: {
6183: const xmlChar *val;
6184:
6185: val = xmlSchemaGetProp(ctxt, node, name);
6186: if (val == NULL)
6187: return (def);
6188: /*
6189: * 3.2.2.1 Lexical representation
6190: * An instance of a datatype that is defined as �boolean�
6191: * can have the following legal literals {true, false, 1, 0}.
6192: */
6193: if (xmlStrEqual(val, BAD_CAST "true"))
6194: def = 1;
6195: else if (xmlStrEqual(val, BAD_CAST "false"))
6196: def = 0;
6197: else if (xmlStrEqual(val, BAD_CAST "1"))
6198: def = 1;
6199: else if (xmlStrEqual(val, BAD_CAST "0"))
6200: def = 0;
6201: else {
6202: xmlSchemaPSimpleTypeErr(ctxt,
6203: XML_SCHEMAP_INVALID_BOOLEAN,
6204: NULL,
6205: (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6206: xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6207: NULL, val, NULL, NULL, NULL);
6208: }
6209: return (def);
6210: }
6211:
6212: /************************************************************************
1.1.1.3 ! misho 6213: * *
1.1 misho 6214: * Shema extraction from an Infoset *
1.1.1.3 ! misho 6215: * *
1.1 misho 6216: ************************************************************************/
6217: static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6218: ctxt, xmlSchemaPtr schema,
6219: xmlNodePtr node,
6220: int topLevel);
6221: static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6222: ctxt,
6223: xmlSchemaPtr schema,
6224: xmlNodePtr node,
6225: int topLevel);
6226: static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6227: ctxt,
6228: xmlSchemaPtr schema,
6229: xmlNodePtr node,
6230: xmlSchemaTypeType parentType);
6231: static xmlSchemaBasicItemPtr
6232: xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6233: xmlSchemaPtr schema,
6234: xmlNodePtr node,
6235: xmlSchemaItemListPtr uses,
6236: int parentType);
6237: static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6238: xmlSchemaPtr schema,
6239: xmlNodePtr node);
6240: static xmlSchemaWildcardPtr
6241: xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6242: xmlSchemaPtr schema, xmlNodePtr node);
6243:
6244: /**
6245: * xmlSchemaPValAttrNodeValue:
6246: *
6247: * @ctxt: a schema parser context
6248: * @ownerDes: the designation of the parent element
6249: * @ownerItem: the schema object owner if existent
6250: * @attr: the schema attribute node being validated
6251: * @value: the value
6252: * @type: the built-in type to be validated against
6253: *
6254: * Validates a value against the given built-in type.
6255: * This one is intended to be used internally for validation
6256: * of schema attribute values during parsing of the schema.
6257: *
6258: * Returns 0 if the value is valid, a positive error code
6259: * number otherwise and -1 in case of an internal or API error.
6260: */
6261: static int
6262: xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6263: xmlSchemaBasicItemPtr ownerItem,
6264: xmlAttrPtr attr,
6265: const xmlChar *value,
6266: xmlSchemaTypePtr type)
6267: {
6268:
6269: int ret = 0;
6270:
6271: /*
6272: * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6273: * one is really meant to be used internally, so better not.
6274: */
6275: if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6276: return (-1);
6277: if (type->type != XML_SCHEMA_TYPE_BASIC) {
6278: PERROR_INT("xmlSchemaPValAttrNodeValue",
6279: "the given type is not a built-in type");
6280: return (-1);
6281: }
6282: switch (type->builtInType) {
6283: case XML_SCHEMAS_NCNAME:
6284: case XML_SCHEMAS_QNAME:
6285: case XML_SCHEMAS_ANYURI:
6286: case XML_SCHEMAS_TOKEN:
6287: case XML_SCHEMAS_LANGUAGE:
6288: ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6289: (xmlNodePtr) attr);
6290: break;
6291: default: {
6292: PERROR_INT("xmlSchemaPValAttrNodeValue",
6293: "validation using the given type is not supported while "
6294: "parsing a schema");
6295: return (-1);
6296: }
6297: }
6298: /*
6299: * TODO: Should we use the S4S error codes instead?
6300: */
6301: if (ret < 0) {
6302: PERROR_INT("xmlSchemaPValAttrNodeValue",
6303: "failed to validate a schema attribute value");
6304: return (-1);
6305: } else if (ret > 0) {
6306: if (WXS_IS_LIST(type))
6307: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6308: else
6309: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6310: xmlSchemaPSimpleTypeErr(pctxt,
6311: ret, ownerItem, (xmlNodePtr) attr,
6312: type, NULL, value, NULL, NULL, NULL);
6313: }
6314: return (ret);
6315: }
6316:
6317: /**
6318: * xmlSchemaPValAttrNode:
6319: *
6320: * @ctxt: a schema parser context
6321: * @ownerDes: the designation of the parent element
6322: * @ownerItem: the schema object owner if existent
6323: * @attr: the schema attribute node being validated
6324: * @type: the built-in type to be validated against
6325: * @value: the resulting value if any
6326: *
6327: * Extracts and validates a value against the given built-in type.
6328: * This one is intended to be used internally for validation
6329: * of schema attribute values during parsing of the schema.
6330: *
6331: * Returns 0 if the value is valid, a positive error code
6332: * number otherwise and -1 in case of an internal or API error.
6333: */
6334: static int
6335: xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6336: xmlSchemaBasicItemPtr ownerItem,
6337: xmlAttrPtr attr,
6338: xmlSchemaTypePtr type,
6339: const xmlChar **value)
6340: {
6341: const xmlChar *val;
6342:
6343: if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6344: return (-1);
6345:
6346: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6347: if (value != NULL)
6348: *value = val;
6349:
6350: return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6351: val, type));
6352: }
6353:
6354: /**
6355: * xmlSchemaPValAttr:
6356: *
6357: * @ctxt: a schema parser context
6358: * @node: the element node of the attribute
6359: * @ownerDes: the designation of the parent element
6360: * @ownerItem: the schema object owner if existent
6361: * @ownerElem: the owner element node
6362: * @name: the name of the schema attribute node
6363: * @type: the built-in type to be validated against
6364: * @value: the resulting value if any
6365: *
6366: * Extracts and validates a value against the given built-in type.
6367: * This one is intended to be used internally for validation
6368: * of schema attribute values during parsing of the schema.
6369: *
6370: * Returns 0 if the value is valid, a positive error code
6371: * number otherwise and -1 in case of an internal or API error.
6372: */
6373: static int
6374: xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6375: xmlSchemaBasicItemPtr ownerItem,
6376: xmlNodePtr ownerElem,
6377: const char *name,
6378: xmlSchemaTypePtr type,
6379: const xmlChar **value)
6380: {
6381: xmlAttrPtr attr;
6382:
6383: if ((ctxt == NULL) || (type == NULL)) {
6384: if (value != NULL)
6385: *value = NULL;
6386: return (-1);
6387: }
6388: if (type->type != XML_SCHEMA_TYPE_BASIC) {
6389: if (value != NULL)
6390: *value = NULL;
6391: xmlSchemaPErr(ctxt, ownerElem,
6392: XML_SCHEMAP_INTERNAL,
6393: "Internal error: xmlSchemaPValAttr, the given "
6394: "type '%s' is not a built-in type.\n",
6395: type->name, NULL);
6396: return (-1);
6397: }
6398: attr = xmlSchemaGetPropNode(ownerElem, name);
6399: if (attr == NULL) {
6400: if (value != NULL)
6401: *value = NULL;
6402: return (0);
6403: }
6404: return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6405: type, value));
6406: }
6407:
6408: static int
6409: xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6410: xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6411: xmlNodePtr node,
6412: xmlAttrPtr attr,
6413: const xmlChar *namespaceName)
6414: {
6415: /* TODO: Pointer comparison instead? */
6416: if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6417: return (0);
6418: if (xmlStrEqual(xmlSchemaNs, namespaceName))
6419: return (0);
6420: /*
6421: * Check if the referenced namespace was <import>ed.
6422: */
6423: if (WXS_BUCKET(pctxt)->relations != NULL) {
6424: xmlSchemaSchemaRelationPtr rel;
6425:
6426: rel = WXS_BUCKET(pctxt)->relations;
6427: do {
6428: if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6429: xmlStrEqual(namespaceName, rel->importNamespace))
6430: return (0);
6431: rel = rel->next;
6432: } while (rel != NULL);
6433: }
6434: /*
6435: * No matching <import>ed namespace found.
6436: */
6437: {
6438: xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6439:
6440: if (namespaceName == NULL)
6441: xmlSchemaCustomErr(ACTXT_CAST pctxt,
6442: XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6443: "References from this schema to components in no "
6444: "namespace are not allowed, since not indicated by an "
6445: "import statement", NULL, NULL);
6446: else
6447: xmlSchemaCustomErr(ACTXT_CAST pctxt,
6448: XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6449: "References from this schema to components in the "
6450: "namespace '%s' are not allowed, since not indicated by an "
6451: "import statement", namespaceName, NULL);
6452: }
6453: return (XML_SCHEMAP_SRC_RESOLVE);
6454: }
6455:
6456: /**
6457: * xmlSchemaParseLocalAttributes:
6458: * @ctxt: a schema validation context
6459: * @schema: the schema being built
6460: * @node: a subtree containing XML Schema informations
6461: * @type: the hosting type where the attributes will be anchored
6462: *
6463: * Parses attribute uses and attribute declarations and
6464: * attribute group references.
6465: */
6466: static int
6467: xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6468: xmlNodePtr *child, xmlSchemaItemListPtr *list,
6469: int parentType, int *hasRefs)
6470: {
6471: void *item;
6472:
6473: while ((IS_SCHEMA((*child), "attribute")) ||
6474: (IS_SCHEMA((*child), "attributeGroup"))) {
6475: if (IS_SCHEMA((*child), "attribute")) {
6476: item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6477: *list, parentType);
6478: } else {
6479: item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6480: if ((item != NULL) && (hasRefs != NULL))
6481: *hasRefs = 1;
6482: }
6483: if (item != NULL) {
6484: if (*list == NULL) {
6485: /* TODO: Customize grow factor. */
6486: *list = xmlSchemaItemListCreate();
6487: if (*list == NULL)
6488: return(-1);
6489: }
6490: if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6491: return(-1);
6492: }
6493: *child = (*child)->next;
6494: }
6495: return (0);
6496: }
6497:
6498: /**
6499: * xmlSchemaParseAnnotation:
6500: * @ctxt: a schema validation context
6501: * @schema: the schema being built
6502: * @node: a subtree containing XML Schema informations
6503: *
6504: * parse a XML schema Attrribute declaration
6505: * *WARNING* this interface is highly subject to change
6506: *
6507: * Returns -1 in case of error, 0 if the declaration is improper and
6508: * 1 in case of success.
6509: */
6510: static xmlSchemaAnnotPtr
6511: xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6512: {
6513: xmlSchemaAnnotPtr ret;
6514: xmlNodePtr child = NULL;
6515: xmlAttrPtr attr;
6516: int barked = 0;
6517:
6518: /*
6519: * INFO: S4S completed.
6520: */
6521: /*
6522: * id = ID
6523: * {any attributes with non-schema namespace . . .}>
6524: * Content: (appinfo | documentation)*
6525: */
6526: if ((ctxt == NULL) || (node == NULL))
6527: return (NULL);
6528: if (needed)
6529: ret = xmlSchemaNewAnnot(ctxt, node);
6530: else
6531: ret = NULL;
6532: attr = node->properties;
6533: while (attr != NULL) {
6534: if (((attr->ns == NULL) &&
6535: (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6536: ((attr->ns != NULL) &&
6537: xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6538:
6539: xmlSchemaPIllegalAttrErr(ctxt,
6540: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6541: }
6542: attr = attr->next;
6543: }
6544: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6545: /*
6546: * And now for the children...
6547: */
6548: child = node->children;
6549: while (child != NULL) {
6550: if (IS_SCHEMA(child, "appinfo")) {
6551: /* TODO: make available the content of "appinfo". */
6552: /*
6553: * source = anyURI
6554: * {any attributes with non-schema namespace . . .}>
6555: * Content: ({any})*
6556: */
6557: attr = child->properties;
6558: while (attr != NULL) {
6559: if (((attr->ns == NULL) &&
6560: (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6561: ((attr->ns != NULL) &&
6562: xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6563:
6564: xmlSchemaPIllegalAttrErr(ctxt,
6565: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6566: }
6567: attr = attr->next;
6568: }
6569: xmlSchemaPValAttr(ctxt, NULL, child, "source",
6570: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6571: child = child->next;
6572: } else if (IS_SCHEMA(child, "documentation")) {
6573: /* TODO: make available the content of "documentation". */
6574: /*
6575: * source = anyURI
6576: * {any attributes with non-schema namespace . . .}>
6577: * Content: ({any})*
6578: */
6579: attr = child->properties;
6580: while (attr != NULL) {
6581: if (attr->ns == NULL) {
6582: if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6583: xmlSchemaPIllegalAttrErr(ctxt,
6584: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6585: }
6586: } else {
6587: if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6588: (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6589: (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6590:
6591: xmlSchemaPIllegalAttrErr(ctxt,
6592: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6593: }
6594: }
6595: attr = attr->next;
6596: }
6597: /*
6598: * Attribute "xml:lang".
6599: */
6600: attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6601: if (attr != NULL)
6602: xmlSchemaPValAttrNode(ctxt, NULL, attr,
6603: xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6604: child = child->next;
6605: } else {
6606: if (!barked)
6607: xmlSchemaPContentErr(ctxt,
6608: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6609: NULL, node, child, NULL, "(appinfo | documentation)*");
6610: barked = 1;
6611: child = child->next;
6612: }
6613: }
6614:
6615: return (ret);
6616: }
6617:
6618: /**
6619: * xmlSchemaParseFacet:
6620: * @ctxt: a schema validation context
6621: * @schema: the schema being built
6622: * @node: a subtree containing XML Schema informations
6623: *
6624: * parse a XML schema Facet declaration
6625: * *WARNING* this interface is highly subject to change
6626: *
6627: * Returns the new type structure or NULL in case of error
6628: */
6629: static xmlSchemaFacetPtr
6630: xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6631: xmlNodePtr node)
6632: {
6633: xmlSchemaFacetPtr facet;
6634: xmlNodePtr child = NULL;
6635: const xmlChar *value;
6636:
6637: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6638: return (NULL);
6639:
6640: facet = xmlSchemaNewFacet();
6641: if (facet == NULL) {
6642: xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6643: return (NULL);
6644: }
6645: facet->node = node;
6646: value = xmlSchemaGetProp(ctxt, node, "value");
6647: if (value == NULL) {
6648: xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6649: "Facet %s has no value\n", node->name, NULL);
6650: xmlSchemaFreeFacet(facet);
6651: return (NULL);
6652: }
6653: if (IS_SCHEMA(node, "minInclusive")) {
6654: facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6655: } else if (IS_SCHEMA(node, "minExclusive")) {
6656: facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6657: } else if (IS_SCHEMA(node, "maxInclusive")) {
6658: facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6659: } else if (IS_SCHEMA(node, "maxExclusive")) {
6660: facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6661: } else if (IS_SCHEMA(node, "totalDigits")) {
6662: facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6663: } else if (IS_SCHEMA(node, "fractionDigits")) {
6664: facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6665: } else if (IS_SCHEMA(node, "pattern")) {
6666: facet->type = XML_SCHEMA_FACET_PATTERN;
6667: } else if (IS_SCHEMA(node, "enumeration")) {
6668: facet->type = XML_SCHEMA_FACET_ENUMERATION;
6669: } else if (IS_SCHEMA(node, "whiteSpace")) {
6670: facet->type = XML_SCHEMA_FACET_WHITESPACE;
6671: } else if (IS_SCHEMA(node, "length")) {
6672: facet->type = XML_SCHEMA_FACET_LENGTH;
6673: } else if (IS_SCHEMA(node, "maxLength")) {
6674: facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6675: } else if (IS_SCHEMA(node, "minLength")) {
6676: facet->type = XML_SCHEMA_FACET_MINLENGTH;
6677: } else {
6678: xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6679: "Unknown facet type %s\n", node->name, NULL);
6680: xmlSchemaFreeFacet(facet);
6681: return (NULL);
6682: }
6683: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6684: facet->value = value;
6685: if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6686: (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6687: const xmlChar *fixed;
6688:
6689: fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6690: if (fixed != NULL) {
6691: if (xmlStrEqual(fixed, BAD_CAST "true"))
6692: facet->fixed = 1;
6693: }
6694: }
6695: child = node->children;
6696:
6697: if (IS_SCHEMA(child, "annotation")) {
6698: facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6699: child = child->next;
6700: }
6701: if (child != NULL) {
6702: xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6703: "Facet %s has unexpected child content\n",
6704: node->name, NULL);
6705: }
6706: return (facet);
6707: }
6708:
6709: /**
6710: * xmlSchemaParseWildcardNs:
6711: * @ctxt: a schema parser context
6712: * @wildc: the wildcard, already created
6713: * @node: a subtree containing XML Schema informations
6714: *
6715: * Parses the attribute "processContents" and "namespace"
6716: * of a xsd:anyAttribute and xsd:any.
6717: * *WARNING* this interface is highly subject to change
6718: *
6719: * Returns 0 if everything goes fine, a positive error code
6720: * if something is not valid and -1 if an internal error occurs.
6721: */
6722: static int
6723: xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6724: xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6725: xmlSchemaWildcardPtr wildc,
6726: xmlNodePtr node)
6727: {
6728: const xmlChar *pc, *ns, *dictnsItem;
6729: int ret = 0;
6730: xmlChar *nsItem;
6731: xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6732: xmlAttrPtr attr;
6733:
6734: pc = xmlSchemaGetProp(ctxt, node, "processContents");
6735: if ((pc == NULL)
6736: || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6737: wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6738: } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6739: wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6740: } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6741: wildc->processContents = XML_SCHEMAS_ANY_LAX;
6742: } else {
6743: xmlSchemaPSimpleTypeErr(ctxt,
6744: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6745: NULL, node,
6746: NULL, "(strict | skip | lax)", pc,
6747: NULL, NULL, NULL);
6748: wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6749: ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6750: }
6751: /*
6752: * Build the namespace constraints.
6753: */
6754: attr = xmlSchemaGetPropNode(node, "namespace");
6755: ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6756: if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6757: wildc->any = 1;
6758: else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6759: wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6760: if (wildc->negNsSet == NULL) {
6761: return (-1);
6762: }
6763: wildc->negNsSet->value = ctxt->targetNamespace;
6764: } else {
6765: const xmlChar *end, *cur;
6766:
6767: cur = ns;
6768: do {
6769: while (IS_BLANK_CH(*cur))
6770: cur++;
6771: end = cur;
6772: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6773: end++;
6774: if (end == cur)
6775: break;
6776: nsItem = xmlStrndup(cur, end - cur);
6777: if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6778: (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6779: xmlSchemaPSimpleTypeErr(ctxt,
6780: XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6781: NULL, (xmlNodePtr) attr,
6782: NULL,
6783: "((##any | ##other) | List of (xs:anyURI | "
6784: "(##targetNamespace | ##local)))",
6785: nsItem, NULL, NULL, NULL);
6786: ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6787: } else {
6788: if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6789: dictnsItem = ctxt->targetNamespace;
6790: } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6791: dictnsItem = NULL;
6792: } else {
6793: /*
6794: * Validate the item (anyURI).
6795: */
6796: xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6797: nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6798: dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6799: }
6800: /*
6801: * Avoid dublicate namespaces.
6802: */
6803: tmp = wildc->nsSet;
6804: while (tmp != NULL) {
6805: if (dictnsItem == tmp->value)
6806: break;
6807: tmp = tmp->next;
6808: }
6809: if (tmp == NULL) {
6810: tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6811: if (tmp == NULL) {
6812: xmlFree(nsItem);
6813: return (-1);
6814: }
6815: tmp->value = dictnsItem;
6816: tmp->next = NULL;
6817: if (wildc->nsSet == NULL)
6818: wildc->nsSet = tmp;
6819: else if (lastNs != NULL)
6820: lastNs->next = tmp;
6821: lastNs = tmp;
6822: }
6823:
6824: }
6825: xmlFree(nsItem);
6826: cur = end;
6827: } while (*cur != 0);
6828: }
6829: return (ret);
6830: }
6831:
6832: static int
6833: xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6834: xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6835: xmlNodePtr node,
6836: int minOccurs,
6837: int maxOccurs) {
6838:
6839: if ((maxOccurs == 0) && ( minOccurs == 0))
6840: return (0);
6841: if (maxOccurs != UNBOUNDED) {
6842: /*
6843: * TODO: Maybe we should better not create the particle,
6844: * if min/max is invalid, since it could confuse the build of the
6845: * content model.
6846: */
6847: /*
6848: * 3.9.6 Schema Component Constraint: Particle Correct
6849: *
6850: */
6851: if (maxOccurs < 1) {
6852: /*
6853: * 2.2 {max occurs} must be greater than or equal to 1.
6854: */
6855: xmlSchemaPCustomAttrErr(ctxt,
6856: XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6857: NULL, NULL,
6858: xmlSchemaGetPropNode(node, "maxOccurs"),
6859: "The value must be greater than or equal to 1");
6860: return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6861: } else if (minOccurs > maxOccurs) {
6862: /*
6863: * 2.1 {min occurs} must not be greater than {max occurs}.
6864: */
6865: xmlSchemaPCustomAttrErr(ctxt,
6866: XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6867: NULL, NULL,
6868: xmlSchemaGetPropNode(node, "minOccurs"),
6869: "The value must not be greater than the value of 'maxOccurs'");
6870: return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6871: }
6872: }
6873: return (0);
6874: }
6875:
6876: /**
6877: * xmlSchemaParseAny:
6878: * @ctxt: a schema validation context
6879: * @schema: the schema being built
6880: * @node: a subtree containing XML Schema informations
6881: *
6882: * Parsea a XML schema <any> element. A particle and wildcard
6883: * will be created (except if minOccurs==maxOccurs==0, in this case
6884: * nothing will be created).
6885: * *WARNING* this interface is highly subject to change
6886: *
6887: * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6888: */
6889: static xmlSchemaParticlePtr
6890: xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6891: xmlNodePtr node)
6892: {
6893: xmlSchemaParticlePtr particle;
6894: xmlNodePtr child = NULL;
6895: xmlSchemaWildcardPtr wild;
6896: int min, max;
6897: xmlAttrPtr attr;
6898: xmlSchemaAnnotPtr annot = NULL;
6899:
6900: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6901: return (NULL);
6902: /*
6903: * Check for illegal attributes.
6904: */
6905: attr = node->properties;
6906: while (attr != NULL) {
6907: if (attr->ns == NULL) {
6908: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6909: (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6910: (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6911: (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6912: (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6913: xmlSchemaPIllegalAttrErr(ctxt,
6914: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6915: }
6916: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6917: xmlSchemaPIllegalAttrErr(ctxt,
6918: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6919: }
6920: attr = attr->next;
6921: }
6922: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6923: /*
6924: * minOccurs/maxOccurs.
6925: */
6926: max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6927: "(xs:nonNegativeInteger | unbounded)");
6928: min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6929: "xs:nonNegativeInteger");
6930: xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6931: /*
6932: * Create & parse the wildcard.
6933: */
6934: wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6935: if (wild == NULL)
6936: return (NULL);
6937: xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6938: /*
6939: * And now for the children...
6940: */
6941: child = node->children;
6942: if (IS_SCHEMA(child, "annotation")) {
6943: annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6944: child = child->next;
6945: }
6946: if (child != NULL) {
6947: xmlSchemaPContentErr(ctxt,
6948: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6949: NULL, node, child,
6950: NULL, "(annotation?)");
6951: }
6952: /*
6953: * No component if minOccurs==maxOccurs==0.
6954: */
6955: if ((min == 0) && (max == 0)) {
6956: /* Don't free the wildcard, since it's already on the list. */
6957: return (NULL);
6958: }
6959: /*
6960: * Create the particle.
6961: */
6962: particle = xmlSchemaAddParticle(ctxt, node, min, max);
6963: if (particle == NULL)
6964: return (NULL);
6965: particle->annot = annot;
6966: particle->children = (xmlSchemaTreeItemPtr) wild;
6967:
6968: return (particle);
6969: }
6970:
6971: /**
6972: * xmlSchemaParseNotation:
6973: * @ctxt: a schema validation context
6974: * @schema: the schema being built
6975: * @node: a subtree containing XML Schema informations
6976: *
6977: * parse a XML schema Notation declaration
6978: *
6979: * Returns the new structure or NULL in case of error
6980: */
6981: static xmlSchemaNotationPtr
6982: xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6983: xmlNodePtr node)
6984: {
6985: const xmlChar *name;
6986: xmlSchemaNotationPtr ret;
6987: xmlNodePtr child = NULL;
6988:
6989: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6990: return (NULL);
6991: name = xmlSchemaGetProp(ctxt, node, "name");
6992: if (name == NULL) {
6993: xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6994: "Notation has no name\n", NULL, NULL);
6995: return (NULL);
6996: }
6997: ret = xmlSchemaAddNotation(ctxt, schema, name,
6998: ctxt->targetNamespace, node);
6999: if (ret == NULL)
7000: return (NULL);
7001: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7002:
7003: child = node->children;
7004: if (IS_SCHEMA(child, "annotation")) {
7005: ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7006: child = child->next;
7007: }
7008: if (child != NULL) {
7009: xmlSchemaPContentErr(ctxt,
7010: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7011: NULL, node, child,
7012: NULL, "(annotation?)");
7013: }
7014:
7015: return (ret);
7016: }
7017:
7018: /**
7019: * xmlSchemaParseAnyAttribute:
7020: * @ctxt: a schema validation context
7021: * @schema: the schema being built
7022: * @node: a subtree containing XML Schema informations
7023: *
7024: * parse a XML schema AnyAttrribute declaration
7025: * *WARNING* this interface is highly subject to change
7026: *
7027: * Returns a wildcard or NULL.
7028: */
7029: static xmlSchemaWildcardPtr
7030: xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7031: xmlSchemaPtr schema, xmlNodePtr node)
7032: {
7033: xmlSchemaWildcardPtr ret;
7034: xmlNodePtr child = NULL;
7035: xmlAttrPtr attr;
7036:
7037: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7038: return (NULL);
7039:
7040: ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7041: node);
7042: if (ret == NULL) {
7043: return (NULL);
7044: }
7045: /*
7046: * Check for illegal attributes.
7047: */
7048: attr = node->properties;
7049: while (attr != NULL) {
7050: if (attr->ns == NULL) {
7051: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7052: (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7053: (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7054: xmlSchemaPIllegalAttrErr(ctxt,
7055: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7056: }
7057: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7058: xmlSchemaPIllegalAttrErr(ctxt,
7059: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7060: }
7061: attr = attr->next;
7062: }
7063: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7064: /*
7065: * Parse the namespace list.
7066: */
7067: if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7068: return (NULL);
7069: /*
7070: * And now for the children...
7071: */
7072: child = node->children;
7073: if (IS_SCHEMA(child, "annotation")) {
7074: ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7075: child = child->next;
7076: }
7077: if (child != NULL) {
7078: xmlSchemaPContentErr(ctxt,
7079: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7080: NULL, node, child,
7081: NULL, "(annotation?)");
7082: }
7083:
7084: return (ret);
7085: }
7086:
7087:
7088: /**
7089: * xmlSchemaParseAttribute:
7090: * @ctxt: a schema validation context
7091: * @schema: the schema being built
7092: * @node: a subtree containing XML Schema informations
7093: *
7094: * parse a XML schema Attrribute declaration
7095: * *WARNING* this interface is highly subject to change
7096: *
7097: * Returns the attribute declaration.
7098: */
7099: static xmlSchemaBasicItemPtr
7100: xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7101: xmlSchemaPtr schema,
7102: xmlNodePtr node,
7103: xmlSchemaItemListPtr uses,
7104: int parentType)
7105: {
7106: const xmlChar *attrValue, *name = NULL, *ns = NULL;
7107: xmlSchemaAttributeUsePtr use = NULL;
7108: xmlNodePtr child = NULL;
7109: xmlAttrPtr attr;
7110: const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7111: int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7112: int nberrors, hasForm = 0, defValueType = 0;
7113:
7114: #define WXS_ATTR_DEF_VAL_DEFAULT 1
7115: #define WXS_ATTR_DEF_VAL_FIXED 2
7116:
7117: /*
7118: * 3.2.3 Constraints on XML Representations of Attribute Declarations
7119: */
7120:
7121: if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7122: return (NULL);
7123: attr = xmlSchemaGetPropNode(node, "ref");
7124: if (attr != NULL) {
7125: if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7126: NULL, attr, &tmpNs, &tmpName) != 0) {
7127: return (NULL);
7128: }
7129: if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7130: return(NULL);
7131: isRef = 1;
7132: }
7133: nberrors = pctxt->nberrors;
7134: /*
7135: * Check for illegal attributes.
7136: */
7137: attr = node->properties;
7138: while (attr != NULL) {
7139: if (attr->ns == NULL) {
7140: if (isRef) {
7141: if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7142: xmlSchemaPValAttrNodeID(pctxt, attr);
7143: goto attr_next;
7144: } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7145: goto attr_next;
7146: }
7147: } else {
7148: if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7149: goto attr_next;
7150: } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7151: xmlSchemaPValAttrNodeID(pctxt, attr);
7152: goto attr_next;
7153: } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7154: xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7155: attr, &tmpNs, &tmpName);
7156: goto attr_next;
7157: } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7158: /*
7159: * Evaluate the target namespace
7160: */
7161: hasForm = 1;
7162: attrValue = xmlSchemaGetNodeContent(pctxt,
7163: (xmlNodePtr) attr);
7164: if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7165: ns = pctxt->targetNamespace;
7166: } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7167: {
7168: xmlSchemaPSimpleTypeErr(pctxt,
7169: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7170: NULL, (xmlNodePtr) attr,
7171: NULL, "(qualified | unqualified)",
7172: attrValue, NULL, NULL, NULL);
7173: }
7174: goto attr_next;
7175: }
7176: }
7177: if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7178:
7179: attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7180: /* TODO: Maybe we need to normalize the value beforehand. */
7181: if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7182: occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7183: else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7184: occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7185: else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7186: occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7187: else {
7188: xmlSchemaPSimpleTypeErr(pctxt,
7189: XML_SCHEMAP_INVALID_ATTR_USE,
7190: NULL, (xmlNodePtr) attr,
7191: NULL, "(optional | prohibited | required)",
7192: attrValue, NULL, NULL, NULL);
7193: }
7194: goto attr_next;
7195: } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7196: /*
7197: * 3.2.3 : 1
7198: * default and fixed must not both be present.
7199: */
7200: if (defValue) {
7201: xmlSchemaPMutualExclAttrErr(pctxt,
7202: XML_SCHEMAP_SRC_ATTRIBUTE_1,
7203: NULL, attr, "default", "fixed");
7204: } else {
7205: defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7206: defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7207: }
7208: goto attr_next;
7209: } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7210: /*
7211: * 3.2.3 : 1
7212: * default and fixed must not both be present.
7213: */
7214: if (defValue) {
7215: xmlSchemaPMutualExclAttrErr(pctxt,
7216: XML_SCHEMAP_SRC_ATTRIBUTE_1,
7217: NULL, attr, "default", "fixed");
7218: } else {
7219: defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7220: defValueType = WXS_ATTR_DEF_VAL_FIXED;
7221: }
7222: goto attr_next;
7223: }
7224: } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7225: goto attr_next;
7226:
7227: xmlSchemaPIllegalAttrErr(pctxt,
7228: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7229:
7230: attr_next:
7231: attr = attr->next;
7232: }
7233: /*
7234: * 3.2.3 : 2
7235: * If default and use are both present, use must have
7236: * the actual value optional.
7237: */
7238: if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7239: (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7240: xmlSchemaPSimpleTypeErr(pctxt,
7241: XML_SCHEMAP_SRC_ATTRIBUTE_2,
7242: NULL, node, NULL,
7243: "(optional | prohibited | required)", NULL,
7244: "The value of the attribute 'use' must be 'optional' "
7245: "if the attribute 'default' is present",
7246: NULL, NULL);
7247: }
7248: /*
7249: * We want correct attributes.
7250: */
7251: if (nberrors != pctxt->nberrors)
7252: return(NULL);
7253: if (! isRef) {
7254: xmlSchemaAttributePtr attrDecl;
7255:
7256: /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7257: if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7258: ns = pctxt->targetNamespace;
7259: /*
7260: * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7261: * TODO: Move this to the component layer.
7262: */
7263: if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7264: xmlSchemaCustomErr(ACTXT_CAST pctxt,
7265: XML_SCHEMAP_NO_XSI,
7266: node, NULL,
7267: "The target namespace must not match '%s'",
7268: xmlSchemaInstanceNs, NULL);
7269: }
7270: attr = xmlSchemaGetPropNode(node, "name");
7271: if (attr == NULL) {
7272: xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7273: NULL, node, "name", NULL);
7274: return (NULL);
7275: }
7276: if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7277: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7278: return (NULL);
7279: }
7280: /*
7281: * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7282: * TODO: Move this to the component layer.
7283: */
7284: if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7285: xmlSchemaPSimpleTypeErr(pctxt,
7286: XML_SCHEMAP_NO_XMLNS,
7287: NULL, (xmlNodePtr) attr,
7288: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7289: "The value of the attribute must not match 'xmlns'",
7290: NULL, NULL);
7291: return (NULL);
7292: }
7293: if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7294: goto check_children;
7295: /*
7296: * Create the attribute use component.
7297: */
7298: use = xmlSchemaAddAttributeUse(pctxt, node);
7299: if (use == NULL)
7300: return(NULL);
7301: use->occurs = occurs;
7302: /*
7303: * Create the attribute declaration.
7304: */
7305: attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7306: if (attrDecl == NULL)
7307: return (NULL);
7308: if (tmpName != NULL) {
7309: attrDecl->typeName = tmpName;
7310: attrDecl->typeNs = tmpNs;
7311: }
7312: use->attrDecl = attrDecl;
7313: /*
7314: * Value constraint.
7315: */
7316: if (defValue != NULL) {
7317: attrDecl->defValue = defValue;
7318: if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7319: attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7320: }
7321: } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7322: xmlSchemaQNameRefPtr ref;
7323:
7324: /*
7325: * Create the attribute use component.
7326: */
7327: use = xmlSchemaAddAttributeUse(pctxt, node);
7328: if (use == NULL)
7329: return(NULL);
7330: /*
7331: * We need to resolve the reference at later stage.
7332: */
7333: WXS_ADD_PENDING(pctxt, use);
7334: use->occurs = occurs;
7335: /*
7336: * Create a QName reference to the attribute declaration.
7337: */
7338: ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7339: tmpName, tmpNs);
7340: if (ref == NULL)
7341: return(NULL);
7342: /*
7343: * Assign the reference. This will be substituted for the
7344: * referenced attribute declaration when the QName is resolved.
7345: */
7346: use->attrDecl = WXS_ATTR_CAST ref;
7347: /*
7348: * Value constraint.
7349: */
7350: if (defValue != NULL)
7351: use->defValue = defValue;
7352: if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7353: use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7354: }
7355:
7356: check_children:
7357: /*
7358: * And now for the children...
7359: */
7360: child = node->children;
7361: if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7362: xmlSchemaAttributeUseProhibPtr prohib;
7363:
7364: if (IS_SCHEMA(child, "annotation")) {
7365: xmlSchemaParseAnnotation(pctxt, child, 0);
7366: child = child->next;
7367: }
7368: if (child != NULL) {
7369: xmlSchemaPContentErr(pctxt,
7370: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7371: NULL, node, child, NULL,
7372: "(annotation?)");
7373: }
7374: /*
7375: * Check for pointlessness of attribute prohibitions.
7376: */
7377: if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7378: xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7379: XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7380: node, NULL,
7381: "Skipping attribute use prohibition, since it is "
7382: "pointless inside an <attributeGroup>",
7383: NULL, NULL, NULL);
7384: return(NULL);
7385: } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7386: xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7387: XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7388: node, NULL,
7389: "Skipping attribute use prohibition, since it is "
7390: "pointless when extending a type",
7391: NULL, NULL, NULL);
7392: return(NULL);
7393: }
7394: if (! isRef) {
7395: tmpName = name;
7396: tmpNs = ns;
7397: }
7398: /*
7399: * Check for duplicate attribute prohibitions.
7400: */
7401: if (uses) {
7402: int i;
7403:
7404: for (i = 0; i < uses->nbItems; i++) {
7405: use = uses->items[i];
7406: if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7407: (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7408: (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7409: {
7410: xmlChar *str = NULL;
7411:
7412: xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7413: XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7414: node, NULL,
7415: "Skipping duplicate attribute use prohibition '%s'",
7416: xmlSchemaFormatQName(&str, tmpNs, tmpName),
7417: NULL, NULL);
7418: FREE_AND_NULL(str)
7419: return(NULL);
7420: }
7421: }
7422: }
7423: /*
7424: * Create the attribute prohibition helper component.
7425: */
7426: prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7427: if (prohib == NULL)
7428: return(NULL);
7429: prohib->node = node;
7430: prohib->name = tmpName;
7431: prohib->targetNamespace = tmpNs;
7432: if (isRef) {
7433: /*
7434: * We need at least to resolve to the attribute declaration.
7435: */
7436: WXS_ADD_PENDING(pctxt, prohib);
7437: }
7438: return(WXS_BASIC_CAST prohib);
7439: } else {
7440: if (IS_SCHEMA(child, "annotation")) {
7441: /*
7442: * TODO: Should this go into the attr decl?
7443: */
7444: use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7445: child = child->next;
7446: }
7447: if (isRef) {
7448: if (child != NULL) {
7449: if (IS_SCHEMA(child, "simpleType"))
7450: /*
7451: * 3.2.3 : 3.2
7452: * If ref is present, then all of <simpleType>,
7453: * form and type must be absent.
7454: */
7455: xmlSchemaPContentErr(pctxt,
7456: XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7457: NULL, node, child, NULL,
7458: "(annotation?)");
7459: else
7460: xmlSchemaPContentErr(pctxt,
7461: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7462: NULL, node, child, NULL,
7463: "(annotation?)");
7464: }
7465: } else {
7466: if (IS_SCHEMA(child, "simpleType")) {
7467: if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7468: /*
7469: * 3.2.3 : 4
7470: * type and <simpleType> must not both be present.
7471: */
7472: xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7473: NULL, node, child,
7474: "The attribute 'type' and the <simpleType> child "
7475: "are mutually exclusive", NULL);
7476: } else
7477: WXS_ATTRUSE_TYPEDEF(use) =
7478: xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7479: child = child->next;
7480: }
7481: if (child != NULL)
7482: xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7483: NULL, node, child, NULL,
7484: "(annotation?, simpleType?)");
7485: }
7486: }
7487: return (WXS_BASIC_CAST use);
7488: }
7489:
7490:
7491: static xmlSchemaAttributePtr
7492: xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7493: xmlSchemaPtr schema,
7494: xmlNodePtr node)
7495: {
7496: const xmlChar *attrValue;
7497: xmlSchemaAttributePtr ret;
7498: xmlNodePtr child = NULL;
7499: xmlAttrPtr attr;
7500:
7501: /*
7502: * Note that the w3c spec assumes the schema to be validated with schema
7503: * for schemas beforehand.
7504: *
7505: * 3.2.3 Constraints on XML Representations of Attribute Declarations
7506: */
7507: if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7508: return (NULL);
7509: /*
7510: * 3.2.3 : 3.1
7511: * One of ref or name must be present, but not both
7512: */
7513: attr = xmlSchemaGetPropNode(node, "name");
7514: if (attr == NULL) {
7515: xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7516: NULL, node, "name", NULL);
7517: return (NULL);
7518: }
7519: if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7520: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7521: return (NULL);
7522: }
7523: /*
7524: * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7525: * TODO: Move this to the component layer.
7526: */
7527: if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7528: xmlSchemaPSimpleTypeErr(pctxt,
7529: XML_SCHEMAP_NO_XMLNS,
7530: NULL, (xmlNodePtr) attr,
7531: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7532: "The value of the attribute must not match 'xmlns'",
7533: NULL, NULL);
7534: return (NULL);
7535: }
7536: /*
7537: * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7538: * TODO: Move this to the component layer.
7539: * Or better leave it here and add it to the component layer
7540: * if we have a schema construction API.
7541: */
7542: if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7543: xmlSchemaCustomErr(ACTXT_CAST pctxt,
7544: XML_SCHEMAP_NO_XSI, node, NULL,
7545: "The target namespace must not match '%s'",
7546: xmlSchemaInstanceNs, NULL);
7547: }
7548:
7549: ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7550: pctxt->targetNamespace, node, 1);
7551: if (ret == NULL)
7552: return (NULL);
7553: ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7554:
7555: /*
7556: * Check for illegal attributes.
7557: */
7558: attr = node->properties;
7559: while (attr != NULL) {
7560: if (attr->ns == NULL) {
7561: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7562: (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7563: (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7564: (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7565: (!xmlStrEqual(attr->name, BAD_CAST "type")))
7566: {
7567: xmlSchemaPIllegalAttrErr(pctxt,
7568: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7569: }
7570: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7571: xmlSchemaPIllegalAttrErr(pctxt,
7572: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7573: }
7574: attr = attr->next;
7575: }
7576: xmlSchemaPValAttrQName(pctxt, schema, NULL,
7577: node, "type", &ret->typeNs, &ret->typeName);
7578:
7579: xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7580: /*
7581: * Attribute "fixed".
7582: */
7583: ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7584: if (ret->defValue != NULL)
7585: ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7586: /*
7587: * Attribute "default".
7588: */
7589: attr = xmlSchemaGetPropNode(node, "default");
7590: if (attr != NULL) {
7591: /*
7592: * 3.2.3 : 1
7593: * default and fixed must not both be present.
7594: */
7595: if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7596: xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7597: WXS_BASIC_CAST ret, attr, "default", "fixed");
7598: } else
7599: ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7600: }
7601: /*
7602: * And now for the children...
7603: */
7604: child = node->children;
7605: if (IS_SCHEMA(child, "annotation")) {
7606: ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7607: child = child->next;
7608: }
7609: if (IS_SCHEMA(child, "simpleType")) {
7610: if (ret->typeName != NULL) {
7611: /*
7612: * 3.2.3 : 4
7613: * type and <simpleType> must not both be present.
7614: */
7615: xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7616: NULL, node, child,
7617: "The attribute 'type' and the <simpleType> child "
7618: "are mutually exclusive", NULL);
7619: } else
7620: ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7621: child = child->next;
7622: }
7623: if (child != NULL)
7624: xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7625: NULL, node, child, NULL,
7626: "(annotation?, simpleType?)");
7627:
7628: return (ret);
7629: }
7630:
7631: /**
7632: * xmlSchemaParseAttributeGroupRef:
7633: * @ctxt: a schema validation context
7634: * @schema: the schema being built
7635: * @node: a subtree containing XML Schema informations
7636: *
7637: * Parse an attribute group definition reference.
7638: * Note that a reference to an attribute group does not
7639: * correspond to any component at all.
7640: * *WARNING* this interface is highly subject to change
7641: *
7642: * Returns the attribute group or NULL in case of error.
7643: */
7644: static xmlSchemaQNameRefPtr
7645: xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7646: xmlSchemaPtr schema,
7647: xmlNodePtr node)
7648: {
7649: xmlSchemaQNameRefPtr ret;
7650: xmlNodePtr child = NULL;
7651: xmlAttrPtr attr;
7652: const xmlChar *refNs = NULL, *ref = NULL;
7653:
7654: if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7655: return (NULL);
7656:
7657: attr = xmlSchemaGetPropNode(node, "ref");
7658: if (attr == NULL) {
7659: xmlSchemaPMissingAttrErr(pctxt,
7660: XML_SCHEMAP_S4S_ATTR_MISSING,
7661: NULL, node, "ref", NULL);
7662: return (NULL);
7663: }
7664: xmlSchemaPValAttrNodeQName(pctxt, schema,
7665: NULL, attr, &refNs, &ref);
7666: if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7667: return(NULL);
7668:
7669: /*
7670: * Check for illegal attributes.
7671: */
7672: attr = node->properties;
7673: while (attr != NULL) {
7674: if (attr->ns == NULL) {
7675: if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7676: (!xmlStrEqual(attr->name, BAD_CAST "id")))
7677: {
7678: xmlSchemaPIllegalAttrErr(pctxt,
7679: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7680: }
7681: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7682: xmlSchemaPIllegalAttrErr(pctxt,
7683: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7684: }
7685: attr = attr->next;
7686: }
7687: /* Attribute ID */
7688: xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7689:
7690: /*
7691: * And now for the children...
7692: */
7693: child = node->children;
7694: if (IS_SCHEMA(child, "annotation")) {
7695: /*
7696: * TODO: We do not have a place to store the annotation, do we?
7697: */
7698: xmlSchemaParseAnnotation(pctxt, child, 0);
7699: child = child->next;
7700: }
7701: if (child != NULL) {
7702: xmlSchemaPContentErr(pctxt,
7703: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7704: NULL, node, child, NULL,
7705: "(annotation?)");
7706: }
7707:
7708: /*
7709: * Handle attribute group redefinitions.
7710: */
7711: if (pctxt->isRedefine && pctxt->redef &&
7712: (pctxt->redef->item->type ==
7713: XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7714: (ref == pctxt->redef->refName) &&
7715: (refNs == pctxt->redef->refTargetNs))
7716: {
7717: /*
7718: * SPEC src-redefine:
7719: * (7.1) "If it has an <attributeGroup> among its contents
7720: * the �actual value� of whose ref [attribute] is the same
7721: * as the �actual value� of its own name attribute plus
7722: * target namespace, then it must have exactly one such group."
7723: */
7724: if (pctxt->redefCounter != 0) {
7725: xmlChar *str = NULL;
7726:
7727: xmlSchemaCustomErr(ACTXT_CAST pctxt,
7728: XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7729: "The redefining attribute group definition "
7730: "'%s' must not contain more than one "
7731: "reference to the redefined definition",
7732: xmlSchemaFormatQName(&str, refNs, ref), NULL);
7733: FREE_AND_NULL(str);
7734: return(NULL);
7735: }
7736: pctxt->redefCounter++;
7737: /*
7738: * URGENT TODO: How to ensure that the reference will not be
7739: * handled by the normal component resolution mechanism?
7740: */
7741: ret = xmlSchemaNewQNameRef(pctxt,
7742: XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7743: if (ret == NULL)
7744: return(NULL);
7745: ret->node = node;
7746: pctxt->redef->reference = WXS_BASIC_CAST ret;
7747: } else {
7748: /*
7749: * Create a QName-reference helper component. We will substitute this
7750: * component for the attribute uses of the referenced attribute group
7751: * definition.
7752: */
7753: ret = xmlSchemaNewQNameRef(pctxt,
7754: XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7755: if (ret == NULL)
7756: return(NULL);
7757: ret->node = node;
7758: /* Add to pending items, to be able to resolve the reference. */
7759: WXS_ADD_PENDING(pctxt, ret);
7760: }
7761: return (ret);
7762: }
7763:
7764: /**
7765: * xmlSchemaParseAttributeGroupDefinition:
7766: * @pctxt: a schema validation context
7767: * @schema: the schema being built
7768: * @node: a subtree containing XML Schema informations
7769: *
7770: * parse a XML schema Attribute Group declaration
7771: * *WARNING* this interface is highly subject to change
7772: *
7773: * Returns the attribute group definition or NULL in case of error.
7774: */
7775: static xmlSchemaAttributeGroupPtr
7776: xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7777: xmlSchemaPtr schema,
7778: xmlNodePtr node)
7779: {
7780: const xmlChar *name;
7781: xmlSchemaAttributeGroupPtr ret;
7782: xmlNodePtr child = NULL;
7783: xmlAttrPtr attr;
7784: int hasRefs = 0;
7785:
7786: if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7787: return (NULL);
7788:
7789: attr = xmlSchemaGetPropNode(node, "name");
7790: if (attr == NULL) {
7791: xmlSchemaPMissingAttrErr(pctxt,
7792: XML_SCHEMAP_S4S_ATTR_MISSING,
7793: NULL, node, "name", NULL);
7794: return (NULL);
7795: }
7796: /*
7797: * The name is crucial, exit if invalid.
7798: */
7799: if (xmlSchemaPValAttrNode(pctxt,
7800: NULL, attr,
7801: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7802: return (NULL);
7803: }
7804: ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7805: name, pctxt->targetNamespace, node);
7806: if (ret == NULL)
7807: return (NULL);
7808: /*
7809: * Check for illegal attributes.
7810: */
7811: attr = node->properties;
7812: while (attr != NULL) {
7813: if (attr->ns == NULL) {
7814: if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7815: (!xmlStrEqual(attr->name, BAD_CAST "id")))
7816: {
7817: xmlSchemaPIllegalAttrErr(pctxt,
7818: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7819: }
7820: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7821: xmlSchemaPIllegalAttrErr(pctxt,
7822: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7823: }
7824: attr = attr->next;
7825: }
7826: /* Attribute ID */
7827: xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7828: /*
7829: * And now for the children...
7830: */
7831: child = node->children;
7832: if (IS_SCHEMA(child, "annotation")) {
7833: ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7834: child = child->next;
7835: }
7836: /*
7837: * Parse contained attribute decls/refs.
7838: */
7839: if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7840: (xmlSchemaItemListPtr *) &(ret->attrUses),
7841: XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7842: return(NULL);
7843: if (hasRefs)
7844: ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7845: /*
7846: * Parse the attribute wildcard.
7847: */
7848: if (IS_SCHEMA(child, "anyAttribute")) {
7849: ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7850: schema, child);
7851: child = child->next;
7852: }
7853: if (child != NULL) {
7854: xmlSchemaPContentErr(pctxt,
7855: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7856: NULL, node, child, NULL,
7857: "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7858: }
7859: return (ret);
7860: }
7861:
7862: /**
7863: * xmlSchemaPValAttrFormDefault:
7864: * @value: the value
7865: * @flags: the flags to be modified
7866: * @flagQualified: the specific flag for "qualified"
7867: *
7868: * Returns 0 if the value is valid, 1 otherwise.
7869: */
7870: static int
7871: xmlSchemaPValAttrFormDefault(const xmlChar *value,
7872: int *flags,
7873: int flagQualified)
7874: {
7875: if (xmlStrEqual(value, BAD_CAST "qualified")) {
7876: if ((*flags & flagQualified) == 0)
7877: *flags |= flagQualified;
7878: } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7879: return (1);
7880:
7881: return (0);
7882: }
7883:
7884: /**
7885: * xmlSchemaPValAttrBlockFinal:
7886: * @value: the value
7887: * @flags: the flags to be modified
7888: * @flagAll: the specific flag for "#all"
7889: * @flagExtension: the specific flag for "extension"
7890: * @flagRestriction: the specific flag for "restriction"
7891: * @flagSubstitution: the specific flag for "substitution"
7892: * @flagList: the specific flag for "list"
7893: * @flagUnion: the specific flag for "union"
7894: *
7895: * Validates the value of the attribute "final" and "block". The value
7896: * is converted into the specified flag values and returned in @flags.
7897: *
7898: * Returns 0 if the value is valid, 1 otherwise.
7899: */
7900:
7901: static int
7902: xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7903: int *flags,
7904: int flagAll,
7905: int flagExtension,
7906: int flagRestriction,
7907: int flagSubstitution,
7908: int flagList,
7909: int flagUnion)
7910: {
7911: int ret = 0;
7912:
7913: /*
7914: * TODO: This does not check for dublicate entries.
7915: */
7916: if ((flags == NULL) || (value == NULL))
7917: return (-1);
7918: if (value[0] == 0)
7919: return (0);
7920: if (xmlStrEqual(value, BAD_CAST "#all")) {
7921: if (flagAll != -1)
7922: *flags |= flagAll;
7923: else {
7924: if (flagExtension != -1)
7925: *flags |= flagExtension;
7926: if (flagRestriction != -1)
7927: *flags |= flagRestriction;
7928: if (flagSubstitution != -1)
7929: *flags |= flagSubstitution;
7930: if (flagList != -1)
7931: *flags |= flagList;
7932: if (flagUnion != -1)
7933: *flags |= flagUnion;
7934: }
7935: } else {
7936: const xmlChar *end, *cur = value;
7937: xmlChar *item;
7938:
7939: do {
7940: while (IS_BLANK_CH(*cur))
7941: cur++;
7942: end = cur;
7943: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7944: end++;
7945: if (end == cur)
7946: break;
7947: item = xmlStrndup(cur, end - cur);
7948: if (xmlStrEqual(item, BAD_CAST "extension")) {
7949: if (flagExtension != -1) {
7950: if ((*flags & flagExtension) == 0)
7951: *flags |= flagExtension;
7952: } else
7953: ret = 1;
7954: } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7955: if (flagRestriction != -1) {
7956: if ((*flags & flagRestriction) == 0)
7957: *flags |= flagRestriction;
7958: } else
7959: ret = 1;
7960: } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7961: if (flagSubstitution != -1) {
7962: if ((*flags & flagSubstitution) == 0)
7963: *flags |= flagSubstitution;
7964: } else
7965: ret = 1;
7966: } else if (xmlStrEqual(item, BAD_CAST "list")) {
7967: if (flagList != -1) {
7968: if ((*flags & flagList) == 0)
7969: *flags |= flagList;
7970: } else
7971: ret = 1;
7972: } else if (xmlStrEqual(item, BAD_CAST "union")) {
7973: if (flagUnion != -1) {
7974: if ((*flags & flagUnion) == 0)
7975: *flags |= flagUnion;
7976: } else
7977: ret = 1;
7978: } else
7979: ret = 1;
7980: if (item != NULL)
7981: xmlFree(item);
7982: cur = end;
7983: } while ((ret == 0) && (*cur != 0));
7984: }
7985:
7986: return (ret);
7987: }
7988:
7989: static int
7990: xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7991: xmlSchemaIDCPtr idc,
7992: xmlSchemaIDCSelectPtr selector,
7993: xmlAttrPtr attr,
7994: int isField)
7995: {
7996: xmlNodePtr node;
7997:
7998: /*
7999: * c-selector-xpath:
8000: * Schema Component Constraint: Selector Value OK
8001: *
8002: * TODO: 1 The {selector} must be a valid XPath expression, as defined
8003: * in [XPath].
8004: */
8005: if (selector == NULL) {
8006: xmlSchemaPErr(ctxt, idc->node,
8007: XML_SCHEMAP_INTERNAL,
8008: "Internal error: xmlSchemaCheckCSelectorXPath, "
8009: "the selector is not specified.\n", NULL, NULL);
8010: return (-1);
8011: }
8012: if (attr == NULL)
8013: node = idc->node;
8014: else
8015: node = (xmlNodePtr) attr;
8016: if (selector->xpath == NULL) {
8017: xmlSchemaPCustomErr(ctxt,
8018: /* TODO: Adjust error code. */
8019: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8020: NULL, node,
8021: "The XPath expression of the selector is not valid", NULL);
8022: return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8023: } else {
8024: const xmlChar **nsArray = NULL;
8025: xmlNsPtr *nsList = NULL;
8026: /*
8027: * Compile the XPath expression.
8028: */
8029: /*
8030: * TODO: We need the array of in-scope namespaces for compilation.
8031: * TODO: Call xmlPatterncompile with different options for selector/
8032: * field.
8033: */
8034: if (attr == NULL)
8035: nsList = NULL;
8036: else
8037: nsList = xmlGetNsList(attr->doc, attr->parent);
8038: /*
8039: * Build an array of prefixes and namespaces.
8040: */
8041: if (nsList != NULL) {
8042: int i, count = 0;
8043:
8044: for (i = 0; nsList[i] != NULL; i++)
8045: count++;
8046:
8047: nsArray = (const xmlChar **) xmlMalloc(
8048: (count * 2 + 1) * sizeof(const xmlChar *));
8049: if (nsArray == NULL) {
8050: xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8051: NULL);
8052: xmlFree(nsList);
8053: return (-1);
8054: }
8055: for (i = 0; i < count; i++) {
8056: nsArray[2 * i] = nsList[i]->href;
8057: nsArray[2 * i + 1] = nsList[i]->prefix;
8058: }
8059: nsArray[count * 2] = NULL;
8060: xmlFree(nsList);
8061: }
8062: /*
8063: * TODO: Differentiate between "selector" and "field".
8064: */
8065: if (isField)
8066: selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8067: NULL, XML_PATTERN_XSFIELD, nsArray);
8068: else
8069: selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8070: NULL, XML_PATTERN_XSSEL, nsArray);
8071: if (nsArray != NULL)
8072: xmlFree((xmlChar **) nsArray);
8073:
8074: if (selector->xpathComp == NULL) {
8075: xmlSchemaPCustomErr(ctxt,
8076: /* TODO: Adjust error code? */
8077: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8078: NULL, node,
8079: "The XPath expression '%s' could not be "
8080: "compiled", selector->xpath);
8081: return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8082: }
8083: }
8084: return (0);
8085: }
8086:
8087: #define ADD_ANNOTATION(annot) \
8088: xmlSchemaAnnotPtr cur = item->annot; \
8089: if (item->annot == NULL) { \
8090: item->annot = annot; \
8091: return (annot); \
8092: } \
8093: cur = item->annot; \
8094: if (cur->next != NULL) { \
8095: cur = cur->next; \
8096: } \
8097: cur->next = annot;
8098:
8099: /**
8100: * xmlSchemaAssignAnnotation:
8101: * @item: the schema component
8102: * @annot: the annotation
8103: *
8104: * Adds the annotation to the given schema component.
8105: *
8106: * Returns the given annotaion.
8107: */
8108: static xmlSchemaAnnotPtr
8109: xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8110: xmlSchemaAnnotPtr annot)
8111: {
8112: if ((annItem == NULL) || (annot == NULL))
8113: return (NULL);
8114: switch (annItem->type) {
8115: case XML_SCHEMA_TYPE_ELEMENT: {
8116: xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8117: ADD_ANNOTATION(annot)
8118: }
8119: break;
8120: case XML_SCHEMA_TYPE_ATTRIBUTE: {
8121: xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8122: ADD_ANNOTATION(annot)
8123: }
8124: break;
8125: case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8126: case XML_SCHEMA_TYPE_ANY: {
8127: xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8128: ADD_ANNOTATION(annot)
8129: }
8130: break;
8131: case XML_SCHEMA_TYPE_PARTICLE:
8132: case XML_SCHEMA_TYPE_IDC_KEY:
8133: case XML_SCHEMA_TYPE_IDC_KEYREF:
8134: case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8135: xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8136: ADD_ANNOTATION(annot)
8137: }
8138: break;
8139: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8140: xmlSchemaAttributeGroupPtr item =
8141: (xmlSchemaAttributeGroupPtr) annItem;
8142: ADD_ANNOTATION(annot)
8143: }
8144: break;
8145: case XML_SCHEMA_TYPE_NOTATION: {
8146: xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8147: ADD_ANNOTATION(annot)
8148: }
8149: break;
8150: case XML_SCHEMA_FACET_MININCLUSIVE:
8151: case XML_SCHEMA_FACET_MINEXCLUSIVE:
8152: case XML_SCHEMA_FACET_MAXINCLUSIVE:
8153: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8154: case XML_SCHEMA_FACET_TOTALDIGITS:
8155: case XML_SCHEMA_FACET_FRACTIONDIGITS:
8156: case XML_SCHEMA_FACET_PATTERN:
8157: case XML_SCHEMA_FACET_ENUMERATION:
8158: case XML_SCHEMA_FACET_WHITESPACE:
8159: case XML_SCHEMA_FACET_LENGTH:
8160: case XML_SCHEMA_FACET_MAXLENGTH:
8161: case XML_SCHEMA_FACET_MINLENGTH: {
8162: xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8163: ADD_ANNOTATION(annot)
8164: }
8165: break;
8166: case XML_SCHEMA_TYPE_SIMPLE:
8167: case XML_SCHEMA_TYPE_COMPLEX: {
8168: xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8169: ADD_ANNOTATION(annot)
8170: }
8171: break;
8172: case XML_SCHEMA_TYPE_GROUP: {
8173: xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8174: ADD_ANNOTATION(annot)
8175: }
8176: break;
8177: case XML_SCHEMA_TYPE_SEQUENCE:
8178: case XML_SCHEMA_TYPE_CHOICE:
8179: case XML_SCHEMA_TYPE_ALL: {
8180: xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8181: ADD_ANNOTATION(annot)
8182: }
8183: break;
8184: default:
8185: xmlSchemaPCustomErr(NULL,
8186: XML_SCHEMAP_INTERNAL,
8187: NULL, NULL,
8188: "Internal error: xmlSchemaAddAnnotation, "
8189: "The item is not a annotated schema component", NULL);
8190: break;
8191: }
8192: return (annot);
8193: }
8194:
8195: /**
8196: * xmlSchemaParseIDCSelectorAndField:
8197: * @ctxt: a schema validation context
8198: * @schema: the schema being built
8199: * @node: a subtree containing XML Schema informations
8200: *
8201: * Parses a XML Schema identity-contraint definition's
8202: * <selector> and <field> elements.
8203: *
8204: * Returns the parsed identity-constraint definition.
8205: */
8206: static xmlSchemaIDCSelectPtr
8207: xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8208: xmlSchemaIDCPtr idc,
8209: xmlNodePtr node,
8210: int isField)
8211: {
8212: xmlSchemaIDCSelectPtr item;
8213: xmlNodePtr child = NULL;
8214: xmlAttrPtr attr;
8215:
8216: /*
8217: * Check for illegal attributes.
8218: */
8219: attr = node->properties;
8220: while (attr != NULL) {
8221: if (attr->ns == NULL) {
8222: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8223: (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8224: xmlSchemaPIllegalAttrErr(ctxt,
8225: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8226: }
8227: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8228: xmlSchemaPIllegalAttrErr(ctxt,
8229: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8230: }
8231: attr = attr->next;
8232: }
8233: /*
8234: * Create the item.
8235: */
8236: item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8237: if (item == NULL) {
8238: xmlSchemaPErrMemory(ctxt,
8239: "allocating a 'selector' of an identity-constraint definition",
8240: NULL);
8241: return (NULL);
8242: }
8243: memset(item, 0, sizeof(xmlSchemaIDCSelect));
8244: /*
8245: * Attribute "xpath" (mandatory).
8246: */
8247: attr = xmlSchemaGetPropNode(node, "xpath");
8248: if (attr == NULL) {
1.1.1.3 ! misho 8249: xmlSchemaPMissingAttrErr(ctxt,
1.1 misho 8250: XML_SCHEMAP_S4S_ATTR_MISSING,
8251: NULL, node,
8252: "name", NULL);
8253: } else {
8254: item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8255: /*
8256: * URGENT TODO: "field"s have an other syntax than "selector"s.
8257: */
8258:
8259: if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8260: isField) == -1) {
8261: xmlSchemaPErr(ctxt,
8262: (xmlNodePtr) attr,
8263: XML_SCHEMAP_INTERNAL,
8264: "Internal error: xmlSchemaParseIDCSelectorAndField, "
8265: "validating the XPath expression of a IDC selector.\n",
8266: NULL, NULL);
8267: }
8268:
8269: }
8270: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8271: /*
8272: * And now for the children...
8273: */
8274: child = node->children;
8275: if (IS_SCHEMA(child, "annotation")) {
8276: /*
8277: * Add the annotation to the parent IDC.
8278: */
8279: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8280: xmlSchemaParseAnnotation(ctxt, child, 1));
8281: child = child->next;
8282: }
8283: if (child != NULL) {
8284: xmlSchemaPContentErr(ctxt,
8285: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8286: NULL, node, child,
8287: NULL, "(annotation?)");
8288: }
8289:
8290: return (item);
8291: }
8292:
8293: /**
8294: * xmlSchemaParseIDC:
8295: * @ctxt: a schema validation context
8296: * @schema: the schema being built
8297: * @node: a subtree containing XML Schema informations
8298: *
8299: * Parses a XML Schema identity-contraint definition.
8300: *
8301: * Returns the parsed identity-constraint definition.
8302: */
8303: static xmlSchemaIDCPtr
8304: xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8305: xmlSchemaPtr schema,
8306: xmlNodePtr node,
8307: xmlSchemaTypeType idcCategory,
8308: const xmlChar *targetNamespace)
8309: {
8310: xmlSchemaIDCPtr item = NULL;
8311: xmlNodePtr child = NULL;
8312: xmlAttrPtr attr;
8313: const xmlChar *name = NULL;
8314: xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8315:
8316: /*
8317: * Check for illegal attributes.
8318: */
8319: attr = node->properties;
8320: while (attr != NULL) {
8321: if (attr->ns == NULL) {
8322: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8323: (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8324: ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8325: (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8326: xmlSchemaPIllegalAttrErr(ctxt,
8327: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8328: }
8329: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8330: xmlSchemaPIllegalAttrErr(ctxt,
8331: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8332: }
8333: attr = attr->next;
8334: }
8335: /*
8336: * Attribute "name" (mandatory).
8337: */
8338: attr = xmlSchemaGetPropNode(node, "name");
8339: if (attr == NULL) {
8340: xmlSchemaPMissingAttrErr(ctxt,
8341: XML_SCHEMAP_S4S_ATTR_MISSING,
8342: NULL, node,
8343: "name", NULL);
8344: return (NULL);
8345: } else if (xmlSchemaPValAttrNode(ctxt,
8346: NULL, attr,
8347: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8348: return (NULL);
8349: }
8350: /* Create the component. */
8351: item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8352: idcCategory, node);
8353: if (item == NULL)
8354: return(NULL);
8355:
8356: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8357: if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8358: /*
8359: * Attribute "refer" (mandatory).
8360: */
8361: attr = xmlSchemaGetPropNode(node, "refer");
8362: if (attr == NULL) {
8363: xmlSchemaPMissingAttrErr(ctxt,
8364: XML_SCHEMAP_S4S_ATTR_MISSING,
8365: NULL, node,
8366: "refer", NULL);
8367: } else {
8368: /*
8369: * Create a reference item.
8370: */
8371: item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8372: NULL, NULL);
8373: if (item->ref == NULL)
8374: return (NULL);
8375: xmlSchemaPValAttrNodeQName(ctxt, schema,
8376: NULL, attr,
8377: &(item->ref->targetNamespace),
8378: &(item->ref->name));
8379: xmlSchemaCheckReference(ctxt, schema, node, attr,
8380: item->ref->targetNamespace);
8381: }
8382: }
8383: /*
8384: * And now for the children...
8385: */
8386: child = node->children;
8387: if (IS_SCHEMA(child, "annotation")) {
8388: item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8389: child = child->next;
8390: }
8391: if (child == NULL) {
8392: xmlSchemaPContentErr(ctxt,
8393: XML_SCHEMAP_S4S_ELEM_MISSING,
8394: NULL, node, child,
8395: "A child element is missing",
8396: "(annotation?, (selector, field+))");
8397: }
8398: /*
8399: * Child element <selector>.
8400: */
8401: if (IS_SCHEMA(child, "selector")) {
8402: item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8403: item, child, 0);
8404: child = child->next;
8405: /*
8406: * Child elements <field>.
8407: */
8408: if (IS_SCHEMA(child, "field")) {
8409: do {
8410: field = xmlSchemaParseIDCSelectorAndField(ctxt,
8411: item, child, 1);
8412: if (field != NULL) {
8413: field->index = item->nbFields;
8414: item->nbFields++;
8415: if (lastField != NULL)
8416: lastField->next = field;
8417: else
8418: item->fields = field;
8419: lastField = field;
8420: }
8421: child = child->next;
8422: } while (IS_SCHEMA(child, "field"));
8423: } else {
8424: xmlSchemaPContentErr(ctxt,
8425: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8426: NULL, node, child,
8427: NULL, "(annotation?, (selector, field+))");
8428: }
8429: }
8430: if (child != NULL) {
8431: xmlSchemaPContentErr(ctxt,
8432: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8433: NULL, node, child,
8434: NULL, "(annotation?, (selector, field+))");
8435: }
8436:
8437: return (item);
8438: }
8439:
8440: /**
8441: * xmlSchemaParseElement:
8442: * @ctxt: a schema validation context
8443: * @schema: the schema being built
8444: * @node: a subtree containing XML Schema informations
8445: * @topLevel: indicates if this is global declaration
8446: *
8447: * Parses a XML schema element declaration.
8448: * *WARNING* this interface is highly subject to change
8449: *
8450: * Returns the element declaration or a particle; NULL in case
8451: * of an error or if the particle has minOccurs==maxOccurs==0.
8452: */
8453: static xmlSchemaBasicItemPtr
8454: xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8455: xmlNodePtr node, int *isElemRef, int topLevel)
8456: {
8457: xmlSchemaElementPtr decl = NULL;
8458: xmlSchemaParticlePtr particle = NULL;
8459: xmlSchemaAnnotPtr annot = NULL;
8460: xmlNodePtr child = NULL;
8461: xmlAttrPtr attr, nameAttr;
8462: int min, max, isRef = 0;
8463: xmlChar *des = NULL;
8464:
8465: /* 3.3.3 Constraints on XML Representations of Element Declarations */
8466: /* TODO: Complete implementation of 3.3.6 */
8467:
8468: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8469: return (NULL);
8470:
8471: if (isElemRef != NULL)
8472: *isElemRef = 0;
8473: /*
8474: * If we get a "ref" attribute on a local <element> we will assume it's
8475: * a reference - even if there's a "name" attribute; this seems to be more
8476: * robust.
8477: */
8478: nameAttr = xmlSchemaGetPropNode(node, "name");
8479: attr = xmlSchemaGetPropNode(node, "ref");
8480: if ((topLevel) || (attr == NULL)) {
8481: if (nameAttr == NULL) {
8482: xmlSchemaPMissingAttrErr(ctxt,
8483: XML_SCHEMAP_S4S_ATTR_MISSING,
8484: NULL, node, "name", NULL);
8485: return (NULL);
8486: }
8487: } else
8488: isRef = 1;
8489:
8490: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8491: child = node->children;
8492: if (IS_SCHEMA(child, "annotation")) {
8493: annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8494: child = child->next;
8495: }
8496: /*
8497: * Skip particle part if a global declaration.
8498: */
8499: if (topLevel)
8500: goto declaration_part;
8501: /*
8502: * The particle part ==================================================
8503: */
8504: min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8505: max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8506: xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8507: particle = xmlSchemaAddParticle(ctxt, node, min, max);
8508: if (particle == NULL)
8509: goto return_null;
8510:
8511: /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8512:
8513: if (isRef) {
8514: const xmlChar *refNs = NULL, *ref = NULL;
8515: xmlSchemaQNameRefPtr refer = NULL;
8516: /*
8517: * The reference part =============================================
8518: */
8519: if (isElemRef != NULL)
8520: *isElemRef = 1;
8521:
8522: xmlSchemaPValAttrNodeQName(ctxt, schema,
8523: NULL, attr, &refNs, &ref);
8524: xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8525: /*
8526: * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8527: */
8528: if (nameAttr != NULL) {
8529: xmlSchemaPMutualExclAttrErr(ctxt,
8530: XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8531: }
8532: /*
8533: * Check for illegal attributes.
8534: */
8535: attr = node->properties;
8536: while (attr != NULL) {
8537: if (attr->ns == NULL) {
8538: if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8539: xmlStrEqual(attr->name, BAD_CAST "name") ||
8540: xmlStrEqual(attr->name, BAD_CAST "id") ||
8541: xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8542: xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8543: {
8544: attr = attr->next;
8545: continue;
8546: } else {
8547: /* SPEC (3.3.3 : 2.2) */
8548: xmlSchemaPCustomAttrErr(ctxt,
8549: XML_SCHEMAP_SRC_ELEMENT_2_2,
8550: NULL, NULL, attr,
8551: "Only the attributes 'minOccurs', 'maxOccurs' and "
8552: "'id' are allowed in addition to 'ref'");
8553: break;
8554: }
8555: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8556: xmlSchemaPIllegalAttrErr(ctxt,
8557: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8558: }
8559: attr = attr->next;
8560: }
8561: /*
8562: * No children except <annotation> expected.
8563: */
8564: if (child != NULL) {
8565: xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8566: NULL, node, child, NULL, "(annotation?)");
8567: }
8568: if ((min == 0) && (max == 0))
8569: goto return_null;
8570: /*
8571: * Create the reference item and attach it to the particle.
8572: */
8573: refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8574: ref, refNs);
8575: if (refer == NULL)
8576: goto return_null;
8577: particle->children = (xmlSchemaTreeItemPtr) refer;
8578: particle->annot = annot;
8579: /*
8580: * Add the particle to pending components, since the reference
8581: * need to be resolved.
8582: */
8583: WXS_ADD_PENDING(ctxt, particle);
8584: return ((xmlSchemaBasicItemPtr) particle);
8585: }
8586: /*
8587: * The declaration part ===============================================
8588: */
8589: declaration_part:
8590: {
8591: const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8592: xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8593:
8594: if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8595: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8596: goto return_null;
8597: /*
8598: * Evaluate the target namespace.
8599: */
8600: if (topLevel) {
8601: ns = ctxt->targetNamespace;
8602: } else {
8603: attr = xmlSchemaGetPropNode(node, "form");
8604: if (attr != NULL) {
8605: attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8606: if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8607: ns = ctxt->targetNamespace;
8608: } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8609: xmlSchemaPSimpleTypeErr(ctxt,
8610: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8611: NULL, (xmlNodePtr) attr,
8612: NULL, "(qualified | unqualified)",
8613: attrValue, NULL, NULL, NULL);
8614: }
8615: } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8616: ns = ctxt->targetNamespace;
8617: }
8618: decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8619: if (decl == NULL) {
8620: goto return_null;
8621: }
8622: /*
8623: * Check for illegal attributes.
8624: */
8625: attr = node->properties;
8626: while (attr != NULL) {
8627: if (attr->ns == NULL) {
8628: if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8629: (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8630: (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8631: (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8632: (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8633: (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8634: (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8635: {
8636: if (topLevel == 0) {
8637: if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8638: (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8639: (!xmlStrEqual(attr->name, BAD_CAST "form")))
8640: {
8641: xmlSchemaPIllegalAttrErr(ctxt,
8642: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8643: }
8644: } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8645: (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8646: (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8647:
8648: xmlSchemaPIllegalAttrErr(ctxt,
8649: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8650: }
8651: }
8652: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8653:
8654: xmlSchemaPIllegalAttrErr(ctxt,
8655: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8656: }
8657: attr = attr->next;
8658: }
8659: /*
8660: * Extract/validate attributes.
8661: */
8662: if (topLevel) {
8663: /*
8664: * Process top attributes of global element declarations here.
8665: */
8666: decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8667: decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8668: xmlSchemaPValAttrQName(ctxt, schema,
8669: NULL, node, "substitutionGroup",
8670: &(decl->substGroupNs), &(decl->substGroup));
8671: if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8672: decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8673: /*
8674: * Attribute "final".
8675: */
8676: attr = xmlSchemaGetPropNode(node, "final");
8677: if (attr == NULL) {
8678: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8679: decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8680: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8681: decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8682: } else {
8683: attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8684: if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8685: -1,
8686: XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8687: XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8688: xmlSchemaPSimpleTypeErr(ctxt,
8689: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8690: NULL, (xmlNodePtr) attr,
8691: NULL, "(#all | List of (extension | restriction))",
8692: attrValue, NULL, NULL, NULL);
8693: }
8694: }
8695: }
8696: /*
8697: * Attribute "block".
8698: */
8699: attr = xmlSchemaGetPropNode(node, "block");
8700: if (attr == NULL) {
8701: /*
8702: * Apply default "block" values.
8703: */
8704: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8705: decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8706: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8707: decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8708: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8709: decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8710: } else {
8711: attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8712: if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8713: -1,
8714: XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8715: XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8716: XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8717: xmlSchemaPSimpleTypeErr(ctxt,
8718: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8719: NULL, (xmlNodePtr) attr,
8720: NULL, "(#all | List of (extension | "
8721: "restriction | substitution))", attrValue,
8722: NULL, NULL, NULL);
8723: }
8724: }
8725: if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8726: decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8727:
8728: attr = xmlSchemaGetPropNode(node, "type");
8729: if (attr != NULL) {
8730: xmlSchemaPValAttrNodeQName(ctxt, schema,
8731: NULL, attr,
8732: &(decl->namedTypeNs), &(decl->namedType));
8733: xmlSchemaCheckReference(ctxt, schema, node,
8734: attr, decl->namedTypeNs);
8735: }
8736: decl->value = xmlSchemaGetProp(ctxt, node, "default");
8737: attr = xmlSchemaGetPropNode(node, "fixed");
8738: if (attr != NULL) {
8739: fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8740: if (decl->value != NULL) {
8741: /*
8742: * 3.3.3 : 1
8743: * default and fixed must not both be present.
8744: */
8745: xmlSchemaPMutualExclAttrErr(ctxt,
8746: XML_SCHEMAP_SRC_ELEMENT_1,
8747: NULL, attr, "default", "fixed");
8748: } else {
8749: decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8750: decl->value = fixed;
8751: }
8752: }
8753: /*
8754: * And now for the children...
8755: */
8756: if (IS_SCHEMA(child, "complexType")) {
8757: /*
8758: * 3.3.3 : 3
8759: * "type" and either <simpleType> or <complexType> are mutually
8760: * exclusive
8761: */
8762: if (decl->namedType != NULL) {
8763: xmlSchemaPContentErr(ctxt,
8764: XML_SCHEMAP_SRC_ELEMENT_3,
8765: NULL, node, child,
8766: "The attribute 'type' and the <complexType> child are "
8767: "mutually exclusive", NULL);
8768: } else
8769: WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8770: child = child->next;
8771: } else if (IS_SCHEMA(child, "simpleType")) {
8772: /*
8773: * 3.3.3 : 3
8774: * "type" and either <simpleType> or <complexType> are
8775: * mutually exclusive
8776: */
8777: if (decl->namedType != NULL) {
8778: xmlSchemaPContentErr(ctxt,
8779: XML_SCHEMAP_SRC_ELEMENT_3,
8780: NULL, node, child,
8781: "The attribute 'type' and the <simpleType> child are "
8782: "mutually exclusive", NULL);
8783: } else
8784: WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8785: child = child->next;
8786: }
8787: while ((IS_SCHEMA(child, "unique")) ||
8788: (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8789: if (IS_SCHEMA(child, "unique")) {
8790: curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8791: XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8792: } else if (IS_SCHEMA(child, "key")) {
8793: curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8794: XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8795: } else if (IS_SCHEMA(child, "keyref")) {
8796: curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8797: XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8798: }
8799: if (lastIDC != NULL)
8800: lastIDC->next = curIDC;
8801: else
8802: decl->idcs = (void *) curIDC;
8803: lastIDC = curIDC;
8804: child = child->next;
8805: }
8806: if (child != NULL) {
8807: xmlSchemaPContentErr(ctxt,
8808: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8809: NULL, node, child,
8810: NULL, "(annotation?, ((simpleType | complexType)?, "
8811: "(unique | key | keyref)*))");
8812: }
8813: decl->annot = annot;
8814: }
8815: /*
8816: * NOTE: Element Declaration Representation OK 4. will be checked at a
8817: * different layer.
8818: */
8819: FREE_AND_NULL(des)
8820: if (topLevel)
8821: return ((xmlSchemaBasicItemPtr) decl);
8822: else {
8823: particle->children = (xmlSchemaTreeItemPtr) decl;
8824: return ((xmlSchemaBasicItemPtr) particle);
8825: }
8826:
8827: return_null:
8828: FREE_AND_NULL(des);
8829: if (annot != NULL) {
8830: if (particle != NULL)
8831: particle->annot = NULL;
8832: if (decl != NULL)
8833: decl->annot = NULL;
8834: xmlSchemaFreeAnnot(annot);
8835: }
8836: return (NULL);
8837: }
8838:
8839: /**
8840: * xmlSchemaParseUnion:
8841: * @ctxt: a schema validation context
8842: * @schema: the schema being built
8843: * @node: a subtree containing XML Schema informations
8844: *
8845: * parse a XML schema Union definition
8846: * *WARNING* this interface is highly subject to change
8847: *
8848: * Returns -1 in case of internal error, 0 in case of success and a positive
8849: * error code otherwise.
8850: */
8851: static int
8852: xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8853: xmlNodePtr node)
8854: {
8855: xmlSchemaTypePtr type;
8856: xmlNodePtr child = NULL;
8857: xmlAttrPtr attr;
8858: const xmlChar *cur = NULL;
8859:
8860: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8861: return (-1);
8862: /* Not a component, don't create it. */
8863: type = ctxt->ctxtType;
8864: /*
8865: * Mark the simple type as being of variety "union".
8866: */
8867: type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8868: /*
8869: * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8870: * then the �simple ur-type definition�."
8871: */
8872: type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8873: /*
8874: * Check for illegal attributes.
8875: */
8876: attr = node->properties;
8877: while (attr != NULL) {
8878: if (attr->ns == NULL) {
8879: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8880: (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8881: xmlSchemaPIllegalAttrErr(ctxt,
8882: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8883: }
8884: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8885: xmlSchemaPIllegalAttrErr(ctxt,
8886: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8887: }
8888: attr = attr->next;
8889: }
8890: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8891: /*
8892: * Attribute "memberTypes". This is a list of QNames.
8893: * TODO: Check the value to contain anything.
8894: */
8895: attr = xmlSchemaGetPropNode(node, "memberTypes");
8896: if (attr != NULL) {
8897: const xmlChar *end;
8898: xmlChar *tmp;
8899: const xmlChar *localName, *nsName;
8900: xmlSchemaTypeLinkPtr link, lastLink = NULL;
8901: xmlSchemaQNameRefPtr ref;
8902:
8903: cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8904: type->base = cur;
8905: do {
8906: while (IS_BLANK_CH(*cur))
8907: cur++;
8908: end = cur;
8909: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8910: end++;
8911: if (end == cur)
8912: break;
8913: tmp = xmlStrndup(cur, end - cur);
8914: if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8915: NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8916: /*
8917: * Create the member type link.
8918: */
8919: link = (xmlSchemaTypeLinkPtr)
8920: xmlMalloc(sizeof(xmlSchemaTypeLink));
8921: if (link == NULL) {
8922: xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8923: "allocating a type link", NULL);
8924: return (-1);
8925: }
8926: link->type = NULL;
8927: link->next = NULL;
8928: if (lastLink == NULL)
8929: type->memberTypes = link;
8930: else
8931: lastLink->next = link;
8932: lastLink = link;
8933: /*
8934: * Create a reference item.
8935: */
8936: ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8937: localName, nsName);
8938: if (ref == NULL) {
8939: FREE_AND_NULL(tmp)
8940: return (-1);
8941: }
8942: /*
8943: * Assign the reference to the link, it will be resolved
8944: * later during fixup of the union simple type.
8945: */
8946: link->type = (xmlSchemaTypePtr) ref;
8947: }
8948: FREE_AND_NULL(tmp)
8949: cur = end;
8950: } while (*cur != 0);
8951:
8952: }
8953: /*
8954: * And now for the children...
8955: */
8956: child = node->children;
8957: if (IS_SCHEMA(child, "annotation")) {
8958: /*
8959: * Add the annotation to the simple type ancestor.
8960: */
8961: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8962: xmlSchemaParseAnnotation(ctxt, child, 1));
8963: child = child->next;
8964: }
8965: if (IS_SCHEMA(child, "simpleType")) {
8966: xmlSchemaTypePtr subtype, last = NULL;
8967:
8968: /*
8969: * Anchor the member types in the "subtypes" field of the
8970: * simple type.
8971: */
8972: while (IS_SCHEMA(child, "simpleType")) {
8973: subtype = (xmlSchemaTypePtr)
8974: xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8975: if (subtype != NULL) {
8976: if (last == NULL) {
8977: type->subtypes = subtype;
8978: last = subtype;
8979: } else {
8980: last->next = subtype;
8981: last = subtype;
8982: }
8983: last->next = NULL;
8984: }
8985: child = child->next;
8986: }
8987: }
8988: if (child != NULL) {
8989: xmlSchemaPContentErr(ctxt,
8990: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8991: NULL, node, child, NULL, "(annotation?, simpleType*)");
8992: }
8993: if ((attr == NULL) && (type->subtypes == NULL)) {
8994: /*
8995: * src-union-memberTypes-or-simpleTypes
8996: * Either the memberTypes [attribute] of the <union> element must
8997: * be non-empty or there must be at least one simpleType [child].
8998: */
8999: xmlSchemaPCustomErr(ctxt,
9000: XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9001: NULL, node,
9002: "Either the attribute 'memberTypes' or "
9003: "at least one <simpleType> child must be present", NULL);
9004: }
9005: return (0);
9006: }
9007:
9008: /**
9009: * xmlSchemaParseList:
9010: * @ctxt: a schema validation context
9011: * @schema: the schema being built
9012: * @node: a subtree containing XML Schema informations
9013: *
9014: * parse a XML schema List definition
9015: * *WARNING* this interface is highly subject to change
9016: *
9017: * Returns -1 in case of error, 0 if the declaration is improper and
9018: * 1 in case of success.
9019: */
9020: static xmlSchemaTypePtr
9021: xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9022: xmlNodePtr node)
9023: {
9024: xmlSchemaTypePtr type;
9025: xmlNodePtr child = NULL;
9026: xmlAttrPtr attr;
9027:
9028: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9029: return (NULL);
9030: /* Not a component, don't create it. */
9031: type = ctxt->ctxtType;
9032: /*
9033: * Mark the type as being of variety "list".
9034: */
9035: type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9036: /*
9037: * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9038: * then the �simple ur-type definition�."
9039: */
9040: type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9041: /*
9042: * Check for illegal attributes.
9043: */
9044: attr = node->properties;
9045: while (attr != NULL) {
9046: if (attr->ns == NULL) {
9047: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9048: (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9049: xmlSchemaPIllegalAttrErr(ctxt,
9050: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9051: }
9052: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9053: xmlSchemaPIllegalAttrErr(ctxt,
9054: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9055: }
9056: attr = attr->next;
9057: }
9058:
9059: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9060:
9061: /*
9062: * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9063: * fields for holding the reference to the itemType.
9064: *
9065: * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9066: * the "ref" fields.
9067: */
9068: xmlSchemaPValAttrQName(ctxt, schema, NULL,
9069: node, "itemType", &(type->baseNs), &(type->base));
9070: /*
9071: * And now for the children...
9072: */
9073: child = node->children;
9074: if (IS_SCHEMA(child, "annotation")) {
9075: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9076: xmlSchemaParseAnnotation(ctxt, child, 1));
9077: child = child->next;
9078: }
9079: if (IS_SCHEMA(child, "simpleType")) {
9080: /*
9081: * src-list-itemType-or-simpleType
9082: * Either the itemType [attribute] or the <simpleType> [child] of
9083: * the <list> element must be present, but not both.
9084: */
9085: if (type->base != NULL) {
9086: xmlSchemaPCustomErr(ctxt,
9087: XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9088: NULL, node,
9089: "The attribute 'itemType' and the <simpleType> child "
9090: "are mutually exclusive", NULL);
9091: } else {
9092: type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9093: }
9094: child = child->next;
9095: } else if (type->base == NULL) {
9096: xmlSchemaPCustomErr(ctxt,
9097: XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9098: NULL, node,
9099: "Either the attribute 'itemType' or the <simpleType> child "
9100: "must be present", NULL);
9101: }
9102: if (child != NULL) {
9103: xmlSchemaPContentErr(ctxt,
9104: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9105: NULL, node, child, NULL, "(annotation?, simpleType?)");
9106: }
9107: if ((type->base == NULL) &&
9108: (type->subtypes == NULL) &&
9109: (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9110: xmlSchemaPCustomErr(ctxt,
9111: XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9112: NULL, node,
9113: "Either the attribute 'itemType' or the <simpleType> child "
9114: "must be present", NULL);
9115: }
9116: return (NULL);
9117: }
9118:
9119: /**
9120: * xmlSchemaParseSimpleType:
9121: * @ctxt: a schema validation context
9122: * @schema: the schema being built
9123: * @node: a subtree containing XML Schema informations
9124: *
9125: * parse a XML schema Simple Type definition
9126: * *WARNING* this interface is highly subject to change
9127: *
9128: * Returns -1 in case of error, 0 if the declaration is improper and
9129: * 1 in case of success.
9130: */
9131: static xmlSchemaTypePtr
9132: xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9133: xmlNodePtr node, int topLevel)
9134: {
9135: xmlSchemaTypePtr type, oldCtxtType;
9136: xmlNodePtr child = NULL;
9137: const xmlChar *attrValue = NULL;
9138: xmlAttrPtr attr;
9139: int hasRestriction = 0;
9140:
9141: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9142: return (NULL);
9143:
9144: if (topLevel) {
9145: attr = xmlSchemaGetPropNode(node, "name");
9146: if (attr == NULL) {
9147: xmlSchemaPMissingAttrErr(ctxt,
9148: XML_SCHEMAP_S4S_ATTR_MISSING,
9149: NULL, node,
9150: "name", NULL);
9151: return (NULL);
9152: } else {
9153: if (xmlSchemaPValAttrNode(ctxt,
9154: NULL, attr,
9155: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9156: return (NULL);
9157: /*
9158: * Skip built-in types.
9159: */
9160: if (ctxt->isS4S) {
9161: xmlSchemaTypePtr biType;
9162:
9163: if (ctxt->isRedefine) {
9164: /*
9165: * REDEFINE: Disallow redefinition of built-in-types.
9166: * TODO: It seems that the spec does not say anything
9167: * about this case.
9168: */
9169: xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9170: NULL, node,
9171: "Redefinition of built-in simple types is not "
9172: "supported", NULL);
9173: return(NULL);
9174: }
9175: biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9176: if (biType != NULL)
9177: return (biType);
9178: }
9179: }
9180: }
9181: /*
9182: * TargetNamespace:
9183: * SPEC "The �actual value� of the targetNamespace [attribute]
9184: * of the <schema> ancestor element information item if present,
9185: * otherwise �absent�.
9186: */
9187: if (topLevel == 0) {
9188: #ifdef ENABLE_NAMED_LOCALS
9189: char buf[40];
9190: #endif
9191: /*
9192: * Parse as local simple type definition.
9193: */
9194: #ifdef ENABLE_NAMED_LOCALS
9195: snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9196: type = xmlSchemaAddType(ctxt, schema,
9197: XML_SCHEMA_TYPE_SIMPLE,
9198: xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9199: ctxt->targetNamespace, node, 0);
9200: #else
9201: type = xmlSchemaAddType(ctxt, schema,
9202: XML_SCHEMA_TYPE_SIMPLE,
9203: NULL, ctxt->targetNamespace, node, 0);
9204: #endif
9205: if (type == NULL)
9206: return (NULL);
9207: type->type = XML_SCHEMA_TYPE_SIMPLE;
9208: type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9209: /*
9210: * Check for illegal attributes.
9211: */
9212: attr = node->properties;
9213: while (attr != NULL) {
9214: if (attr->ns == NULL) {
9215: if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9216: xmlSchemaPIllegalAttrErr(ctxt,
9217: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9218: }
9219: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9220: xmlSchemaPIllegalAttrErr(ctxt,
9221: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9222: }
9223: attr = attr->next;
9224: }
9225: } else {
9226: /*
9227: * Parse as global simple type definition.
9228: *
9229: * Note that attrValue is the value of the attribute "name" here.
9230: */
9231: type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9232: attrValue, ctxt->targetNamespace, node, 1);
9233: if (type == NULL)
9234: return (NULL);
9235: type->type = XML_SCHEMA_TYPE_SIMPLE;
9236: type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9237: type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9238: /*
9239: * Check for illegal attributes.
9240: */
9241: attr = node->properties;
9242: while (attr != NULL) {
9243: if (attr->ns == NULL) {
9244: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9245: (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9246: (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9247: xmlSchemaPIllegalAttrErr(ctxt,
9248: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9249: }
9250: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9251: xmlSchemaPIllegalAttrErr(ctxt,
9252: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9253: }
9254: attr = attr->next;
9255: }
9256: /*
9257: * Attribute "final".
9258: */
9259: attr = xmlSchemaGetPropNode(node, "final");
9260: if (attr == NULL) {
9261: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9262: type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9263: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9264: type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9265: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9266: type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9267: } else {
9268: attrValue = xmlSchemaGetProp(ctxt, node, "final");
9269: if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9270: -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9271: XML_SCHEMAS_TYPE_FINAL_LIST,
9272: XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9273:
9274: xmlSchemaPSimpleTypeErr(ctxt,
9275: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9276: WXS_BASIC_CAST type, (xmlNodePtr) attr,
9277: NULL, "(#all | List of (list | union | restriction)",
9278: attrValue, NULL, NULL, NULL);
9279: }
9280: }
9281: }
9282: type->targetNamespace = ctxt->targetNamespace;
9283: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9284: /*
9285: * And now for the children...
9286: */
9287: oldCtxtType = ctxt->ctxtType;
9288:
9289: ctxt->ctxtType = type;
9290:
9291: child = node->children;
9292: if (IS_SCHEMA(child, "annotation")) {
9293: type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9294: child = child->next;
9295: }
9296: if (child == NULL) {
9297: xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9298: NULL, node, child, NULL,
9299: "(annotation?, (restriction | list | union))");
9300: } else if (IS_SCHEMA(child, "restriction")) {
9301: xmlSchemaParseRestriction(ctxt, schema, child,
9302: XML_SCHEMA_TYPE_SIMPLE);
9303: hasRestriction = 1;
9304: child = child->next;
9305: } else if (IS_SCHEMA(child, "list")) {
9306: xmlSchemaParseList(ctxt, schema, child);
9307: child = child->next;
9308: } else if (IS_SCHEMA(child, "union")) {
9309: xmlSchemaParseUnion(ctxt, schema, child);
9310: child = child->next;
9311: }
9312: if (child != NULL) {
9313: xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9314: NULL, node, child, NULL,
9315: "(annotation?, (restriction | list | union))");
9316: }
9317: /*
9318: * REDEFINE: SPEC src-redefine (5)
9319: * "Within the [children], each <simpleType> must have a
9320: * <restriction> among its [children] ... the �actual value� of whose
9321: * base [attribute] must be the same as the �actual value� of its own
9322: * name attribute plus target namespace;"
9323: */
9324: if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9325: xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9326: NULL, node, "This is a redefinition, thus the "
9327: "<simpleType> must have a <restriction> child", NULL);
9328: }
9329:
9330: ctxt->ctxtType = oldCtxtType;
9331: return (type);
9332: }
9333:
9334: /**
9335: * xmlSchemaParseModelGroupDefRef:
9336: * @ctxt: the parser context
9337: * @schema: the schema being built
9338: * @node: the node
9339: *
9340: * Parses a reference to a model group definition.
9341: *
9342: * We will return a particle component with a qname-component or
9343: * NULL in case of an error.
9344: */
9345: static xmlSchemaTreeItemPtr
9346: xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9347: xmlSchemaPtr schema,
9348: xmlNodePtr node)
9349: {
9350: xmlSchemaParticlePtr item;
9351: xmlNodePtr child = NULL;
9352: xmlAttrPtr attr;
9353: const xmlChar *ref = NULL, *refNs = NULL;
9354: int min, max;
9355:
9356: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9357: return (NULL);
9358:
9359: attr = xmlSchemaGetPropNode(node, "ref");
9360: if (attr == NULL) {
9361: xmlSchemaPMissingAttrErr(ctxt,
9362: XML_SCHEMAP_S4S_ATTR_MISSING,
9363: NULL, node, "ref", NULL);
9364: return (NULL);
9365: } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9366: attr, &refNs, &ref) != 0) {
9367: return (NULL);
9368: }
9369: xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9370: min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9371: max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9372: "(xs:nonNegativeInteger | unbounded)");
9373: /*
9374: * Check for illegal attributes.
9375: */
9376: attr = node->properties;
9377: while (attr != NULL) {
9378: if (attr->ns == NULL) {
9379: if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9380: (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9381: (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9382: (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9383: xmlSchemaPIllegalAttrErr(ctxt,
9384: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9385: }
9386: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9387: xmlSchemaPIllegalAttrErr(ctxt,
9388: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9389: }
9390: attr = attr->next;
9391: }
9392: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9393: item = xmlSchemaAddParticle(ctxt, node, min, max);
9394: if (item == NULL)
9395: return (NULL);
9396: /*
9397: * Create a qname-reference and set as the term; it will be substituted
9398: * for the model group after the reference has been resolved.
9399: */
9400: item->children = (xmlSchemaTreeItemPtr)
9401: xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9402: xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9403: /*
9404: * And now for the children...
9405: */
9406: child = node->children;
9407: /* TODO: Is annotation even allowed for a model group reference? */
9408: if (IS_SCHEMA(child, "annotation")) {
9409: /*
9410: * TODO: What to do exactly with the annotation?
9411: */
9412: item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9413: child = child->next;
9414: }
9415: if (child != NULL) {
9416: xmlSchemaPContentErr(ctxt,
9417: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9418: NULL, node, child, NULL,
9419: "(annotation?)");
9420: }
9421: /*
9422: * Corresponds to no component at all if minOccurs==maxOccurs==0.
9423: */
9424: if ((min == 0) && (max == 0))
9425: return (NULL);
9426:
9427: return ((xmlSchemaTreeItemPtr) item);
9428: }
9429:
9430: /**
9431: * xmlSchemaParseModelGroupDefinition:
9432: * @ctxt: a schema validation context
9433: * @schema: the schema being built
9434: * @node: a subtree containing XML Schema informations
9435: *
9436: * Parses a XML schema model group definition.
9437: *
9438: * Note that the contraint src-redefine (6.2) can't be applied until
9439: * references have been resolved. So we will do this at the
9440: * component fixup level.
9441: *
9442: * *WARNING* this interface is highly subject to change
9443: *
9444: * Returns -1 in case of error, 0 if the declaration is improper and
9445: * 1 in case of success.
9446: */
9447: static xmlSchemaModelGroupDefPtr
9448: xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9449: xmlSchemaPtr schema,
9450: xmlNodePtr node)
9451: {
9452: xmlSchemaModelGroupDefPtr item;
9453: xmlNodePtr child = NULL;
9454: xmlAttrPtr attr;
9455: const xmlChar *name;
9456:
9457: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9458: return (NULL);
9459:
9460: attr = xmlSchemaGetPropNode(node, "name");
9461: if (attr == NULL) {
9462: xmlSchemaPMissingAttrErr(ctxt,
9463: XML_SCHEMAP_S4S_ATTR_MISSING,
9464: NULL, node,
9465: "name", NULL);
9466: return (NULL);
9467: } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9468: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9469: return (NULL);
9470: }
9471: item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9472: ctxt->targetNamespace, node);
9473: if (item == NULL)
9474: return (NULL);
9475: /*
9476: * Check for illegal attributes.
9477: */
9478: attr = node->properties;
9479: while (attr != NULL) {
9480: if (attr->ns == NULL) {
9481: if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9482: (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9483: xmlSchemaPIllegalAttrErr(ctxt,
9484: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9485: }
9486: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9487: xmlSchemaPIllegalAttrErr(ctxt,
9488: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9489: }
9490: attr = attr->next;
9491: }
9492: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9493: /*
9494: * And now for the children...
9495: */
9496: child = node->children;
9497: if (IS_SCHEMA(child, "annotation")) {
9498: item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9499: child = child->next;
9500: }
9501: if (IS_SCHEMA(child, "all")) {
9502: item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9503: XML_SCHEMA_TYPE_ALL, 0);
9504: child = child->next;
9505: } else if (IS_SCHEMA(child, "choice")) {
9506: item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9507: XML_SCHEMA_TYPE_CHOICE, 0);
9508: child = child->next;
9509: } else if (IS_SCHEMA(child, "sequence")) {
9510: item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9511: XML_SCHEMA_TYPE_SEQUENCE, 0);
9512: child = child->next;
9513: }
9514:
9515:
9516:
9517: if (child != NULL) {
9518: xmlSchemaPContentErr(ctxt,
9519: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9520: NULL, node, child, NULL,
9521: "(annotation?, (all | choice | sequence)?)");
9522: }
9523: return (item);
9524: }
9525:
9526: /**
9527: * xmlSchemaCleanupDoc:
9528: * @ctxt: a schema validation context
9529: * @node: the root of the document.
9530: *
9531: * removes unwanted nodes in a schemas document tree
9532: */
9533: static void
9534: xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9535: {
9536: xmlNodePtr delete, cur;
9537:
9538: if ((ctxt == NULL) || (root == NULL)) return;
9539:
9540: /*
9541: * Remove all the blank text nodes
9542: */
9543: delete = NULL;
9544: cur = root;
9545: while (cur != NULL) {
9546: if (delete != NULL) {
9547: xmlUnlinkNode(delete);
9548: xmlFreeNode(delete);
9549: delete = NULL;
9550: }
9551: if (cur->type == XML_TEXT_NODE) {
9552: if (IS_BLANK_NODE(cur)) {
9553: if (xmlNodeGetSpacePreserve(cur) != 1) {
9554: delete = cur;
9555: }
9556: }
9557: } else if ((cur->type != XML_ELEMENT_NODE) &&
9558: (cur->type != XML_CDATA_SECTION_NODE)) {
9559: delete = cur;
9560: goto skip_children;
9561: }
9562:
9563: /*
9564: * Skip to next node
9565: */
9566: if (cur->children != NULL) {
9567: if ((cur->children->type != XML_ENTITY_DECL) &&
9568: (cur->children->type != XML_ENTITY_REF_NODE) &&
9569: (cur->children->type != XML_ENTITY_NODE)) {
9570: cur = cur->children;
9571: continue;
9572: }
9573: }
9574: skip_children:
9575: if (cur->next != NULL) {
9576: cur = cur->next;
9577: continue;
9578: }
9579:
9580: do {
9581: cur = cur->parent;
9582: if (cur == NULL)
9583: break;
9584: if (cur == root) {
9585: cur = NULL;
9586: break;
9587: }
9588: if (cur->next != NULL) {
9589: cur = cur->next;
9590: break;
9591: }
9592: } while (cur != NULL);
9593: }
9594: if (delete != NULL) {
9595: xmlUnlinkNode(delete);
9596: xmlFreeNode(delete);
9597: delete = NULL;
9598: }
9599: }
9600:
9601:
9602: static void
9603: xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9604: {
9605: if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9606: schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9607:
9608: if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9609: schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9610:
9611: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9612: schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9613: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9614: schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9615: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9616: schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9617: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9618: schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9619:
9620: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9621: schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9622: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9623: schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9624: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9625: schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9626: }
9627:
9628: static int
9629: xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9630: xmlSchemaPtr schema,
9631: xmlNodePtr node)
9632: {
9633: xmlAttrPtr attr;
9634: const xmlChar *val;
9635: int res = 0, oldErrs = ctxt->nberrors;
9636:
9637: /*
9638: * Those flags should be moved to the parser context flags,
9639: * since they are not visible at the component level. I.e.
9640: * they are used if processing schema *documents* only.
9641: */
9642: res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9643: HFAILURE;
9644:
9645: /*
9646: * Since the version is of type xs:token, we won't bother to
9647: * check it.
9648: */
9649: /* REMOVED:
9650: attr = xmlSchemaGetPropNode(node, "version");
9651: if (attr != NULL) {
9652: res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9653: xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9654: HFAILURE;
9655: }
9656: */
9657: attr = xmlSchemaGetPropNode(node, "targetNamespace");
9658: if (attr != NULL) {
9659: res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9660: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9661: HFAILURE;
9662: if (res != 0) {
9663: ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9664: goto exit;
9665: }
9666: }
9667: attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9668: if (attr != NULL) {
9669: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9670: res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9671: XML_SCHEMAS_QUALIF_ELEM);
9672: HFAILURE;
9673: if (res != 0) {
9674: xmlSchemaPSimpleTypeErr(ctxt,
9675: XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9676: NULL, (xmlNodePtr) attr, NULL,
9677: "(qualified | unqualified)", val, NULL, NULL, NULL);
9678: }
9679: }
9680: attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9681: if (attr != NULL) {
9682: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9683: res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9684: XML_SCHEMAS_QUALIF_ATTR);
9685: HFAILURE;
9686: if (res != 0) {
9687: xmlSchemaPSimpleTypeErr(ctxt,
9688: XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9689: NULL, (xmlNodePtr) attr, NULL,
9690: "(qualified | unqualified)", val, NULL, NULL, NULL);
9691: }
9692: }
9693: attr = xmlSchemaGetPropNode(node, "finalDefault");
9694: if (attr != NULL) {
9695: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9696: res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9697: XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9698: XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9699: -1,
9700: XML_SCHEMAS_FINAL_DEFAULT_LIST,
9701: XML_SCHEMAS_FINAL_DEFAULT_UNION);
9702: HFAILURE;
9703: if (res != 0) {
9704: xmlSchemaPSimpleTypeErr(ctxt,
9705: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9706: NULL, (xmlNodePtr) attr, NULL,
9707: "(#all | List of (extension | restriction | list | union))",
9708: val, NULL, NULL, NULL);
9709: }
9710: }
9711: attr = xmlSchemaGetPropNode(node, "blockDefault");
9712: if (attr != NULL) {
9713: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9714: res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9715: XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9716: XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9717: XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9718: HFAILURE;
9719: if (res != 0) {
9720: xmlSchemaPSimpleTypeErr(ctxt,
9721: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9722: NULL, (xmlNodePtr) attr, NULL,
9723: "(#all | List of (extension | restriction | substitution))",
9724: val, NULL, NULL, NULL);
9725: }
9726: }
9727:
9728: exit:
9729: if (oldErrs != ctxt->nberrors)
9730: res = ctxt->err;
9731: return(res);
9732: exit_failure:
9733: return(-1);
9734: }
9735:
9736: /**
9737: * xmlSchemaParseSchemaTopLevel:
9738: * @ctxt: a schema validation context
9739: * @schema: the schemas
9740: * @nodes: the list of top level nodes
9741: *
9742: * Returns the internal XML Schema structure built from the resource or
9743: * NULL in case of error
9744: */
9745: static int
9746: xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9747: xmlSchemaPtr schema, xmlNodePtr nodes)
9748: {
9749: xmlNodePtr child;
9750: xmlSchemaAnnotPtr annot;
9751: int res = 0, oldErrs, tmpOldErrs;
9752:
9753: if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9754: return(-1);
9755:
9756: oldErrs = ctxt->nberrors;
9757: child = nodes;
9758: while ((IS_SCHEMA(child, "include")) ||
9759: (IS_SCHEMA(child, "import")) ||
9760: (IS_SCHEMA(child, "redefine")) ||
9761: (IS_SCHEMA(child, "annotation"))) {
9762: if (IS_SCHEMA(child, "annotation")) {
9763: annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9764: if (schema->annot == NULL)
9765: schema->annot = annot;
9766: else
9767: xmlSchemaFreeAnnot(annot);
9768: } else if (IS_SCHEMA(child, "import")) {
9769: tmpOldErrs = ctxt->nberrors;
9770: res = xmlSchemaParseImport(ctxt, schema, child);
9771: HFAILURE;
9772: HSTOP(ctxt);
9773: if (tmpOldErrs != ctxt->nberrors)
9774: goto exit;
9775: } else if (IS_SCHEMA(child, "include")) {
9776: tmpOldErrs = ctxt->nberrors;
9777: res = xmlSchemaParseInclude(ctxt, schema, child);
9778: HFAILURE;
9779: HSTOP(ctxt);
9780: if (tmpOldErrs != ctxt->nberrors)
9781: goto exit;
9782: } else if (IS_SCHEMA(child, "redefine")) {
9783: tmpOldErrs = ctxt->nberrors;
9784: res = xmlSchemaParseRedefine(ctxt, schema, child);
9785: HFAILURE;
9786: HSTOP(ctxt);
9787: if (tmpOldErrs != ctxt->nberrors)
9788: goto exit;
9789: }
9790: child = child->next;
9791: }
9792: /*
9793: * URGENT TODO: Change the functions to return int results.
9794: * We need especially to catch internal errors.
9795: */
9796: while (child != NULL) {
9797: if (IS_SCHEMA(child, "complexType")) {
9798: xmlSchemaParseComplexType(ctxt, schema, child, 1);
9799: child = child->next;
9800: } else if (IS_SCHEMA(child, "simpleType")) {
9801: xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9802: child = child->next;
9803: } else if (IS_SCHEMA(child, "element")) {
9804: xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9805: child = child->next;
9806: } else if (IS_SCHEMA(child, "attribute")) {
9807: xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9808: child = child->next;
9809: } else if (IS_SCHEMA(child, "attributeGroup")) {
9810: xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9811: child = child->next;
9812: } else if (IS_SCHEMA(child, "group")) {
9813: xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9814: child = child->next;
9815: } else if (IS_SCHEMA(child, "notation")) {
9816: xmlSchemaParseNotation(ctxt, schema, child);
9817: child = child->next;
9818: } else {
9819: xmlSchemaPContentErr(ctxt,
9820: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9821: NULL, child->parent, child,
9822: NULL, "((include | import | redefine | annotation)*, "
9823: "(((simpleType | complexType | group | attributeGroup) "
9824: "| element | attribute | notation), annotation*)*)");
9825: child = child->next;
9826: }
9827: while (IS_SCHEMA(child, "annotation")) {
9828: /*
9829: * TODO: We should add all annotations.
9830: */
9831: annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9832: if (schema->annot == NULL)
9833: schema->annot = annot;
9834: else
9835: xmlSchemaFreeAnnot(annot);
9836: child = child->next;
9837: }
9838: }
9839: exit:
9840: ctxt->ctxtType = NULL;
9841: if (oldErrs != ctxt->nberrors)
9842: res = ctxt->err;
9843: return(res);
9844: exit_failure:
9845: return(-1);
9846: }
9847:
9848: static xmlSchemaSchemaRelationPtr
9849: xmlSchemaSchemaRelationCreate(void)
9850: {
9851: xmlSchemaSchemaRelationPtr ret;
9852:
9853: ret = (xmlSchemaSchemaRelationPtr)
9854: xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9855: if (ret == NULL) {
9856: xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9857: return(NULL);
9858: }
9859: memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9860: return(ret);
9861: }
9862:
9863: #if 0
9864: static void
9865: xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9866: {
9867: xmlFree(rel);
9868: }
9869: #endif
9870:
9871: static void
9872: xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9873: {
9874: xmlSchemaRedefPtr prev;
9875:
9876: while (redef != NULL) {
9877: prev = redef;
9878: redef = redef->next;
9879: xmlFree(prev);
9880: }
9881: }
9882:
9883: static void
9884: xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9885: {
9886: /*
9887: * After the construction context has been freed, there will be
9888: * no schema graph available any more. Only the schema buckets
9889: * will stay alive, which are put into the "schemasImports" and
9890: * "includes" slots of the xmlSchema.
9891: */
9892: if (con->buckets != NULL)
9893: xmlSchemaItemListFree(con->buckets);
9894: if (con->pending != NULL)
9895: xmlSchemaItemListFree(con->pending);
9896: if (con->substGroups != NULL)
9897: xmlHashFree(con->substGroups,
9898: (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9899: if (con->redefs != NULL)
9900: xmlSchemaRedefListFree(con->redefs);
9901: if (con->dict != NULL)
9902: xmlDictFree(con->dict);
9903: xmlFree(con);
9904: }
9905:
9906: static xmlSchemaConstructionCtxtPtr
9907: xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9908: {
9909: xmlSchemaConstructionCtxtPtr ret;
9910:
9911: ret = (xmlSchemaConstructionCtxtPtr)
9912: xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9913: if (ret == NULL) {
9914: xmlSchemaPErrMemory(NULL,
9915: "allocating schema construction context", NULL);
9916: return (NULL);
9917: }
9918: memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9919:
9920: ret->buckets = xmlSchemaItemListCreate();
9921: if (ret->buckets == NULL) {
9922: xmlSchemaPErrMemory(NULL,
9923: "allocating list of schema buckets", NULL);
9924: xmlFree(ret);
9925: return (NULL);
9926: }
9927: ret->pending = xmlSchemaItemListCreate();
9928: if (ret->pending == NULL) {
9929: xmlSchemaPErrMemory(NULL,
9930: "allocating list of pending global components", NULL);
9931: xmlSchemaConstructionCtxtFree(ret);
9932: return (NULL);
9933: }
9934: ret->dict = dict;
9935: xmlDictReference(dict);
9936: return(ret);
9937: }
9938:
9939: static xmlSchemaParserCtxtPtr
9940: xmlSchemaParserCtxtCreate(void)
9941: {
9942: xmlSchemaParserCtxtPtr ret;
9943:
9944: ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9945: if (ret == NULL) {
9946: xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9947: NULL);
9948: return (NULL);
9949: }
9950: memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9951: ret->type = XML_SCHEMA_CTXT_PARSER;
9952: ret->attrProhibs = xmlSchemaItemListCreate();
9953: if (ret->attrProhibs == NULL) {
9954: xmlFree(ret);
9955: return(NULL);
9956: }
9957: return(ret);
9958: }
9959:
9960: /**
9961: * xmlSchemaNewParserCtxtUseDict:
9962: * @URL: the location of the schema
9963: * @dict: the dictionary to be used
9964: *
9965: * Create an XML Schemas parse context for that file/resource expected
9966: * to contain an XML Schemas file.
9967: *
9968: * Returns the parser context or NULL in case of error
9969: */
9970: static xmlSchemaParserCtxtPtr
9971: xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9972: {
9973: xmlSchemaParserCtxtPtr ret;
9974:
9975: ret = xmlSchemaParserCtxtCreate();
9976: if (ret == NULL)
9977: return (NULL);
9978: ret->dict = dict;
9979: xmlDictReference(dict);
9980: if (URL != NULL)
9981: ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9982: return (ret);
9983: }
9984:
9985: static int
9986: xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9987: {
9988: if (vctxt->pctxt == NULL) {
9989: if (vctxt->schema != NULL)
9990: vctxt->pctxt =
9991: xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9992: else
9993: vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9994: if (vctxt->pctxt == NULL) {
9995: VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9996: "failed to create a temp. parser context");
9997: return (-1);
9998: }
9999: /* TODO: Pass user data. */
10000: xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10001: vctxt->warning, vctxt->errCtxt);
10002: xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10003: vctxt->errCtxt);
10004: }
10005: return (0);
10006: }
10007:
10008: /**
10009: * xmlSchemaGetSchemaBucket:
10010: * @pctxt: the schema parser context
10011: * @schemaLocation: the URI of the schema document
10012: *
10013: * Returns a schema bucket if it was already parsed.
10014: *
10015: * Returns a schema bucket if it was already parsed from
10016: * @schemaLocation, NULL otherwise.
10017: */
10018: static xmlSchemaBucketPtr
10019: xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10020: const xmlChar *schemaLocation)
10021: {
10022: xmlSchemaBucketPtr cur;
10023: xmlSchemaItemListPtr list;
10024:
10025: list = pctxt->constructor->buckets;
10026: if (list->nbItems == 0)
10027: return(NULL);
10028: else {
10029: int i;
10030: for (i = 0; i < list->nbItems; i++) {
10031: cur = (xmlSchemaBucketPtr) list->items[i];
10032: /* Pointer comparison! */
10033: if (cur->schemaLocation == schemaLocation)
10034: return(cur);
10035: }
10036: }
10037: return(NULL);
10038: }
10039:
10040: static xmlSchemaBucketPtr
10041: xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10042: const xmlChar *schemaLocation,
10043: const xmlChar *targetNamespace)
10044: {
10045: xmlSchemaBucketPtr cur;
10046: xmlSchemaItemListPtr list;
10047:
10048: list = pctxt->constructor->buckets;
10049: if (list->nbItems == 0)
10050: return(NULL);
10051: else {
10052: int i;
10053: for (i = 0; i < list->nbItems; i++) {
10054: cur = (xmlSchemaBucketPtr) list->items[i];
10055: /* Pointer comparison! */
10056: if ((cur->origTargetNamespace == NULL) &&
10057: (cur->schemaLocation == schemaLocation) &&
10058: (cur->targetNamespace == targetNamespace))
10059: return(cur);
10060: }
10061: }
10062: return(NULL);
10063: }
10064:
10065:
10066: #define IS_BAD_SCHEMA_DOC(b) \
10067: (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10068:
10069: static xmlSchemaBucketPtr
10070: xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10071: const xmlChar *targetNamespace,
10072: int imported)
10073: {
10074: xmlSchemaBucketPtr cur;
10075: xmlSchemaItemListPtr list;
10076:
10077: list = pctxt->constructor->buckets;
10078: if (list->nbItems == 0)
10079: return(NULL);
10080: else {
10081: int i;
10082: for (i = 0; i < list->nbItems; i++) {
10083: cur = (xmlSchemaBucketPtr) list->items[i];
10084: if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10085: (cur->origTargetNamespace == targetNamespace) &&
10086: ((imported && cur->imported) ||
10087: ((!imported) && (!cur->imported))))
10088: return(cur);
10089: }
10090: }
10091: return(NULL);
10092: }
10093:
10094: static int
10095: xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10096: xmlSchemaPtr schema,
10097: xmlSchemaBucketPtr bucket)
10098: {
10099: int oldFlags;
10100: xmlDocPtr oldDoc;
10101: xmlNodePtr node;
10102: int ret, oldErrs;
10103: xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10104:
10105: /*
10106: * Save old values; reset the *main* schema.
10107: * URGENT TODO: This is not good; move the per-document information
10108: * to the parser. Get rid of passing the main schema to the
10109: * parsing functions.
10110: */
10111: oldFlags = schema->flags;
10112: oldDoc = schema->doc;
10113: if (schema->flags != 0)
10114: xmlSchemaClearSchemaDefaults(schema);
10115: schema->doc = bucket->doc;
10116: pctxt->schema = schema;
10117: /*
10118: * Keep the current target namespace on the parser *not* on the
10119: * main schema.
10120: */
10121: pctxt->targetNamespace = bucket->targetNamespace;
10122: WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10123:
10124: if ((bucket->targetNamespace != NULL) &&
10125: xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10126: /*
10127: * We are parsing the schema for schemas!
10128: */
10129: pctxt->isS4S = 1;
10130: }
10131: /* Mark it as parsed, even if parsing fails. */
10132: bucket->parsed++;
10133: /* Compile the schema doc. */
10134: node = xmlDocGetRootElement(bucket->doc);
10135: ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10136: if (ret != 0)
10137: goto exit;
10138: /* An empty schema; just get out. */
10139: if (node->children == NULL)
10140: goto exit;
10141: oldErrs = pctxt->nberrors;
10142: ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10143: if (ret != 0)
10144: goto exit;
10145: /*
10146: * TODO: Not nice, but I'm not 100% sure we will get always an error
10147: * as a result of the obove functions; so better rely on pctxt->err
10148: * as well.
10149: */
10150: if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10151: ret = pctxt->err;
10152: goto exit;
10153: }
10154:
10155: exit:
10156: WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10157: /* Restore schema values. */
10158: schema->doc = oldDoc;
10159: schema->flags = oldFlags;
10160: return(ret);
10161: }
10162:
10163: static int
10164: xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10165: xmlSchemaPtr schema,
10166: xmlSchemaBucketPtr bucket)
10167: {
10168: xmlSchemaParserCtxtPtr newpctxt;
10169: int res = 0;
10170:
10171: if (bucket == NULL)
10172: return(0);
10173: if (bucket->parsed) {
10174: PERROR_INT("xmlSchemaParseNewDoc",
10175: "reparsing a schema doc");
10176: return(-1);
10177: }
10178: if (bucket->doc == NULL) {
10179: PERROR_INT("xmlSchemaParseNewDoc",
10180: "parsing a schema doc, but there's no doc");
10181: return(-1);
10182: }
10183: if (pctxt->constructor == NULL) {
10184: PERROR_INT("xmlSchemaParseNewDoc",
10185: "no constructor");
10186: return(-1);
10187: }
10188: /* Create and init the temporary parser context. */
10189: newpctxt = xmlSchemaNewParserCtxtUseDict(
10190: (const char *) bucket->schemaLocation, pctxt->dict);
10191: if (newpctxt == NULL)
10192: return(-1);
10193: newpctxt->constructor = pctxt->constructor;
10194: /*
10195: * TODO: Can we avoid that the parser knows about the main schema?
10196: * It would be better if he knows about the current schema bucket
10197: * only.
10198: */
10199: newpctxt->schema = schema;
10200: xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10201: pctxt->errCtxt);
10202: xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10203: pctxt->errCtxt);
10204: newpctxt->counter = pctxt->counter;
10205:
10206:
10207: res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10208:
10209: /* Channel back errors and cleanup the temporary parser context. */
10210: if (res != 0)
10211: pctxt->err = res;
10212: pctxt->nberrors += newpctxt->nberrors;
10213: pctxt->counter = newpctxt->counter;
10214: newpctxt->constructor = NULL;
10215: /* Free the parser context. */
10216: xmlSchemaFreeParserCtxt(newpctxt);
10217: return(res);
10218: }
10219:
10220: static void
10221: xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10222: xmlSchemaSchemaRelationPtr rel)
10223: {
10224: xmlSchemaSchemaRelationPtr cur = bucket->relations;
10225:
10226: if (cur == NULL) {
10227: bucket->relations = rel;
10228: return;
10229: }
10230: while (cur->next != NULL)
10231: cur = cur->next;
10232: cur->next = rel;
10233: }
10234:
10235:
10236: static const xmlChar *
10237: xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10238: xmlNodePtr ctxtNode)
10239: {
10240: /*
10241: * Build an absolue location URI.
10242: */
10243: if (location != NULL) {
10244: if (ctxtNode == NULL)
10245: return(location);
10246: else {
10247: xmlChar *base, *URI;
10248: const xmlChar *ret = NULL;
10249:
10250: base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10251: if (base == NULL) {
10252: URI = xmlBuildURI(location, ctxtNode->doc->URL);
10253: } else {
10254: URI = xmlBuildURI(location, base);
10255: xmlFree(base);
10256: }
10257: if (URI != NULL) {
10258: ret = xmlDictLookup(dict, URI, -1);
10259: xmlFree(URI);
10260: return(ret);
10261: }
10262: }
10263: }
10264: return(NULL);
10265: }
10266:
10267:
10268:
10269: /**
10270: * xmlSchemaAddSchemaDoc:
10271: * @pctxt: a schema validation context
10272: * @schema: the schema being built
10273: * @node: a subtree containing XML Schema informations
10274: *
10275: * Parse an included (and to-be-redefined) XML schema document.
10276: *
10277: * Returns 0 on success, a positive error code on errors and
10278: * -1 in case of an internal or API error.
10279: */
10280:
10281: static int
10282: xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10283: int type, /* import or include or redefine */
10284: const xmlChar *schemaLocation,
10285: xmlDocPtr schemaDoc,
10286: const char *schemaBuffer,
10287: int schemaBufferLen,
10288: xmlNodePtr invokingNode,
10289: const xmlChar *sourceTargetNamespace,
10290: const xmlChar *importNamespace,
10291: xmlSchemaBucketPtr *bucket)
10292: {
10293: const xmlChar *targetNamespace = NULL;
10294: xmlSchemaSchemaRelationPtr relation = NULL;
10295: xmlDocPtr doc = NULL;
10296: int res = 0, err = 0, located = 0, preserveDoc = 0;
10297: xmlSchemaBucketPtr bkt = NULL;
10298:
10299: if (bucket != NULL)
10300: *bucket = NULL;
10301:
10302: switch (type) {
10303: case XML_SCHEMA_SCHEMA_IMPORT:
10304: case XML_SCHEMA_SCHEMA_MAIN:
10305: err = XML_SCHEMAP_SRC_IMPORT;
10306: break;
10307: case XML_SCHEMA_SCHEMA_INCLUDE:
10308: err = XML_SCHEMAP_SRC_INCLUDE;
10309: break;
10310: case XML_SCHEMA_SCHEMA_REDEFINE:
10311: err = XML_SCHEMAP_SRC_REDEFINE;
10312: break;
10313: }
10314:
10315:
10316: /* Special handling for the main schema:
10317: * skip the location and relation logic and just parse the doc.
10318: * We need just a bucket to be returned in this case.
10319: */
10320: if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10321: goto doc_load;
10322:
10323: /* Note that we expect the location to be an absulute URI. */
10324: if (schemaLocation != NULL) {
10325: bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10326: if ((bkt != NULL) &&
10327: (pctxt->constructor->bucket == bkt)) {
10328: /* Report self-imports/inclusions/redefinitions. */
10329:
10330: xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10331: invokingNode, NULL,
10332: "The schema must not import/include/redefine itself",
10333: NULL, NULL);
10334: goto exit;
10335: }
10336: }
10337: /*
10338: * Create a relation for the graph of schemas.
10339: */
10340: relation = xmlSchemaSchemaRelationCreate();
10341: if (relation == NULL)
10342: return(-1);
10343: xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10344: relation);
10345: relation->type = type;
10346:
10347: /*
10348: * Save the namespace import information.
10349: */
10350: if (WXS_IS_BUCKET_IMPMAIN(type)) {
10351: relation->importNamespace = importNamespace;
10352: if (schemaLocation == NULL) {
10353: /*
10354: * No location; this is just an import of the namespace.
10355: * Note that we don't assign a bucket to the relation
10356: * in this case.
10357: */
10358: goto exit;
10359: }
10360: targetNamespace = importNamespace;
10361: }
10362:
10363: /* Did we already fetch the doc? */
10364: if (bkt != NULL) {
10365: if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10366: /*
10367: * We included/redefined and then try to import a schema,
10368: * but the new location provided for import was different.
10369: */
10370: if (schemaLocation == NULL)
10371: schemaLocation = BAD_CAST "in_memory_buffer";
10372: if (!xmlStrEqual(schemaLocation,
10373: bkt->schemaLocation)) {
10374: xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10375: invokingNode, NULL,
10376: "The schema document '%s' cannot be imported, since "
10377: "it was already included or redefined",
10378: schemaLocation, NULL);
10379: goto exit;
10380: }
10381: } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10382: /*
10383: * We imported and then try to include/redefine a schema,
10384: * but the new location provided for the include/redefine
10385: * was different.
10386: */
10387: if (schemaLocation == NULL)
10388: schemaLocation = BAD_CAST "in_memory_buffer";
10389: if (!xmlStrEqual(schemaLocation,
10390: bkt->schemaLocation)) {
10391: xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10392: invokingNode, NULL,
10393: "The schema document '%s' cannot be included or "
10394: "redefined, since it was already imported",
10395: schemaLocation, NULL);
10396: goto exit;
10397: }
10398: }
10399: }
10400:
10401: if (WXS_IS_BUCKET_IMPMAIN(type)) {
10402: /*
10403: * Given that the schemaLocation [attribute] is only a hint, it is open
10404: * to applications to ignore all but the first <import> for a given
10405: * namespace, regardless of the �actual value� of schemaLocation, but
10406: * such a strategy risks missing useful information when new
10407: * schemaLocations are offered.
10408: *
10409: * We will use the first <import> that comes with a location.
10410: * Further <import>s *with* a location, will result in an error.
10411: * TODO: Better would be to just report a warning here, but
10412: * we'll try it this way until someone complains.
10413: *
10414: * Schema Document Location Strategy:
10415: * 3 Based on the namespace name, identify an existing schema document,
10416: * either as a resource which is an XML document or a <schema> element
10417: * information item, in some local schema repository;
10418: * 5 Attempt to resolve the namespace name to locate such a resource.
10419: *
10420: * NOTE: (3) and (5) are not supported.
10421: */
10422: if (bkt != NULL) {
10423: relation->bucket = bkt;
10424: goto exit;
10425: }
10426: bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10427: importNamespace, 1);
10428:
10429: if (bkt != NULL) {
10430: relation->bucket = bkt;
10431: if (bkt->schemaLocation == NULL) {
10432: /* First given location of the schema; load the doc. */
10433: bkt->schemaLocation = schemaLocation;
10434: } else {
10435: if (!xmlStrEqual(schemaLocation,
10436: bkt->schemaLocation)) {
10437: /*
10438: * Additional location given; just skip it.
10439: * URGENT TODO: We should report a warning here.
10440: * res = XML_SCHEMAP_SRC_IMPORT;
10441: */
10442: if (schemaLocation == NULL)
10443: schemaLocation = BAD_CAST "in_memory_buffer";
10444:
10445: xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10446: XML_SCHEMAP_WARN_SKIP_SCHEMA,
10447: invokingNode, NULL,
10448: "Skipping import of schema located at '%s' for the "
10449: "namespace '%s', since this namespace was already "
10450: "imported with the schema located at '%s'",
10451: schemaLocation, importNamespace, bkt->schemaLocation);
10452: }
10453: goto exit;
10454: }
10455: }
10456: /*
10457: * No bucket + first location: load the doc and create a
10458: * bucket.
10459: */
10460: } else {
10461: /* <include> and <redefine> */
10462: if (bkt != NULL) {
10463:
10464: if ((bkt->origTargetNamespace == NULL) &&
10465: (bkt->targetNamespace != sourceTargetNamespace)) {
10466: xmlSchemaBucketPtr chamel;
10467:
10468: /*
10469: * Chameleon include/redefine: skip loading only if it was
10470: * aleady build for the targetNamespace of the including
10471: * schema.
10472: */
10473: /*
10474: * URGENT TODO: If the schema is a chameleon-include then copy
10475: * the components into the including schema and modify the
10476: * targetNamespace of those components, do nothing otherwise.
10477: * NOTE: This is currently worked-around by compiling the
10478: * chameleon for every destinct including targetNamespace; thus
10479: * not performant at the moment.
10480: * TODO: Check when the namespace in wildcards for chameleons
10481: * needs to be converted: before we built wildcard intersections
10482: * or after.
10483: * Answer: after!
10484: */
10485: chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10486: schemaLocation, sourceTargetNamespace);
10487: if (chamel != NULL) {
10488: /* A fitting chameleon was already parsed; NOP. */
10489: relation->bucket = chamel;
10490: goto exit;
10491: }
10492: /*
10493: * We need to parse the chameleon again for a different
10494: * targetNamespace.
10495: * CHAMELEON TODO: Optimize this by only parsing the
10496: * chameleon once, and then copying the components to
10497: * the new targetNamespace.
10498: */
10499: bkt = NULL;
10500: } else {
10501: relation->bucket = bkt;
10502: goto exit;
10503: }
10504: }
10505: }
10506: if ((bkt != NULL) && (bkt->doc != NULL)) {
10507: PERROR_INT("xmlSchemaAddSchemaDoc",
10508: "trying to load a schema doc, but a doc is already "
10509: "assigned to the schema bucket");
10510: goto exit_failure;
10511: }
10512:
10513: doc_load:
10514: /*
10515: * Load the document.
10516: */
10517: if (schemaDoc != NULL) {
10518: doc = schemaDoc;
10519: /* Don' free this one, since it was provided by the caller. */
10520: preserveDoc = 1;
10521: /* TODO: Does the context or the doc hold the location? */
10522: if (schemaDoc->URL != NULL)
10523: schemaLocation = xmlDictLookup(pctxt->dict,
10524: schemaDoc->URL, -1);
10525: else
10526: schemaLocation = BAD_CAST "in_memory_buffer";
10527: } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10528: xmlParserCtxtPtr parserCtxt;
10529:
10530: parserCtxt = xmlNewParserCtxt();
10531: if (parserCtxt == NULL) {
10532: xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10533: "allocating a parser context", NULL);
10534: goto exit_failure;
10535: }
10536: if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10537: /*
10538: * TODO: Do we have to burden the schema parser dict with all
10539: * the content of the schema doc?
10540: */
10541: xmlDictFree(parserCtxt->dict);
10542: parserCtxt->dict = pctxt->dict;
10543: xmlDictReference(parserCtxt->dict);
10544: }
10545: if (schemaLocation != NULL) {
10546: /* Parse from file. */
10547: doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10548: NULL, SCHEMAS_PARSE_OPTIONS);
10549: } else if (schemaBuffer != NULL) {
10550: /* Parse from memory buffer. */
10551: doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10552: NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10553: schemaLocation = BAD_CAST "in_memory_buffer";
10554: if (doc != NULL)
10555: doc->URL = xmlStrdup(schemaLocation);
10556: }
10557: /*
10558: * For <import>:
10559: * 2.1 The referent is (a fragment of) a resource which is an
10560: * XML document (see clause 1.1), which in turn corresponds to
10561: * a <schema> element information item in a well-formed information
10562: * set, which in turn corresponds to a valid schema.
10563: * TODO: (2.1) fragments of XML documents are not supported.
10564: *
10565: * 2.2 The referent is a <schema> element information item in
10566: * a well-formed information set, which in turn corresponds
10567: * to a valid schema.
10568: * TODO: (2.2) is not supported.
10569: */
10570: if (doc == NULL) {
10571: xmlErrorPtr lerr;
10572: lerr = xmlGetLastError();
10573: /*
10574: * Check if this a parser error, or if the document could
10575: * just not be located.
10576: * TODO: Try to find specific error codes to react only on
10577: * localisation failures.
10578: */
10579: if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10580: /*
10581: * We assume a parser error here.
10582: */
10583: located = 1;
10584: /* TODO: Error code ?? */
10585: res = XML_SCHEMAP_SRC_IMPORT_2_1;
10586: xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10587: invokingNode, NULL,
10588: "Failed to parse the XML resource '%s'",
10589: schemaLocation, NULL);
10590: }
10591: }
10592: xmlFreeParserCtxt(parserCtxt);
10593: if ((doc == NULL) && located)
10594: goto exit_error;
10595: } else {
10596: xmlSchemaPErr(pctxt, NULL,
10597: XML_SCHEMAP_NOTHING_TO_PARSE,
10598: "No information for parsing was provided with the "
10599: "given schema parser context.\n",
10600: NULL, NULL);
10601: goto exit_failure;
10602: }
10603: /*
10604: * Preprocess the document.
10605: */
10606: if (doc != NULL) {
10607: xmlNodePtr docElem = NULL;
10608:
10609: located = 1;
10610: docElem = xmlDocGetRootElement(doc);
10611: if (docElem == NULL) {
10612: xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10613: invokingNode, NULL,
10614: "The document '%s' has no document element",
10615: schemaLocation, NULL);
10616: goto exit_error;
10617: }
10618: /*
10619: * Remove all the blank text nodes.
10620: */
10621: xmlSchemaCleanupDoc(pctxt, docElem);
10622: /*
10623: * Check the schema's top level element.
10624: */
10625: if (!IS_SCHEMA(docElem, "schema")) {
10626: xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10627: invokingNode, NULL,
10628: "The XML document '%s' is not a schema document",
10629: schemaLocation, NULL);
10630: goto exit_error;
10631: }
10632: /*
10633: * Note that we don't apply a type check for the
10634: * targetNamespace value here.
10635: */
10636: targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10637: "targetNamespace");
10638: }
10639:
10640: /* after_doc_loading: */
10641: if ((bkt == NULL) && located) {
10642: /* Only create a bucket if the schema was located. */
10643: bkt = xmlSchemaBucketCreate(pctxt, type,
10644: targetNamespace);
10645: if (bkt == NULL)
10646: goto exit_failure;
10647: }
10648: if (bkt != NULL) {
10649: bkt->schemaLocation = schemaLocation;
10650: bkt->located = located;
10651: if (doc != NULL) {
10652: bkt->doc = doc;
10653: bkt->targetNamespace = targetNamespace;
10654: bkt->origTargetNamespace = targetNamespace;
10655: if (preserveDoc)
10656: bkt->preserveDoc = 1;
10657: }
10658: if (WXS_IS_BUCKET_IMPMAIN(type))
10659: bkt->imported++;
10660: /*
10661: * Add it to the graph of schemas.
10662: */
10663: if (relation != NULL)
10664: relation->bucket = bkt;
10665: }
10666:
10667: exit:
10668: /*
10669: * Return the bucket explicitely; this is needed for the
10670: * main schema.
10671: */
10672: if (bucket != NULL)
10673: *bucket = bkt;
10674: return (0);
10675:
10676: exit_error:
10677: if ((doc != NULL) && (! preserveDoc)) {
10678: xmlFreeDoc(doc);
10679: if (bkt != NULL)
10680: bkt->doc = NULL;
10681: }
10682: return(pctxt->err);
10683:
10684: exit_failure:
10685: if ((doc != NULL) && (! preserveDoc)) {
10686: xmlFreeDoc(doc);
10687: if (bkt != NULL)
10688: bkt->doc = NULL;
10689: }
10690: return (-1);
10691: }
10692:
10693: /**
10694: * xmlSchemaParseImport:
10695: * @ctxt: a schema validation context
10696: * @schema: the schema being built
10697: * @node: a subtree containing XML Schema informations
10698: *
10699: * parse a XML schema Import definition
10700: * *WARNING* this interface is highly subject to change
10701: *
10702: * Returns 0 in case of success, a positive error code if
10703: * not valid and -1 in case of an internal error.
10704: */
10705: static int
10706: xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10707: xmlNodePtr node)
10708: {
10709: xmlNodePtr child;
10710: const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10711: const xmlChar *thisTargetNamespace;
10712: xmlAttrPtr attr;
10713: int ret = 0;
10714: xmlSchemaBucketPtr bucket = NULL;
10715:
10716: if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10717: return (-1);
10718:
10719: /*
10720: * Check for illegal attributes.
10721: */
10722: attr = node->properties;
10723: while (attr != NULL) {
10724: if (attr->ns == NULL) {
10725: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10726: (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10727: (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10728: xmlSchemaPIllegalAttrErr(pctxt,
10729: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10730: }
10731: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10732: xmlSchemaPIllegalAttrErr(pctxt,
10733: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10734: }
10735: attr = attr->next;
10736: }
10737: /*
10738: * Extract and validate attributes.
10739: */
10740: if (xmlSchemaPValAttr(pctxt, NULL, node,
10741: "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10742: &namespaceName) != 0) {
10743: xmlSchemaPSimpleTypeErr(pctxt,
10744: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10745: NULL, node,
10746: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10747: NULL, namespaceName, NULL, NULL, NULL);
10748: return (pctxt->err);
10749: }
10750:
10751: if (xmlSchemaPValAttr(pctxt, NULL, node,
10752: "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10753: &schemaLocation) != 0) {
10754: xmlSchemaPSimpleTypeErr(pctxt,
10755: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10756: NULL, node,
10757: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10758: NULL, namespaceName, NULL, NULL, NULL);
10759: return (pctxt->err);
10760: }
10761: /*
10762: * And now for the children...
10763: */
10764: child = node->children;
10765: if (IS_SCHEMA(child, "annotation")) {
10766: /*
10767: * the annotation here is simply discarded ...
10768: * TODO: really?
10769: */
10770: child = child->next;
10771: }
10772: if (child != NULL) {
10773: xmlSchemaPContentErr(pctxt,
10774: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10775: NULL, node, child, NULL,
10776: "(annotation?)");
10777: }
10778: /*
10779: * Apply additional constraints.
10780: *
10781: * Note that it is important to use the original @targetNamespace
10782: * (or none at all), to rule out imports of schemas _with_ a
10783: * @targetNamespace if the importing schema is a chameleon schema
10784: * (with no @targetNamespace).
10785: */
10786: thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10787: if (namespaceName != NULL) {
10788: /*
10789: * 1.1 If the namespace [attribute] is present, then its �actual value�
10790: * must not match the �actual value� of the enclosing <schema>'s
10791: * targetNamespace [attribute].
10792: */
10793: if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10794: xmlSchemaPCustomErr(pctxt,
10795: XML_SCHEMAP_SRC_IMPORT_1_1,
10796: NULL, node,
10797: "The value of the attribute 'namespace' must not match "
10798: "the target namespace '%s' of the importing schema",
10799: thisTargetNamespace);
10800: return (pctxt->err);
10801: }
10802: } else {
10803: /*
10804: * 1.2 If the namespace [attribute] is not present, then the enclosing
10805: * <schema> must have a targetNamespace [attribute].
10806: */
10807: if (thisTargetNamespace == NULL) {
10808: xmlSchemaPCustomErr(pctxt,
10809: XML_SCHEMAP_SRC_IMPORT_1_2,
10810: NULL, node,
10811: "The attribute 'namespace' must be existent if "
10812: "the importing schema has no target namespace",
10813: NULL);
10814: return (pctxt->err);
10815: }
10816: }
10817: /*
10818: * Locate and acquire the schema document.
10819: */
10820: if (schemaLocation != NULL)
10821: schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10822: schemaLocation, node);
10823: ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10824: schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10825: namespaceName, &bucket);
10826:
10827: if (ret != 0)
10828: return(ret);
10829:
10830: /*
10831: * For <import>: "It is *not* an error for the application
10832: * schema reference strategy to fail."
10833: * So just don't parse if no schema document was found.
10834: * Note that we will get no bucket if the schema could not be
10835: * located or if there was no schemaLocation.
10836: */
10837: if ((bucket == NULL) && (schemaLocation != NULL)) {
10838: xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10839: XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10840: node, NULL,
10841: "Failed to locate a schema at location '%s'. "
10842: "Skipping the import", schemaLocation, NULL, NULL);
10843: }
10844:
10845: if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10846: ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10847: }
10848:
10849: return (ret);
10850: }
10851:
10852: static int
10853: xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10854: xmlSchemaPtr schema,
10855: xmlNodePtr node,
10856: xmlChar **schemaLocation,
10857: int type)
10858: {
10859: xmlAttrPtr attr;
10860:
10861: if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10862: (schemaLocation == NULL))
10863: return (-1);
10864:
10865: *schemaLocation = NULL;
10866: /*
10867: * Check for illegal attributes.
10868: * Applies for both <include> and <redefine>.
10869: */
10870: attr = node->properties;
10871: while (attr != NULL) {
10872: if (attr->ns == NULL) {
10873: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10874: (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10875: xmlSchemaPIllegalAttrErr(pctxt,
10876: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10877: }
10878: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10879: xmlSchemaPIllegalAttrErr(pctxt,
10880: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10881: }
10882: attr = attr->next;
10883: }
10884: xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10885: /*
10886: * Preliminary step, extract the URI-Reference and make an URI
10887: * from the base.
10888: */
10889: /*
10890: * Attribute "schemaLocation" is mandatory.
10891: */
10892: attr = xmlSchemaGetPropNode(node, "schemaLocation");
10893: if (attr != NULL) {
10894: xmlChar *base = NULL;
10895: xmlChar *uri = NULL;
10896:
10897: if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10898: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10899: (const xmlChar **) schemaLocation) != 0)
10900: goto exit_error;
10901: base = xmlNodeGetBase(node->doc, node);
10902: if (base == NULL) {
10903: uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10904: } else {
10905: uri = xmlBuildURI(*schemaLocation, base);
10906: xmlFree(base);
10907: }
10908: if (uri == NULL) {
10909: PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10910: "could not build an URI from the schemaLocation")
10911: goto exit_failure;
10912: }
10913: (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10914: xmlFree(uri);
10915: } else {
10916: xmlSchemaPMissingAttrErr(pctxt,
10917: XML_SCHEMAP_S4S_ATTR_MISSING,
10918: NULL, node, "schemaLocation", NULL);
10919: goto exit_error;
10920: }
10921: /*
10922: * Report self-inclusion and self-redefinition.
10923: */
10924: if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10925: if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10926: xmlSchemaPCustomErr(pctxt,
10927: XML_SCHEMAP_SRC_REDEFINE,
10928: NULL, node,
10929: "The schema document '%s' cannot redefine itself.",
10930: *schemaLocation);
10931: } else {
10932: xmlSchemaPCustomErr(pctxt,
10933: XML_SCHEMAP_SRC_INCLUDE,
10934: NULL, node,
10935: "The schema document '%s' cannot include itself.",
10936: *schemaLocation);
10937: }
10938: goto exit_error;
10939: }
10940:
10941: return(0);
10942: exit_error:
10943: return(pctxt->err);
10944: exit_failure:
10945: return(-1);
10946: }
10947:
10948: static int
10949: xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10950: xmlSchemaPtr schema,
10951: xmlNodePtr node,
10952: int type)
10953: {
10954: xmlNodePtr child = NULL;
10955: const xmlChar *schemaLocation = NULL;
10956: int res = 0; /* hasRedefinitions = 0 */
10957: int isChameleon = 0, wasChameleon = 0;
10958: xmlSchemaBucketPtr bucket = NULL;
10959:
10960: if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10961: return (-1);
10962:
10963: /*
10964: * Parse attributes. Note that the returned schemaLocation will
10965: * be already converted to an absolute URI.
10966: */
10967: res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10968: node, (xmlChar **) (&schemaLocation), type);
10969: if (res != 0)
10970: return(res);
10971: /*
10972: * Load and add the schema document.
10973: */
10974: res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10975: NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10976: if (res != 0)
10977: return(res);
10978: /*
10979: * If we get no schema bucket back, then this means that the schema
10980: * document could not be located or was broken XML or was not
10981: * a schema document.
10982: */
10983: if ((bucket == NULL) || (bucket->doc == NULL)) {
10984: if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10985: /*
10986: * WARNING for <include>:
10987: * We will raise an error if the schema cannot be located
10988: * for inclusions, since the that was the feedback from the
10989: * schema people. I.e. the following spec piece will *not* be
10990: * satisfied:
10991: * SPEC src-include: "It is not an error for the �actual value� of the
10992: * schemaLocation [attribute] to fail to resolve it all, in which
10993: * case no corresponding inclusion is performed.
10994: * So do we need a warning report here?"
10995: */
10996: res = XML_SCHEMAP_SRC_INCLUDE;
10997: xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10998: node, NULL,
10999: "Failed to load the document '%s' for inclusion",
11000: schemaLocation, NULL);
11001: } else {
11002: /*
11003: * NOTE: This was changed to raise an error even if no redefinitions
11004: * are specified.
11005: *
11006: * SPEC src-redefine (1)
11007: * "If there are any element information items among the [children]
11008: * other than <annotation> then the �actual value� of the
11009: * schemaLocation [attribute] must successfully resolve."
11010: * TODO: Ask the WG if a the location has always to resolve
11011: * here as well!
11012: */
11013: res = XML_SCHEMAP_SRC_REDEFINE;
11014: xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11015: node, NULL,
11016: "Failed to load the document '%s' for redefinition",
11017: schemaLocation, NULL);
11018: }
11019: } else {
11020: /*
11021: * Check targetNamespace sanity before parsing the new schema.
11022: * TODO: Note that we won't check further content if the
11023: * targetNamespace was bad.
11024: */
11025: if (bucket->origTargetNamespace != NULL) {
11026: /*
11027: * SPEC src-include (2.1)
11028: * "SII has a targetNamespace [attribute], and its �actual
11029: * value� is identical to the �actual value� of the targetNamespace
11030: * [attribute] of SII� (which must have such an [attribute])."
11031: */
11032: if (pctxt->targetNamespace == NULL) {
11033: xmlSchemaCustomErr(ACTXT_CAST pctxt,
11034: XML_SCHEMAP_SRC_INCLUDE,
11035: node, NULL,
11036: "The target namespace of the included/redefined schema "
11037: "'%s' has to be absent, since the including/redefining "
11038: "schema has no target namespace",
11039: schemaLocation, NULL);
11040: goto exit_error;
11041: } else if (!xmlStrEqual(bucket->origTargetNamespace,
11042: pctxt->targetNamespace)) {
11043: /* TODO: Change error function. */
11044: xmlSchemaPCustomErrExt(pctxt,
11045: XML_SCHEMAP_SRC_INCLUDE,
11046: NULL, node,
11047: "The target namespace '%s' of the included/redefined "
11048: "schema '%s' differs from '%s' of the "
11049: "including/redefining schema",
11050: bucket->origTargetNamespace, schemaLocation,
11051: pctxt->targetNamespace);
11052: goto exit_error;
11053: }
11054: } else if (pctxt->targetNamespace != NULL) {
11055: /*
11056: * Chameleons: the original target namespace will
11057: * differ from the resulting namespace.
11058: */
11059: isChameleon = 1;
11060: if (bucket->parsed &&
11061: bucket->origTargetNamespace != NULL) {
11062: xmlSchemaCustomErr(ACTXT_CAST pctxt,
11063: XML_SCHEMAP_SRC_INCLUDE,
11064: node, NULL,
11065: "The target namespace of the included/redefined schema "
11066: "'%s' has to be absent or the same as the "
11067: "including/redefining schema's target namespace",
11068: schemaLocation, NULL);
11069: goto exit_error;
11070: }
11071: bucket->targetNamespace = pctxt->targetNamespace;
11072: }
11073: }
11074: /*
11075: * Parse the schema.
11076: */
11077: if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11078: if (isChameleon) {
11079: /* TODO: Get rid of this flag on the schema itself. */
11080: if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11081: schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11082: } else
11083: wasChameleon = 1;
11084: }
11085: xmlSchemaParseNewDoc(pctxt, schema, bucket);
11086: /* Restore chameleon flag. */
11087: if (isChameleon && (!wasChameleon))
11088: schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11089: }
11090: /*
11091: * And now for the children...
11092: */
11093: child = node->children;
11094: if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11095: /*
11096: * Parse (simpleType | complexType | group | attributeGroup))*
11097: */
11098: pctxt->redefined = bucket;
11099: /*
11100: * How to proceed if the redefined schema was not located?
11101: */
11102: pctxt->isRedefine = 1;
11103: while (IS_SCHEMA(child, "annotation") ||
11104: IS_SCHEMA(child, "simpleType") ||
11105: IS_SCHEMA(child, "complexType") ||
11106: IS_SCHEMA(child, "group") ||
11107: IS_SCHEMA(child, "attributeGroup")) {
11108: if (IS_SCHEMA(child, "annotation")) {
11109: /*
11110: * TODO: discard or not?
11111: */
11112: } else if (IS_SCHEMA(child, "simpleType")) {
11113: xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11114: } else if (IS_SCHEMA(child, "complexType")) {
11115: xmlSchemaParseComplexType(pctxt, schema, child, 1);
11116: /* hasRedefinitions = 1; */
11117: } else if (IS_SCHEMA(child, "group")) {
11118: /* hasRedefinitions = 1; */
11119: xmlSchemaParseModelGroupDefinition(pctxt,
11120: schema, child);
11121: } else if (IS_SCHEMA(child, "attributeGroup")) {
11122: /* hasRedefinitions = 1; */
11123: xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11124: child);
11125: }
11126: child = child->next;
11127: }
11128: pctxt->redefined = NULL;
11129: pctxt->isRedefine = 0;
11130: } else {
11131: if (IS_SCHEMA(child, "annotation")) {
11132: /*
11133: * TODO: discard or not?
11134: */
11135: child = child->next;
11136: }
11137: }
11138: if (child != NULL) {
11139: res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11140: if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11141: xmlSchemaPContentErr(pctxt, res,
11142: NULL, node, child, NULL,
11143: "(annotation | (simpleType | complexType | group | attributeGroup))*");
11144: } else {
11145: xmlSchemaPContentErr(pctxt, res,
11146: NULL, node, child, NULL,
11147: "(annotation?)");
11148: }
11149: }
11150: return(res);
11151:
11152: exit_error:
11153: return(pctxt->err);
11154: }
11155:
11156: static int
11157: xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11158: xmlNodePtr node)
11159: {
11160: int res;
11161: #ifndef ENABLE_REDEFINE
11162: TODO
11163: return(0);
11164: #endif
11165: res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11166: XML_SCHEMA_SCHEMA_REDEFINE);
11167: if (res != 0)
11168: return(res);
11169: return(0);
11170: }
11171:
11172: static int
11173: xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11174: xmlNodePtr node)
11175: {
11176: int res;
11177:
11178: res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11179: XML_SCHEMA_SCHEMA_INCLUDE);
11180: if (res != 0)
11181: return(res);
11182: return(0);
11183: }
11184:
11185: /**
11186: * xmlSchemaParseModelGroup:
11187: * @ctxt: a schema validation context
11188: * @schema: the schema being built
11189: * @node: a subtree containing XML Schema informations
11190: * @type: the "compositor" type
11191: * @particleNeeded: if a a model group with a particle
11192: *
11193: * parse a XML schema Sequence definition.
11194: * Applies parts of:
11195: * Schema Representation Constraint:
11196: * Redefinition Constraints and Semantics (src-redefine)
11197: * (6.1), (6.1.1), (6.1.2)
11198: *
11199: * Schema Component Constraint:
11200: * All Group Limited (cos-all-limited) (2)
11201: * TODO: Actually this should go to component-level checks,
11202: * but is done here due to performance. Move it to an other layer
11203: * is schema construction via an API is implemented.
11204: *
11205: * *WARNING* this interface is highly subject to change
11206: *
11207: * Returns -1 in case of error, 0 if the declaration is improper and
11208: * 1 in case of success.
11209: */
11210: static xmlSchemaTreeItemPtr
11211: xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11212: xmlNodePtr node, xmlSchemaTypeType type,
11213: int withParticle)
11214: {
11215: xmlSchemaModelGroupPtr item;
11216: xmlSchemaParticlePtr particle = NULL;
11217: xmlNodePtr child = NULL;
11218: xmlAttrPtr attr;
11219: int min = 1, max = 1, isElemRef, hasRefs = 0;
11220:
11221: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11222: return (NULL);
11223: /*
11224: * Create a model group with the given compositor.
11225: */
11226: item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11227: if (item == NULL)
11228: return (NULL);
11229:
11230: if (withParticle) {
11231: if (type == XML_SCHEMA_TYPE_ALL) {
11232: min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11233: max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11234: } else {
11235: /* choice + sequence */
11236: min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11237: max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11238: "(xs:nonNegativeInteger | unbounded)");
11239: }
11240: xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11241: /*
11242: * Create a particle
11243: */
11244: particle = xmlSchemaAddParticle(ctxt, node, min, max);
11245: if (particle == NULL)
11246: return (NULL);
11247: particle->children = (xmlSchemaTreeItemPtr) item;
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: (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11256: (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11257: xmlSchemaPIllegalAttrErr(ctxt,
11258: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11259: }
11260: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11261: xmlSchemaPIllegalAttrErr(ctxt,
11262: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11263: }
11264: attr = attr->next;
11265: }
11266: } else {
11267: /*
11268: * Check for illegal attributes.
11269: */
11270: attr = node->properties;
11271: while (attr != NULL) {
11272: if (attr->ns == NULL) {
11273: if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11274: xmlSchemaPIllegalAttrErr(ctxt,
11275: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11276: }
11277: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11278: xmlSchemaPIllegalAttrErr(ctxt,
11279: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11280: }
11281: attr = attr->next;
11282: }
11283: }
11284:
11285: /*
11286: * Extract and validate attributes.
11287: */
11288: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11289: /*
11290: * And now for the children...
11291: */
11292: child = node->children;
11293: if (IS_SCHEMA(child, "annotation")) {
11294: item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11295: child = child->next;
11296: }
11297: if (type == XML_SCHEMA_TYPE_ALL) {
11298: xmlSchemaParticlePtr part, last = NULL;
11299:
11300: while (IS_SCHEMA(child, "element")) {
11301: part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11302: schema, child, &isElemRef, 0);
11303: /*
11304: * SPEC cos-all-limited (2)
11305: * "The {max occurs} of all the particles in the {particles}
11306: * of the ('all') group must be 0 or 1.
11307: */
11308: if (part != NULL) {
11309: if (isElemRef)
11310: hasRefs++;
11311: if (part->minOccurs > 1) {
11312: xmlSchemaPCustomErr(ctxt,
11313: XML_SCHEMAP_COS_ALL_LIMITED,
11314: NULL, child,
11315: "Invalid value for minOccurs (must be 0 or 1)",
11316: NULL);
11317: /* Reset to 1. */
11318: part->minOccurs = 1;
11319: }
11320: if (part->maxOccurs > 1) {
11321: xmlSchemaPCustomErr(ctxt,
11322: XML_SCHEMAP_COS_ALL_LIMITED,
11323: NULL, child,
11324: "Invalid value for maxOccurs (must be 0 or 1)",
11325: NULL);
11326: /* Reset to 1. */
11327: part->maxOccurs = 1;
11328: }
11329: if (last == NULL)
11330: item->children = (xmlSchemaTreeItemPtr) part;
11331: else
11332: last->next = (xmlSchemaTreeItemPtr) part;
11333: last = part;
11334: }
11335: child = child->next;
11336: }
11337: if (child != NULL) {
11338: xmlSchemaPContentErr(ctxt,
11339: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11340: NULL, node, child, NULL,
11341: "(annotation?, (annotation?, element*)");
11342: }
11343: } else {
11344: /* choice + sequence */
11345: xmlSchemaTreeItemPtr part = NULL, last = NULL;
11346:
11347: while ((IS_SCHEMA(child, "element")) ||
11348: (IS_SCHEMA(child, "group")) ||
11349: (IS_SCHEMA(child, "any")) ||
11350: (IS_SCHEMA(child, "choice")) ||
11351: (IS_SCHEMA(child, "sequence"))) {
11352:
11353: if (IS_SCHEMA(child, "element")) {
11354: part = (xmlSchemaTreeItemPtr)
11355: xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11356: if (part && isElemRef)
11357: hasRefs++;
11358: } else if (IS_SCHEMA(child, "group")) {
11359: part =
11360: xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11361: if (part != NULL)
11362: hasRefs++;
11363: /*
11364: * Handle redefinitions.
11365: */
11366: if (ctxt->isRedefine && ctxt->redef &&
11367: (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11368: part && part->children)
11369: {
11370: if ((xmlSchemaGetQNameRefName(part->children) ==
11371: ctxt->redef->refName) &&
11372: (xmlSchemaGetQNameRefTargetNs(part->children) ==
11373: ctxt->redef->refTargetNs))
11374: {
11375: /*
11376: * SPEC src-redefine:
11377: * (6.1) "If it has a <group> among its contents at
11378: * some level the �actual value� of whose ref
11379: * [attribute] is the same as the �actual value� of
11380: * its own name attribute plus target namespace, then
11381: * all of the following must be true:"
11382: * (6.1.1) "It must have exactly one such group."
11383: */
11384: if (ctxt->redefCounter != 0) {
11385: xmlChar *str = NULL;
11386:
11387: xmlSchemaCustomErr(ACTXT_CAST ctxt,
11388: XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11389: "The redefining model group definition "
11390: "'%s' must not contain more than one "
11391: "reference to the redefined definition",
11392: xmlSchemaFormatQName(&str,
11393: ctxt->redef->refTargetNs,
11394: ctxt->redef->refName),
11395: NULL);
11396: FREE_AND_NULL(str)
11397: part = NULL;
11398: } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11399: ((WXS_PARTICLE(part))->maxOccurs != 1))
11400: {
11401: xmlChar *str = NULL;
11402: /*
11403: * SPEC src-redefine:
11404: * (6.1.2) "The �actual value� of both that
11405: * group's minOccurs and maxOccurs [attribute]
11406: * must be 1 (or �absent�).
11407: */
11408: xmlSchemaCustomErr(ACTXT_CAST ctxt,
11409: XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11410: "The redefining model group definition "
11411: "'%s' must not contain a reference to the "
11412: "redefined definition with a "
11413: "maxOccurs/minOccurs other than 1",
11414: xmlSchemaFormatQName(&str,
11415: ctxt->redef->refTargetNs,
11416: ctxt->redef->refName),
11417: NULL);
11418: FREE_AND_NULL(str)
11419: part = NULL;
11420: }
11421: ctxt->redef->reference = WXS_BASIC_CAST part;
11422: ctxt->redefCounter++;
11423: }
11424: }
11425: } else if (IS_SCHEMA(child, "any")) {
11426: part = (xmlSchemaTreeItemPtr)
11427: xmlSchemaParseAny(ctxt, schema, child);
11428: } else if (IS_SCHEMA(child, "choice")) {
11429: part = xmlSchemaParseModelGroup(ctxt, schema, child,
11430: XML_SCHEMA_TYPE_CHOICE, 1);
11431: } else if (IS_SCHEMA(child, "sequence")) {
11432: part = xmlSchemaParseModelGroup(ctxt, schema, child,
11433: XML_SCHEMA_TYPE_SEQUENCE, 1);
11434: }
11435: if (part != NULL) {
11436: if (last == NULL)
11437: item->children = part;
11438: else
11439: last->next = part;
11440: last = part;
11441: }
11442: child = child->next;
11443: }
11444: if (child != NULL) {
11445: xmlSchemaPContentErr(ctxt,
11446: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11447: NULL, node, child, NULL,
11448: "(annotation?, (element | group | choice | sequence | any)*)");
11449: }
11450: }
11451: if ((max == 0) && (min == 0))
11452: return (NULL);
11453: if (hasRefs) {
11454: /*
11455: * We need to resolve references.
11456: */
11457: WXS_ADD_PENDING(ctxt, item);
11458: }
11459: if (withParticle)
11460: return ((xmlSchemaTreeItemPtr) particle);
11461: else
11462: return ((xmlSchemaTreeItemPtr) item);
11463: }
11464:
11465: /**
11466: * xmlSchemaParseRestriction:
11467: * @ctxt: a schema validation context
11468: * @schema: the schema being built
11469: * @node: a subtree containing XML Schema informations
11470: *
11471: * parse a XML schema Restriction definition
11472: * *WARNING* this interface is highly subject to change
11473: *
11474: * Returns the type definition or NULL in case of error
11475: */
11476: static xmlSchemaTypePtr
11477: xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11478: xmlNodePtr node, xmlSchemaTypeType parentType)
11479: {
11480: xmlSchemaTypePtr type;
11481: xmlNodePtr child = NULL;
11482: xmlAttrPtr attr;
11483:
11484: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11485: return (NULL);
11486: /* Not a component, don't create it. */
11487: type = ctxt->ctxtType;
11488: type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11489:
11490: /*
11491: * Check for illegal attributes.
11492: */
11493: attr = node->properties;
11494: while (attr != NULL) {
11495: if (attr->ns == NULL) {
11496: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11497: (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11498: xmlSchemaPIllegalAttrErr(ctxt,
11499: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11500: }
11501: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11502: xmlSchemaPIllegalAttrErr(ctxt,
11503: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11504: }
11505: attr = attr->next;
11506: }
11507: /*
11508: * Extract and validate attributes.
11509: */
11510: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11511: /*
11512: * Attribute
11513: */
11514: /*
11515: * Extract the base type. The "base" attribute is mandatory if inside
11516: * a complex type or if redefining.
11517: *
11518: * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11519: * among its [children]), the simple type definition which is
11520: * the {content type} of the type definition �resolved� to by
11521: * the �actual value� of the base [attribute]"
11522: */
11523: if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11524: &(type->baseNs), &(type->base)) == 0)
11525: {
11526: if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11527: xmlSchemaPMissingAttrErr(ctxt,
11528: XML_SCHEMAP_S4S_ATTR_MISSING,
11529: NULL, node, "base", NULL);
11530: } else if ((ctxt->isRedefine) &&
11531: (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11532: {
11533: if (type->base == NULL) {
11534: xmlSchemaPMissingAttrErr(ctxt,
11535: XML_SCHEMAP_S4S_ATTR_MISSING,
11536: NULL, node, "base", NULL);
11537: } else if ((! xmlStrEqual(type->base, type->name)) ||
11538: (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11539: {
11540: xmlChar *str1 = NULL, *str2 = NULL;
11541: /*
11542: * REDEFINE: SPEC src-redefine (5)
11543: * "Within the [children], each <simpleType> must have a
11544: * <restriction> among its [children] ... the �actual value� of
11545: * whose base [attribute] must be the same as the �actual value�
11546: * of its own name attribute plus target namespace;"
11547: */
11548: xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11549: NULL, node, "This is a redefinition, but the QName "
11550: "value '%s' of the 'base' attribute does not match the "
11551: "type's designation '%s'",
11552: xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11553: xmlSchemaFormatQName(&str2, type->targetNamespace,
11554: type->name), NULL);
11555: FREE_AND_NULL(str1);
11556: FREE_AND_NULL(str2);
11557: /* Avoid confusion and erase the values. */
11558: type->base = NULL;
11559: type->baseNs = NULL;
11560: }
11561: }
11562: }
11563: /*
11564: * And now for the children...
11565: */
11566: child = node->children;
11567: if (IS_SCHEMA(child, "annotation")) {
11568: /*
11569: * Add the annotation to the simple type ancestor.
11570: */
11571: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11572: xmlSchemaParseAnnotation(ctxt, child, 1));
11573: child = child->next;
11574: }
11575: if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11576: /*
11577: * Corresponds to <simpleType><restriction><simpleType>.
11578: */
11579: if (IS_SCHEMA(child, "simpleType")) {
11580: if (type->base != NULL) {
11581: /*
11582: * src-restriction-base-or-simpleType
11583: * Either the base [attribute] or the simpleType [child] of the
11584: * <restriction> element must be present, but not both.
11585: */
11586: xmlSchemaPContentErr(ctxt,
11587: XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11588: NULL, node, child,
11589: "The attribute 'base' and the <simpleType> child are "
11590: "mutually exclusive", NULL);
11591: } else {
11592: type->baseType = (xmlSchemaTypePtr)
11593: xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11594: }
11595: child = child->next;
11596: } else if (type->base == NULL) {
11597: xmlSchemaPContentErr(ctxt,
11598: XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11599: NULL, node, child,
11600: "Either the attribute 'base' or a <simpleType> child "
11601: "must be present", NULL);
11602: }
11603: } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11604: /*
11605: * Corresponds to <complexType><complexContent><restriction>...
11606: * followed by:
11607: *
11608: * Model groups <all>, <choice> and <sequence>.
11609: */
11610: if (IS_SCHEMA(child, "all")) {
11611: type->subtypes = (xmlSchemaTypePtr)
11612: xmlSchemaParseModelGroup(ctxt, schema, child,
11613: XML_SCHEMA_TYPE_ALL, 1);
11614: child = child->next;
11615: } else if (IS_SCHEMA(child, "choice")) {
11616: type->subtypes = (xmlSchemaTypePtr)
11617: xmlSchemaParseModelGroup(ctxt,
11618: schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11619: child = child->next;
11620: } else if (IS_SCHEMA(child, "sequence")) {
11621: type->subtypes = (xmlSchemaTypePtr)
11622: xmlSchemaParseModelGroup(ctxt, schema, child,
11623: XML_SCHEMA_TYPE_SEQUENCE, 1);
11624: child = child->next;
11625: /*
11626: * Model group reference <group>.
11627: */
11628: } else if (IS_SCHEMA(child, "group")) {
11629: type->subtypes = (xmlSchemaTypePtr)
11630: xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11631: /*
11632: * Note that the reference will be resolved in
11633: * xmlSchemaResolveTypeReferences();
11634: */
11635: child = child->next;
11636: }
11637: } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11638: /*
11639: * Corresponds to <complexType><simpleContent><restriction>...
11640: *
11641: * "1.1 the simple type definition corresponding to the <simpleType>
11642: * among the [children] of <restriction> if there is one;"
11643: */
11644: if (IS_SCHEMA(child, "simpleType")) {
11645: /*
11646: * We will store the to-be-restricted simple type in
11647: * type->contentTypeDef *temporarily*.
11648: */
11649: type->contentTypeDef = (xmlSchemaTypePtr)
11650: xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11651: if ( type->contentTypeDef == NULL)
11652: return (NULL);
11653: child = child->next;
11654: }
11655: }
11656:
11657: if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11658: (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11659: xmlSchemaFacetPtr facet, lastfacet = NULL;
11660: /*
11661: * Corresponds to <complexType><simpleContent><restriction>...
11662: * <simpleType><restriction>...
11663: */
11664:
11665: /*
11666: * Add the facets to the simple type ancestor.
11667: */
11668: /*
11669: * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11670: * Simple Type Definition Schema Representation Constraint:
11671: * *Single Facet Value*
11672: */
11673: while ((IS_SCHEMA(child, "minInclusive")) ||
11674: (IS_SCHEMA(child, "minExclusive")) ||
11675: (IS_SCHEMA(child, "maxInclusive")) ||
11676: (IS_SCHEMA(child, "maxExclusive")) ||
11677: (IS_SCHEMA(child, "totalDigits")) ||
11678: (IS_SCHEMA(child, "fractionDigits")) ||
11679: (IS_SCHEMA(child, "pattern")) ||
11680: (IS_SCHEMA(child, "enumeration")) ||
11681: (IS_SCHEMA(child, "whiteSpace")) ||
11682: (IS_SCHEMA(child, "length")) ||
11683: (IS_SCHEMA(child, "maxLength")) ||
11684: (IS_SCHEMA(child, "minLength"))) {
11685: facet = xmlSchemaParseFacet(ctxt, schema, child);
11686: if (facet != NULL) {
11687: if (lastfacet == NULL)
11688: type->facets = facet;
11689: else
11690: lastfacet->next = facet;
11691: lastfacet = facet;
11692: lastfacet->next = NULL;
11693: }
11694: child = child->next;
11695: }
11696: /*
11697: * Create links for derivation and validation.
11698: */
11699: if (type->facets != NULL) {
11700: xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11701:
11702: facet = type->facets;
11703: do {
11704: facetLink = (xmlSchemaFacetLinkPtr)
11705: xmlMalloc(sizeof(xmlSchemaFacetLink));
11706: if (facetLink == NULL) {
11707: xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11708: xmlFree(facetLink);
11709: return (NULL);
11710: }
11711: facetLink->facet = facet;
11712: facetLink->next = NULL;
11713: if (lastFacetLink == NULL)
11714: type->facetSet = facetLink;
11715: else
11716: lastFacetLink->next = facetLink;
11717: lastFacetLink = facetLink;
11718: facet = facet->next;
11719: } while (facet != NULL);
11720: }
11721: }
11722: if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11723: /*
11724: * Attribute uses/declarations.
11725: */
11726: if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11727: (xmlSchemaItemListPtr *) &(type->attrUses),
11728: XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11729: return(NULL);
11730: /*
11731: * Attribute wildcard.
11732: */
11733: if (IS_SCHEMA(child, "anyAttribute")) {
11734: type->attributeWildcard =
11735: xmlSchemaParseAnyAttribute(ctxt, schema, child);
11736: child = child->next;
11737: }
11738: }
11739: if (child != NULL) {
11740: if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11741: xmlSchemaPContentErr(ctxt,
11742: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11743: NULL, node, child, NULL,
11744: "annotation?, (group | all | choice | sequence)?, "
11745: "((attribute | attributeGroup)*, anyAttribute?))");
11746: } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11747: xmlSchemaPContentErr(ctxt,
11748: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11749: NULL, node, child, NULL,
11750: "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11751: "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11752: "length | minLength | maxLength | enumeration | whiteSpace | "
11753: "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11754: } else {
11755: /* Simple type */
11756: xmlSchemaPContentErr(ctxt,
11757: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11758: NULL, node, child, NULL,
11759: "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11760: "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11761: "length | minLength | maxLength | enumeration | whiteSpace | "
11762: "pattern)*))");
11763: }
11764: }
11765: return (NULL);
11766: }
11767:
11768: /**
11769: * xmlSchemaParseExtension:
11770: * @ctxt: a schema validation context
11771: * @schema: the schema being built
11772: * @node: a subtree containing XML Schema informations
11773: *
11774: * Parses an <extension>, which is found inside a
11775: * <simpleContent> or <complexContent>.
11776: * *WARNING* this interface is highly subject to change.
11777: *
11778: * TODO: Returns the type definition or NULL in case of error
11779: */
11780: static xmlSchemaTypePtr
11781: xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11782: xmlNodePtr node, xmlSchemaTypeType parentType)
11783: {
11784: xmlSchemaTypePtr type;
11785: xmlNodePtr child = NULL;
11786: xmlAttrPtr attr;
11787:
11788: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11789: return (NULL);
11790: /* Not a component, don't create it. */
11791: type = ctxt->ctxtType;
11792: type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11793:
11794: /*
11795: * Check for illegal attributes.
11796: */
11797: attr = node->properties;
11798: while (attr != NULL) {
11799: if (attr->ns == NULL) {
11800: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11801: (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11802: xmlSchemaPIllegalAttrErr(ctxt,
11803: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11804: }
11805: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11806: xmlSchemaPIllegalAttrErr(ctxt,
11807: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11808: }
11809: attr = attr->next;
11810: }
11811:
11812: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11813:
11814: /*
11815: * Attribute "base" - mandatory.
11816: */
11817: if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11818: "base", &(type->baseNs), &(type->base)) == 0) &&
11819: (type->base == NULL)) {
11820: xmlSchemaPMissingAttrErr(ctxt,
11821: XML_SCHEMAP_S4S_ATTR_MISSING,
11822: NULL, node, "base", NULL);
11823: }
11824: /*
11825: * And now for the children...
11826: */
11827: child = node->children;
11828: if (IS_SCHEMA(child, "annotation")) {
11829: /*
11830: * Add the annotation to the type ancestor.
11831: */
11832: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11833: xmlSchemaParseAnnotation(ctxt, child, 1));
11834: child = child->next;
11835: }
11836: if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11837: /*
11838: * Corresponds to <complexType><complexContent><extension>... and:
11839: *
11840: * Model groups <all>, <choice>, <sequence> and <group>.
11841: */
11842: if (IS_SCHEMA(child, "all")) {
11843: type->subtypes = (xmlSchemaTypePtr)
11844: xmlSchemaParseModelGroup(ctxt, schema,
11845: child, XML_SCHEMA_TYPE_ALL, 1);
11846: child = child->next;
11847: } else if (IS_SCHEMA(child, "choice")) {
11848: type->subtypes = (xmlSchemaTypePtr)
11849: xmlSchemaParseModelGroup(ctxt, schema,
11850: child, XML_SCHEMA_TYPE_CHOICE, 1);
11851: child = child->next;
11852: } else if (IS_SCHEMA(child, "sequence")) {
11853: type->subtypes = (xmlSchemaTypePtr)
11854: xmlSchemaParseModelGroup(ctxt, schema,
11855: child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11856: child = child->next;
11857: } else if (IS_SCHEMA(child, "group")) {
11858: type->subtypes = (xmlSchemaTypePtr)
11859: xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11860: /*
11861: * Note that the reference will be resolved in
11862: * xmlSchemaResolveTypeReferences();
11863: */
11864: child = child->next;
11865: }
11866: }
11867: if (child != NULL) {
11868: /*
11869: * Attribute uses/declarations.
11870: */
11871: if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11872: (xmlSchemaItemListPtr *) &(type->attrUses),
11873: XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11874: return(NULL);
11875: /*
11876: * Attribute wildcard.
11877: */
11878: if (IS_SCHEMA(child, "anyAttribute")) {
11879: ctxt->ctxtType->attributeWildcard =
11880: xmlSchemaParseAnyAttribute(ctxt, schema, child);
11881: child = child->next;
11882: }
11883: }
11884: if (child != NULL) {
11885: if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11886: /* Complex content extension. */
11887: xmlSchemaPContentErr(ctxt,
11888: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11889: NULL, node, child, NULL,
11890: "(annotation?, ((group | all | choice | sequence)?, "
11891: "((attribute | attributeGroup)*, anyAttribute?)))");
11892: } else {
11893: /* Simple content extension. */
11894: xmlSchemaPContentErr(ctxt,
11895: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11896: NULL, node, child, NULL,
11897: "(annotation?, ((attribute | attributeGroup)*, "
11898: "anyAttribute?))");
11899: }
11900: }
11901: return (NULL);
11902: }
11903:
11904: /**
11905: * xmlSchemaParseSimpleContent:
11906: * @ctxt: a schema validation context
11907: * @schema: the schema being built
11908: * @node: a subtree containing XML Schema informations
11909: *
11910: * parse a XML schema SimpleContent definition
11911: * *WARNING* this interface is highly subject to change
11912: *
11913: * Returns the type definition or NULL in case of error
11914: */
11915: static int
11916: xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11917: xmlSchemaPtr schema, xmlNodePtr node,
11918: int *hasRestrictionOrExtension)
11919: {
11920: xmlSchemaTypePtr type;
11921: xmlNodePtr child = NULL;
11922: xmlAttrPtr attr;
11923:
11924: if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11925: (hasRestrictionOrExtension == NULL))
11926: return (-1);
11927: *hasRestrictionOrExtension = 0;
11928: /* Not a component, don't create it. */
11929: type = ctxt->ctxtType;
11930: type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11931: /*
11932: * Check for illegal attributes.
11933: */
11934: attr = node->properties;
11935: while (attr != NULL) {
11936: if (attr->ns == NULL) {
11937: if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11938: xmlSchemaPIllegalAttrErr(ctxt,
11939: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11940: }
11941: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11942: xmlSchemaPIllegalAttrErr(ctxt,
11943: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11944: }
11945: attr = attr->next;
11946: }
11947:
11948: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11949:
11950: /*
11951: * And now for the children...
11952: */
11953: child = node->children;
11954: if (IS_SCHEMA(child, "annotation")) {
11955: /*
11956: * Add the annotation to the complex type ancestor.
11957: */
11958: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11959: xmlSchemaParseAnnotation(ctxt, child, 1));
11960: child = child->next;
11961: }
11962: if (child == NULL) {
11963: xmlSchemaPContentErr(ctxt,
11964: XML_SCHEMAP_S4S_ELEM_MISSING,
11965: NULL, node, NULL, NULL,
11966: "(annotation?, (restriction | extension))");
11967: }
11968: if (child == NULL) {
11969: xmlSchemaPContentErr(ctxt,
11970: XML_SCHEMAP_S4S_ELEM_MISSING,
11971: NULL, node, NULL, NULL,
11972: "(annotation?, (restriction | extension))");
11973: }
11974: if (IS_SCHEMA(child, "restriction")) {
11975: xmlSchemaParseRestriction(ctxt, schema, child,
11976: XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11977: (*hasRestrictionOrExtension) = 1;
11978: child = child->next;
11979: } else if (IS_SCHEMA(child, "extension")) {
11980: xmlSchemaParseExtension(ctxt, schema, child,
11981: XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11982: (*hasRestrictionOrExtension) = 1;
11983: child = child->next;
11984: }
11985: if (child != NULL) {
11986: xmlSchemaPContentErr(ctxt,
11987: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11988: NULL, node, child, NULL,
11989: "(annotation?, (restriction | extension))");
11990: }
11991: return (0);
11992: }
11993:
11994: /**
11995: * xmlSchemaParseComplexContent:
11996: * @ctxt: a schema validation context
11997: * @schema: the schema being built
11998: * @node: a subtree containing XML Schema informations
11999: *
12000: * parse a XML schema ComplexContent definition
12001: * *WARNING* this interface is highly subject to change
12002: *
12003: * Returns the type definition or NULL in case of error
12004: */
12005: static int
12006: xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12007: xmlSchemaPtr schema, xmlNodePtr node,
12008: int *hasRestrictionOrExtension)
12009: {
12010: xmlSchemaTypePtr type;
12011: xmlNodePtr child = NULL;
12012: xmlAttrPtr attr;
12013:
12014: if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12015: (hasRestrictionOrExtension == NULL))
12016: return (-1);
12017: *hasRestrictionOrExtension = 0;
12018: /* Not a component, don't create it. */
12019: type = ctxt->ctxtType;
12020: /*
12021: * Check for illegal attributes.
12022: */
12023: attr = node->properties;
12024: while (attr != NULL) {
12025: if (attr->ns == NULL) {
12026: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12027: (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12028: {
12029: xmlSchemaPIllegalAttrErr(ctxt,
12030: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12031: }
12032: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12033: xmlSchemaPIllegalAttrErr(ctxt,
12034: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12035: }
12036: attr = attr->next;
12037: }
12038:
12039: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12040:
12041: /*
12042: * Set the 'mixed' on the complex type ancestor.
12043: */
12044: if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
12045: if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12046: type->flags |= XML_SCHEMAS_TYPE_MIXED;
12047: }
12048: child = node->children;
12049: if (IS_SCHEMA(child, "annotation")) {
12050: /*
12051: * Add the annotation to the complex type ancestor.
12052: */
12053: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12054: xmlSchemaParseAnnotation(ctxt, child, 1));
12055: child = child->next;
12056: }
12057: if (child == NULL) {
12058: xmlSchemaPContentErr(ctxt,
12059: XML_SCHEMAP_S4S_ELEM_MISSING,
12060: NULL, node, NULL,
12061: NULL, "(annotation?, (restriction | extension))");
12062: }
12063: if (child == NULL) {
12064: xmlSchemaPContentErr(ctxt,
12065: XML_SCHEMAP_S4S_ELEM_MISSING,
12066: NULL, node, NULL,
12067: NULL, "(annotation?, (restriction | extension))");
12068: }
12069: if (IS_SCHEMA(child, "restriction")) {
12070: xmlSchemaParseRestriction(ctxt, schema, child,
12071: XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12072: (*hasRestrictionOrExtension) = 1;
12073: child = child->next;
12074: } else if (IS_SCHEMA(child, "extension")) {
12075: xmlSchemaParseExtension(ctxt, schema, child,
12076: XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12077: (*hasRestrictionOrExtension) = 1;
12078: child = child->next;
12079: }
12080: if (child != NULL) {
12081: xmlSchemaPContentErr(ctxt,
12082: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12083: NULL, node, child,
12084: NULL, "(annotation?, (restriction | extension))");
12085: }
12086: return (0);
12087: }
12088:
12089: /**
12090: * xmlSchemaParseComplexType:
12091: * @ctxt: a schema validation context
12092: * @schema: the schema being built
12093: * @node: a subtree containing XML Schema informations
12094: *
12095: * parse a XML schema Complex Type definition
12096: * *WARNING* this interface is highly subject to change
12097: *
12098: * Returns the type definition or NULL in case of error
12099: */
12100: static xmlSchemaTypePtr
12101: xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12102: xmlNodePtr node, int topLevel)
12103: {
12104: xmlSchemaTypePtr type, ctxtType;
12105: xmlNodePtr child = NULL;
12106: const xmlChar *name = NULL;
12107: xmlAttrPtr attr;
12108: const xmlChar *attrValue;
12109: #ifdef ENABLE_NAMED_LOCALS
12110: char buf[40];
12111: #endif
12112: int final = 0, block = 0, hasRestrictionOrExtension = 0;
12113:
12114:
12115: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12116: return (NULL);
12117:
12118: ctxtType = ctxt->ctxtType;
12119:
12120: if (topLevel) {
12121: attr = xmlSchemaGetPropNode(node, "name");
12122: if (attr == NULL) {
12123: xmlSchemaPMissingAttrErr(ctxt,
12124: XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12125: return (NULL);
12126: } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12127: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12128: return (NULL);
12129: }
12130: }
12131:
12132: if (topLevel == 0) {
12133: /*
12134: * Parse as local complex type definition.
12135: */
12136: #ifdef ENABLE_NAMED_LOCALS
12137: snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12138: type = xmlSchemaAddType(ctxt, schema,
12139: XML_SCHEMA_TYPE_COMPLEX,
12140: xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12141: ctxt->targetNamespace, node, 0);
12142: #else
12143: type = xmlSchemaAddType(ctxt, schema,
12144: XML_SCHEMA_TYPE_COMPLEX,
12145: NULL, ctxt->targetNamespace, node, 0);
12146: #endif
12147: if (type == NULL)
12148: return (NULL);
12149: name = type->name;
12150: type->node = node;
12151: type->type = XML_SCHEMA_TYPE_COMPLEX;
12152: /*
12153: * TODO: We need the target namespace.
12154: */
12155: } else {
12156: /*
12157: * Parse as global complex type definition.
12158: */
12159: type = xmlSchemaAddType(ctxt, schema,
12160: XML_SCHEMA_TYPE_COMPLEX,
12161: name, ctxt->targetNamespace, node, 1);
12162: if (type == NULL)
12163: return (NULL);
12164: type->node = node;
12165: type->type = XML_SCHEMA_TYPE_COMPLEX;
12166: type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12167: }
12168: type->targetNamespace = ctxt->targetNamespace;
12169: /*
12170: * Handle attributes.
12171: */
12172: attr = node->properties;
12173: while (attr != NULL) {
12174: if (attr->ns == NULL) {
12175: if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12176: /*
12177: * Attribute "id".
12178: */
12179: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12180: } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12181: /*
12182: * Attribute "mixed".
12183: */
12184: if (xmlSchemaPGetBoolNodeValue(ctxt,
12185: NULL, (xmlNodePtr) attr))
12186: type->flags |= XML_SCHEMAS_TYPE_MIXED;
12187: } else if (topLevel) {
12188: /*
12189: * Attributes of global complex type definitions.
12190: */
12191: if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12192: /* Pass. */
12193: } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12194: /*
12195: * Attribute "abstract".
12196: */
12197: if (xmlSchemaPGetBoolNodeValue(ctxt,
12198: NULL, (xmlNodePtr) attr))
12199: type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12200: } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12201: /*
12202: * Attribute "final".
12203: */
12204: attrValue = xmlSchemaGetNodeContent(ctxt,
12205: (xmlNodePtr) attr);
12206: if (xmlSchemaPValAttrBlockFinal(attrValue,
12207: &(type->flags),
12208: -1,
12209: XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12210: XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12211: -1, -1, -1) != 0)
12212: {
12213: xmlSchemaPSimpleTypeErr(ctxt,
12214: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12215: NULL, (xmlNodePtr) attr, NULL,
12216: "(#all | List of (extension | restriction))",
12217: attrValue, NULL, NULL, NULL);
12218: } else
12219: final = 1;
12220: } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12221: /*
12222: * Attribute "block".
12223: */
12224: attrValue = xmlSchemaGetNodeContent(ctxt,
12225: (xmlNodePtr) attr);
12226: if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12227: -1,
12228: XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12229: XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12230: -1, -1, -1) != 0) {
12231: xmlSchemaPSimpleTypeErr(ctxt,
12232: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12233: NULL, (xmlNodePtr) attr, NULL,
12234: "(#all | List of (extension | restriction)) ",
12235: attrValue, NULL, NULL, NULL);
12236: } else
12237: block = 1;
12238: } else {
12239: xmlSchemaPIllegalAttrErr(ctxt,
12240: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12241: }
12242: } else {
12243: xmlSchemaPIllegalAttrErr(ctxt,
12244: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12245: }
12246: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12247: xmlSchemaPIllegalAttrErr(ctxt,
12248: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12249: }
12250: attr = attr->next;
12251: }
12252: if (! block) {
12253: /*
12254: * Apply default "block" values.
12255: */
12256: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12257: type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12258: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12259: type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12260: }
12261: if (! final) {
12262: /*
12263: * Apply default "block" values.
12264: */
12265: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12266: type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12267: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12268: type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12269: }
12270: /*
12271: * And now for the children...
12272: */
12273: child = node->children;
12274: if (IS_SCHEMA(child, "annotation")) {
12275: type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12276: child = child->next;
12277: }
12278: ctxt->ctxtType = type;
12279: if (IS_SCHEMA(child, "simpleContent")) {
12280: /*
12281: * <complexType><simpleContent>...
12282: * 3.4.3 : 2.2
12283: * Specifying mixed='true' when the <simpleContent>
12284: * alternative is chosen has no effect
12285: */
12286: if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12287: type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12288: xmlSchemaParseSimpleContent(ctxt, schema, child,
12289: &hasRestrictionOrExtension);
12290: child = child->next;
12291: } else if (IS_SCHEMA(child, "complexContent")) {
12292: /*
12293: * <complexType><complexContent>...
12294: */
12295: type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12296: xmlSchemaParseComplexContent(ctxt, schema, child,
12297: &hasRestrictionOrExtension);
12298: child = child->next;
12299: } else {
12300: /*
12301: * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12302: *
12303: * SPEC
12304: * "...the third alternative (neither <simpleContent> nor
12305: * <complexContent>) is chosen. This case is understood as shorthand
12306: * for complex content restricting the �ur-type definition�, and the
12307: * details of the mappings should be modified as necessary.
12308: */
12309: type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12310: type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12311: /*
12312: * Parse model groups.
12313: */
12314: if (IS_SCHEMA(child, "all")) {
12315: type->subtypes = (xmlSchemaTypePtr)
12316: xmlSchemaParseModelGroup(ctxt, schema, child,
12317: XML_SCHEMA_TYPE_ALL, 1);
12318: child = child->next;
12319: } else if (IS_SCHEMA(child, "choice")) {
12320: type->subtypes = (xmlSchemaTypePtr)
12321: xmlSchemaParseModelGroup(ctxt, schema, child,
12322: XML_SCHEMA_TYPE_CHOICE, 1);
12323: child = child->next;
12324: } else if (IS_SCHEMA(child, "sequence")) {
12325: type->subtypes = (xmlSchemaTypePtr)
12326: xmlSchemaParseModelGroup(ctxt, schema, child,
12327: XML_SCHEMA_TYPE_SEQUENCE, 1);
12328: child = child->next;
12329: } else if (IS_SCHEMA(child, "group")) {
12330: type->subtypes = (xmlSchemaTypePtr)
12331: xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12332: /*
12333: * Note that the reference will be resolved in
12334: * xmlSchemaResolveTypeReferences();
12335: */
12336: child = child->next;
12337: }
12338: /*
12339: * Parse attribute decls/refs.
12340: */
12341: if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12342: (xmlSchemaItemListPtr *) &(type->attrUses),
12343: XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12344: return(NULL);
12345: /*
12346: * Parse attribute wildcard.
12347: */
12348: if (IS_SCHEMA(child, "anyAttribute")) {
12349: type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12350: child = child->next;
12351: }
12352: }
12353: if (child != NULL) {
12354: xmlSchemaPContentErr(ctxt,
12355: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12356: NULL, node, child,
12357: NULL, "(annotation?, (simpleContent | complexContent | "
12358: "((group | all | choice | sequence)?, ((attribute | "
12359: "attributeGroup)*, anyAttribute?))))");
12360: }
12361: /*
12362: * REDEFINE: SPEC src-redefine (5)
12363: */
12364: if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12365: xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12366: NULL, node, "This is a redefinition, thus the "
12367: "<complexType> must have a <restriction> or <extension> "
12368: "grand-child", NULL);
12369: }
12370: ctxt->ctxtType = ctxtType;
12371: return (type);
12372: }
12373:
12374: /************************************************************************
1.1.1.3 ! misho 12375: * *
! 12376: * Validating using Schemas *
! 12377: * *
1.1 misho 12378: ************************************************************************/
12379:
12380: /************************************************************************
1.1.1.3 ! misho 12381: * *
! 12382: * Reading/Writing Schemas *
! 12383: * *
1.1 misho 12384: ************************************************************************/
12385:
12386: #if 0 /* Will be enabled if it is clear what options are needed. */
12387: /**
12388: * xmlSchemaParserCtxtSetOptions:
12389: * @ctxt: a schema parser context
12390: * @options: a combination of xmlSchemaParserOption
12391: *
12392: * Sets the options to be used during the parse.
12393: *
12394: * Returns 0 in case of success, -1 in case of an
12395: * API error.
12396: */
12397: static int
12398: xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12399: int options)
12400:
12401: {
12402: int i;
12403:
12404: if (ctxt == NULL)
12405: return (-1);
12406: /*
12407: * WARNING: Change the start value if adding to the
12408: * xmlSchemaParseOption.
12409: */
12410: for (i = 1; i < (int) sizeof(int) * 8; i++) {
12411: if (options & 1<<i) {
12412: return (-1);
12413: }
12414: }
12415: ctxt->options = options;
12416: return (0);
12417: }
12418:
12419: /**
12420: * xmlSchemaValidCtxtGetOptions:
12421: * @ctxt: a schema parser context
12422: *
12423: * Returns the option combination of the parser context.
12424: */
12425: static int
12426: xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12427:
12428: {
12429: if (ctxt == NULL)
12430: return (-1);
12431: else
12432: return (ctxt->options);
12433: }
12434: #endif
12435:
12436: /**
12437: * xmlSchemaNewParserCtxt:
12438: * @URL: the location of the schema
12439: *
12440: * Create an XML Schemas parse context for that file/resource expected
12441: * to contain an XML Schemas file.
12442: *
12443: * Returns the parser context or NULL in case of error
12444: */
12445: xmlSchemaParserCtxtPtr
12446: xmlSchemaNewParserCtxt(const char *URL)
12447: {
12448: xmlSchemaParserCtxtPtr ret;
12449:
12450: if (URL == NULL)
12451: return (NULL);
12452:
12453: ret = xmlSchemaParserCtxtCreate();
12454: if (ret == NULL)
12455: return(NULL);
12456: ret->dict = xmlDictCreate();
12457: ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12458: return (ret);
12459: }
12460:
12461: /**
12462: * xmlSchemaNewMemParserCtxt:
12463: * @buffer: a pointer to a char array containing the schemas
12464: * @size: the size of the array
12465: *
12466: * Create an XML Schemas parse context for that memory buffer expected
12467: * to contain an XML Schemas file.
12468: *
12469: * Returns the parser context or NULL in case of error
12470: */
12471: xmlSchemaParserCtxtPtr
12472: xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12473: {
12474: xmlSchemaParserCtxtPtr ret;
12475:
12476: if ((buffer == NULL) || (size <= 0))
12477: return (NULL);
12478: ret = xmlSchemaParserCtxtCreate();
12479: if (ret == NULL)
12480: return(NULL);
12481: ret->buffer = buffer;
12482: ret->size = size;
12483: ret->dict = xmlDictCreate();
12484: return (ret);
12485: }
12486:
12487: /**
12488: * xmlSchemaNewDocParserCtxt:
12489: * @doc: a preparsed document tree
12490: *
12491: * Create an XML Schemas parse context for that document.
12492: * NB. The document may be modified during the parsing process.
12493: *
12494: * Returns the parser context or NULL in case of error
12495: */
12496: xmlSchemaParserCtxtPtr
12497: xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12498: {
12499: xmlSchemaParserCtxtPtr ret;
12500:
12501: if (doc == NULL)
12502: return (NULL);
12503: ret = xmlSchemaParserCtxtCreate();
12504: if (ret == NULL)
12505: return(NULL);
12506: ret->doc = doc;
12507: ret->dict = xmlDictCreate();
12508: /* The application has responsibility for the document */
12509: ret->preserve = 1;
12510:
12511: return (ret);
12512: }
12513:
12514: /**
12515: * xmlSchemaFreeParserCtxt:
12516: * @ctxt: the schema parser context
12517: *
12518: * Free the resources associated to the schema parser context
12519: */
12520: void
12521: xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12522: {
12523: if (ctxt == NULL)
12524: return;
12525: if (ctxt->doc != NULL && !ctxt->preserve)
12526: xmlFreeDoc(ctxt->doc);
12527: if (ctxt->vctxt != NULL) {
12528: xmlSchemaFreeValidCtxt(ctxt->vctxt);
12529: }
12530: if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12531: xmlSchemaConstructionCtxtFree(ctxt->constructor);
12532: ctxt->constructor = NULL;
12533: ctxt->ownsConstructor = 0;
12534: }
12535: if (ctxt->attrProhibs != NULL)
12536: xmlSchemaItemListFree(ctxt->attrProhibs);
12537: xmlDictFree(ctxt->dict);
12538: xmlFree(ctxt);
12539: }
12540:
12541: /************************************************************************
12542: * *
12543: * Building the content models *
12544: * *
12545: ************************************************************************/
12546:
12547: /**
12548: * xmlSchemaBuildContentModelForSubstGroup:
12549: *
12550: * Returns 1 if nillable, 0 otherwise
12551: */
12552: static int
12553: xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12554: xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12555: {
12556: xmlAutomataStatePtr start, tmp;
12557: xmlSchemaElementPtr elemDecl, member;
12558: xmlSchemaSubstGroupPtr substGroup;
12559: int i;
12560: int ret = 0;
12561:
12562: elemDecl = (xmlSchemaElementPtr) particle->children;
12563: /*
12564: * Wrap the substitution group with a CHOICE.
12565: */
12566: start = pctxt->state;
12567: if (end == NULL)
12568: end = xmlAutomataNewState(pctxt->am);
12569: substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12570: if (substGroup == NULL) {
12571: xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12572: XML_SCHEMAP_INTERNAL,
12573: "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12574: "declaration is marked having a subst. group but none "
12575: "available.\n", elemDecl->name, NULL);
12576: return(0);
12577: }
12578: if (counter >= 0) {
12579: /*
12580: * NOTE that we put the declaration in, even if it's abstract.
12581: * However, an error will be raised during *validation* if an element
12582: * information item shall be validated against an abstract element
12583: * declaration.
12584: */
12585: tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12586: xmlAutomataNewTransition2(pctxt->am, tmp, end,
12587: elemDecl->name, elemDecl->targetNamespace, elemDecl);
12588: /*
12589: * Add subst. group members.
12590: */
12591: for (i = 0; i < substGroup->members->nbItems; i++) {
12592: member = (xmlSchemaElementPtr) substGroup->members->items[i];
12593: xmlAutomataNewTransition2(pctxt->am, tmp, end,
12594: member->name, member->targetNamespace, member);
12595: }
12596: } else if (particle->maxOccurs == 1) {
12597: /*
12598: * NOTE that we put the declaration in, even if it's abstract,
12599: */
12600: xmlAutomataNewEpsilon(pctxt->am,
12601: xmlAutomataNewTransition2(pctxt->am,
12602: start, NULL,
12603: elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12604: /*
12605: * Add subst. group members.
12606: */
12607: for (i = 0; i < substGroup->members->nbItems; i++) {
12608: member = (xmlSchemaElementPtr) substGroup->members->items[i];
12609: /*
12610: * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12611: * was incorrectly used instead of xmlAutomataNewTransition2()
12612: * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12613: * section in xmlSchemaBuildAContentModel() ).
12614: * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12615: * intended for the above "counter" section originally. I.e.,
12616: * check xs:all with subst-groups.
12617: *
12618: * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12619: * member->name, member->targetNamespace,
12620: * 1, 1, member);
12621: */
12622: tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12623: member->name, member->targetNamespace, member);
12624: xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12625: }
12626: } else {
12627: xmlAutomataStatePtr hop;
12628: int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12629: UNBOUNDED : particle->maxOccurs - 1;
12630: int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12631:
12632: counter =
12633: xmlAutomataNewCounter(pctxt->am, minOccurs,
12634: maxOccurs);
12635: hop = xmlAutomataNewState(pctxt->am);
12636:
12637: xmlAutomataNewEpsilon(pctxt->am,
12638: xmlAutomataNewTransition2(pctxt->am,
12639: start, NULL,
12640: elemDecl->name, elemDecl->targetNamespace, elemDecl),
12641: hop);
12642: /*
12643: * Add subst. group members.
12644: */
12645: for (i = 0; i < substGroup->members->nbItems; i++) {
12646: member = (xmlSchemaElementPtr) substGroup->members->items[i];
12647: xmlAutomataNewEpsilon(pctxt->am,
12648: xmlAutomataNewTransition2(pctxt->am,
12649: start, NULL,
12650: member->name, member->targetNamespace, member),
12651: hop);
12652: }
12653: xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12654: xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12655: }
12656: if (particle->minOccurs == 0) {
12657: xmlAutomataNewEpsilon(pctxt->am, start, end);
12658: ret = 1;
12659: }
12660: pctxt->state = end;
12661: return(ret);
12662: }
12663:
12664: /**
12665: * xmlSchemaBuildContentModelForElement:
12666: *
12667: * Returns 1 if nillable, 0 otherwise
12668: */
12669: static int
12670: xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12671: xmlSchemaParticlePtr particle)
12672: {
12673: int ret = 0;
12674:
12675: if (((xmlSchemaElementPtr) particle->children)->flags &
12676: XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12677: /*
12678: * Substitution groups.
12679: */
12680: ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12681: } else {
12682: xmlSchemaElementPtr elemDecl;
12683: xmlAutomataStatePtr start;
12684:
12685: elemDecl = (xmlSchemaElementPtr) particle->children;
12686:
12687: if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12688: return(0);
12689: if (particle->maxOccurs == 1) {
12690: start = ctxt->state;
12691: ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12692: elemDecl->name, elemDecl->targetNamespace, elemDecl);
12693: } else if ((particle->maxOccurs >= UNBOUNDED) &&
12694: (particle->minOccurs < 2)) {
12695: /* Special case. */
12696: start = ctxt->state;
12697: ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12698: elemDecl->name, elemDecl->targetNamespace, elemDecl);
12699: ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12700: elemDecl->name, elemDecl->targetNamespace, elemDecl);
12701: } else {
12702: int counter;
12703: int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12704: UNBOUNDED : particle->maxOccurs - 1;
12705: int minOccurs = particle->minOccurs < 1 ?
12706: 0 : particle->minOccurs - 1;
12707:
12708: start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12709: counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12710: ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12711: elemDecl->name, elemDecl->targetNamespace, elemDecl);
12712: xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12713: ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12714: NULL, counter);
12715: }
12716: if (particle->minOccurs == 0) {
12717: xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12718: ret = 1;
12719: }
12720: }
12721: return(ret);
12722: }
12723:
12724: /**
12725: * xmlSchemaBuildAContentModel:
12726: * @ctxt: the schema parser context
12727: * @particle: the particle component
12728: * @name: the complex type's name whose content is being built
12729: *
12730: * Create the automaton for the {content type} of a complex type.
12731: *
12732: * Returns 1 if the content is nillable, 0 otherwise
12733: */
12734: static int
12735: xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12736: xmlSchemaParticlePtr particle)
12737: {
12738: int ret = 0, tmp2;
12739:
12740: if (particle == NULL) {
12741: PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12742: return(1);
12743: }
12744: if (particle->children == NULL) {
12745: /*
12746: * Just return in this case. A missing "term" of the particle
12747: * might arise due to an invalid "term" component.
12748: */
12749: return(1);
12750: }
12751:
12752: switch (particle->children->type) {
12753: case XML_SCHEMA_TYPE_ANY: {
12754: xmlAutomataStatePtr start, end;
12755: xmlSchemaWildcardPtr wild;
12756: xmlSchemaWildcardNsPtr ns;
12757:
12758: wild = (xmlSchemaWildcardPtr) particle->children;
12759:
12760: start = pctxt->state;
12761: end = xmlAutomataNewState(pctxt->am);
12762:
12763: if (particle->maxOccurs == 1) {
12764: if (wild->any == 1) {
12765: /*
12766: * We need to add both transitions:
12767: *
12768: * 1. the {"*", "*"} for elements in a namespace.
12769: */
12770: pctxt->state =
12771: xmlAutomataNewTransition2(pctxt->am,
12772: start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12773: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12774: /*
12775: * 2. the {"*"} for elements in no namespace.
12776: */
12777: pctxt->state =
12778: xmlAutomataNewTransition2(pctxt->am,
12779: start, NULL, BAD_CAST "*", NULL, wild);
12780: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12781:
12782: } else if (wild->nsSet != NULL) {
12783: ns = wild->nsSet;
12784: do {
12785: pctxt->state = start;
12786: pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12787: pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12788: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12789: ns = ns->next;
12790: } while (ns != NULL);
12791:
12792: } else if (wild->negNsSet != NULL) {
12793: pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12794: start, end, BAD_CAST "*", wild->negNsSet->value,
12795: wild);
12796: }
12797: } else {
12798: int counter;
12799: xmlAutomataStatePtr hop;
12800: int maxOccurs =
12801: particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12802: particle->maxOccurs - 1;
12803: int minOccurs =
12804: particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12805:
12806: counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12807: hop = xmlAutomataNewState(pctxt->am);
12808: if (wild->any == 1) {
12809: pctxt->state =
12810: xmlAutomataNewTransition2(pctxt->am,
12811: start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12812: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12813: pctxt->state =
12814: xmlAutomataNewTransition2(pctxt->am,
12815: start, NULL, BAD_CAST "*", NULL, wild);
12816: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12817: } else if (wild->nsSet != NULL) {
12818: ns = wild->nsSet;
12819: do {
12820: pctxt->state =
12821: xmlAutomataNewTransition2(pctxt->am,
12822: start, NULL, BAD_CAST "*", ns->value, wild);
12823: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12824: ns = ns->next;
12825: } while (ns != NULL);
12826:
12827: } else if (wild->negNsSet != NULL) {
12828: pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12829: start, hop, BAD_CAST "*", wild->negNsSet->value,
12830: wild);
12831: }
12832: xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12833: xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12834: }
12835: if (particle->minOccurs == 0) {
12836: xmlAutomataNewEpsilon(pctxt->am, start, end);
12837: ret = 1;
12838: }
12839: pctxt->state = end;
12840: break;
12841: }
12842: case XML_SCHEMA_TYPE_ELEMENT:
12843: ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12844: break;
12845: case XML_SCHEMA_TYPE_SEQUENCE:{
12846: xmlSchemaTreeItemPtr sub;
12847:
12848: ret = 1;
12849: /*
12850: * If max and min occurances are default (1) then
12851: * simply iterate over the particles of the <sequence>.
12852: */
12853: if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12854: sub = particle->children->children;
12855:
12856: while (sub != NULL) {
12857: tmp2 = xmlSchemaBuildAContentModel(pctxt,
12858: (xmlSchemaParticlePtr) sub);
12859: if (tmp2 != 1) ret = 0;
12860: sub = sub->next;
12861: }
12862: } else {
12863: xmlAutomataStatePtr oldstate = pctxt->state;
12864:
12865: if (particle->maxOccurs >= UNBOUNDED) {
12866: if (particle->minOccurs > 1) {
12867: xmlAutomataStatePtr tmp;
12868: int counter;
12869:
12870: pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12871: oldstate, NULL);
12872: oldstate = pctxt->state;
12873:
12874: counter = xmlAutomataNewCounter(pctxt->am,
12875: particle->minOccurs - 1, UNBOUNDED);
12876:
12877: sub = particle->children->children;
12878: while (sub != NULL) {
12879: tmp2 = xmlSchemaBuildAContentModel(pctxt,
12880: (xmlSchemaParticlePtr) sub);
12881: if (tmp2 != 1) ret = 0;
12882: sub = sub->next;
12883: }
12884: tmp = pctxt->state;
12885: xmlAutomataNewCountedTrans(pctxt->am, tmp,
12886: oldstate, counter);
12887: pctxt->state =
12888: xmlAutomataNewCounterTrans(pctxt->am, tmp,
12889: NULL, counter);
12890: if (ret == 1)
12891: xmlAutomataNewEpsilon(pctxt->am,
12892: oldstate, pctxt->state);
12893:
12894: } else {
12895: pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12896: oldstate, NULL);
12897: oldstate = pctxt->state;
12898:
12899: sub = particle->children->children;
12900: while (sub != NULL) {
12901: tmp2 = xmlSchemaBuildAContentModel(pctxt,
12902: (xmlSchemaParticlePtr) sub);
12903: if (tmp2 != 1) ret = 0;
12904: sub = sub->next;
12905: }
12906: xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12907: oldstate);
12908: /*
12909: * epsilon needed to block previous trans from
12910: * being allowed to enter back from another
12911: * construct
12912: */
12913: pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12914: pctxt->state, NULL);
12915: if (particle->minOccurs == 0) {
12916: xmlAutomataNewEpsilon(pctxt->am,
12917: oldstate, pctxt->state);
12918: ret = 1;
12919: }
12920: }
12921: } else if ((particle->maxOccurs > 1)
12922: || (particle->minOccurs > 1)) {
12923: xmlAutomataStatePtr tmp;
12924: int counter;
12925:
12926: pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12927: oldstate, NULL);
12928: oldstate = pctxt->state;
12929:
12930: counter = xmlAutomataNewCounter(pctxt->am,
12931: particle->minOccurs - 1,
12932: particle->maxOccurs - 1);
12933:
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: tmp = pctxt->state;
12942: xmlAutomataNewCountedTrans(pctxt->am,
12943: tmp, oldstate, counter);
12944: pctxt->state =
12945: xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12946: counter);
12947: if ((particle->minOccurs == 0) || (ret == 1)) {
12948: xmlAutomataNewEpsilon(pctxt->am,
12949: oldstate, pctxt->state);
12950: ret = 1;
12951: }
12952: } else {
12953: sub = particle->children->children;
12954: while (sub != NULL) {
12955: tmp2 = xmlSchemaBuildAContentModel(pctxt,
12956: (xmlSchemaParticlePtr) sub);
12957: if (tmp2 != 1) ret = 0;
12958: sub = sub->next;
12959: }
1.1.1.3 ! misho 12960:
! 12961: /*
! 12962: * epsilon needed to block previous trans from
! 12963: * being allowed to enter back from another
! 12964: * construct
! 12965: */
! 12966: pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
! 12967: pctxt->state, NULL);
! 12968:
1.1 misho 12969: if (particle->minOccurs == 0) {
12970: xmlAutomataNewEpsilon(pctxt->am, oldstate,
12971: pctxt->state);
12972: ret = 1;
12973: }
12974: }
12975: }
12976: break;
12977: }
12978: case XML_SCHEMA_TYPE_CHOICE:{
12979: xmlSchemaTreeItemPtr sub;
12980: xmlAutomataStatePtr start, end;
12981:
12982: ret = 0;
12983: start = pctxt->state;
12984: end = xmlAutomataNewState(pctxt->am);
12985:
12986: /*
12987: * iterate over the subtypes and remerge the end with an
12988: * epsilon transition
12989: */
12990: if (particle->maxOccurs == 1) {
12991: sub = particle->children->children;
12992: while (sub != NULL) {
12993: pctxt->state = start;
12994: tmp2 = xmlSchemaBuildAContentModel(pctxt,
12995: (xmlSchemaParticlePtr) sub);
12996: if (tmp2 == 1) ret = 1;
12997: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12998: sub = sub->next;
12999: }
13000: } else {
13001: int counter;
13002: xmlAutomataStatePtr hop, base;
13003: int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13004: UNBOUNDED : particle->maxOccurs - 1;
13005: int minOccurs =
13006: particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13007:
13008: /*
13009: * use a counter to keep track of the number of transtions
13010: * which went through the choice.
13011: */
13012: counter =
13013: xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13014: hop = xmlAutomataNewState(pctxt->am);
13015: base = xmlAutomataNewState(pctxt->am);
13016:
13017: sub = particle->children->children;
13018: while (sub != NULL) {
13019: pctxt->state = base;
13020: tmp2 = xmlSchemaBuildAContentModel(pctxt,
13021: (xmlSchemaParticlePtr) sub);
13022: if (tmp2 == 1) ret = 1;
13023: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13024: sub = sub->next;
13025: }
13026: xmlAutomataNewEpsilon(pctxt->am, start, base);
13027: xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13028: xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13029: if (ret == 1)
13030: xmlAutomataNewEpsilon(pctxt->am, base, end);
13031: }
13032: if (particle->minOccurs == 0) {
13033: xmlAutomataNewEpsilon(pctxt->am, start, end);
13034: ret = 1;
13035: }
13036: pctxt->state = end;
13037: break;
13038: }
13039: case XML_SCHEMA_TYPE_ALL:{
13040: xmlAutomataStatePtr start, tmp;
13041: xmlSchemaParticlePtr sub;
13042: xmlSchemaElementPtr elemDecl;
13043:
13044: ret = 1;
13045:
13046: sub = (xmlSchemaParticlePtr) particle->children->children;
13047: if (sub == NULL)
13048: break;
13049:
13050: ret = 0;
13051:
13052: start = pctxt->state;
13053: tmp = xmlAutomataNewState(pctxt->am);
13054: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13055: pctxt->state = tmp;
13056: while (sub != NULL) {
13057: pctxt->state = tmp;
13058:
13059: elemDecl = (xmlSchemaElementPtr) sub->children;
13060: if (elemDecl == NULL) {
13061: PERROR_INT("xmlSchemaBuildAContentModel",
13062: "<element> particle has no term");
13063: return(ret);
13064: };
13065: /*
13066: * NOTE: The {max occurs} of all the particles in the
13067: * {particles} of the group must be 0 or 1; this is
13068: * already ensured during the parse of the content of
13069: * <all>.
13070: */
13071: if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13072: int counter;
13073:
13074: /*
13075: * This is an abstract group, we need to share
13076: * the same counter for all the element transitions
13077: * derived from the group
13078: */
13079: counter = xmlAutomataNewCounter(pctxt->am,
13080: sub->minOccurs, sub->maxOccurs);
13081: xmlSchemaBuildContentModelForSubstGroup(pctxt,
13082: sub, counter, pctxt->state);
13083: } else {
13084: if ((sub->minOccurs == 1) &&
13085: (sub->maxOccurs == 1)) {
13086: xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13087: pctxt->state,
13088: elemDecl->name,
13089: elemDecl->targetNamespace,
13090: 1, 1, elemDecl);
13091: } else if ((sub->minOccurs == 0) &&
13092: (sub->maxOccurs == 1)) {
13093:
13094: xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13095: pctxt->state,
13096: elemDecl->name,
13097: elemDecl->targetNamespace,
13098: 0,
13099: 1,
13100: elemDecl);
13101: }
13102: }
13103: sub = (xmlSchemaParticlePtr) sub->next;
13104: }
13105: pctxt->state =
13106: xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13107: if (particle->minOccurs == 0) {
13108: xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13109: ret = 1;
13110: }
13111: break;
13112: }
13113: case XML_SCHEMA_TYPE_GROUP:
13114: /*
13115: * If we hit a model group definition, then this means that
13116: * it was empty, thus was not substituted for the containing
13117: * model group. Just do nothing in this case.
13118: * TODO: But the group should be substituted and not occur at
13119: * all in the content model at this point. Fix this.
13120: */
13121: ret = 1;
13122: break;
13123: default:
13124: xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13125: "xmlSchemaBuildAContentModel",
13126: "found unexpected term of type '%s' in content model",
13127: WXS_ITEM_TYPE_NAME(particle->children), NULL);
13128: return(ret);
13129: }
13130: return(ret);
13131: }
13132:
13133: /**
13134: * xmlSchemaBuildContentModel:
13135: * @ctxt: the schema parser context
13136: * @type: the complex type definition
13137: * @name: the element name
13138: *
13139: * Builds the content model of the complex type.
13140: */
13141: static void
13142: xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13143: xmlSchemaParserCtxtPtr ctxt)
13144: {
13145: if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13146: (type->contModel != NULL) ||
13147: ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13148: (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13149: return;
13150:
13151: #ifdef DEBUG_CONTENT
13152: xmlGenericError(xmlGenericErrorContext,
13153: "Building content model for %s\n", name);
13154: #endif
13155: ctxt->am = NULL;
13156: ctxt->am = xmlNewAutomata();
13157: if (ctxt->am == NULL) {
13158: xmlGenericError(xmlGenericErrorContext,
13159: "Cannot create automata for complex type %s\n", type->name);
13160: return;
13161: }
13162: ctxt->state = xmlAutomataGetInitState(ctxt->am);
13163: /*
13164: * Build the automaton.
13165: */
13166: xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13167: xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13168: type->contModel = xmlAutomataCompile(ctxt->am);
13169: if (type->contModel == NULL) {
13170: xmlSchemaPCustomErr(ctxt,
13171: XML_SCHEMAP_INTERNAL,
13172: WXS_BASIC_CAST type, type->node,
13173: "Failed to compile the content model", NULL);
13174: } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13175: xmlSchemaPCustomErr(ctxt,
13176: XML_SCHEMAP_NOT_DETERMINISTIC,
13177: /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13178: WXS_BASIC_CAST type, type->node,
13179: "The content model is not determinist", NULL);
13180: } else {
13181: #ifdef DEBUG_CONTENT_REGEXP
13182: xmlGenericError(xmlGenericErrorContext,
13183: "Content model of %s:\n", type->name);
13184: xmlRegexpPrint(stderr, type->contModel);
13185: #endif
13186: }
13187: ctxt->state = NULL;
13188: xmlFreeAutomata(ctxt->am);
13189: ctxt->am = NULL;
13190: }
13191:
13192: /**
13193: * xmlSchemaResolveElementReferences:
13194: * @elem: the schema element context
13195: * @ctxt: the schema parser context
13196: *
13197: * Resolves the references of an element declaration
13198: * or particle, which has an element declaration as it's
13199: * term.
13200: */
13201: static void
13202: xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13203: xmlSchemaParserCtxtPtr ctxt)
13204: {
13205: if ((ctxt == NULL) || (elemDecl == NULL) ||
13206: ((elemDecl != NULL) &&
13207: (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13208: return;
13209: elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13210:
13211: if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13212: xmlSchemaTypePtr type;
13213:
13214: /* (type definition) ... otherwise the type definition �resolved�
13215: * to by the �actual value� of the type [attribute] ...
13216: */
13217: type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13218: elemDecl->namedTypeNs);
13219: if (type == NULL) {
13220: xmlSchemaPResCompAttrErr(ctxt,
13221: XML_SCHEMAP_SRC_RESOLVE,
13222: WXS_BASIC_CAST elemDecl, elemDecl->node,
13223: "type", elemDecl->namedType, elemDecl->namedTypeNs,
13224: XML_SCHEMA_TYPE_BASIC, "type definition");
13225: } else
13226: elemDecl->subtypes = type;
13227: }
13228: if (elemDecl->substGroup != NULL) {
13229: xmlSchemaElementPtr substHead;
13230:
13231: /*
13232: * FIXME TODO: Do we need a new field in _xmlSchemaElement for
13233: * substitutionGroup?
13234: */
13235: substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13236: elemDecl->substGroupNs);
13237: if (substHead == NULL) {
13238: xmlSchemaPResCompAttrErr(ctxt,
13239: XML_SCHEMAP_SRC_RESOLVE,
13240: WXS_BASIC_CAST elemDecl, NULL,
13241: "substitutionGroup", elemDecl->substGroup,
13242: elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13243: } else {
13244: xmlSchemaResolveElementReferences(substHead, ctxt);
13245: /*
13246: * Set the "substitution group affiliation".
13247: * NOTE that now we use the "refDecl" field for this.
13248: */
13249: WXS_SUBST_HEAD(elemDecl) = substHead;
13250: /*
13251: * The type definitions is set to:
13252: * SPEC "...the {type definition} of the element
13253: * declaration �resolved� to by the �actual value�
13254: * of the substitutionGroup [attribute], if present"
13255: */
13256: if (elemDecl->subtypes == NULL)
13257: elemDecl->subtypes = substHead->subtypes;
13258: }
13259: }
13260: /*
13261: * SPEC "The definition of anyType serves as the default type definition
13262: * for element declarations whose XML representation does not specify one."
13263: */
13264: if ((elemDecl->subtypes == NULL) &&
13265: (elemDecl->namedType == NULL) &&
13266: (elemDecl->substGroup == NULL))
13267: elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13268: }
13269:
13270: /**
13271: * xmlSchemaResolveUnionMemberTypes:
13272: * @ctxt: the schema parser context
13273: * @type: the schema simple type definition
13274: *
13275: * Checks and builds the "member type definitions" property of the union
13276: * simple type. This handles part (1), part (2) is done in
13277: * xmlSchemaFinishMemberTypeDefinitionsProperty()
13278: *
13279: * Returns -1 in case of an internal error, 0 otherwise.
13280: */
13281: static int
13282: xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13283: xmlSchemaTypePtr type)
13284: {
13285:
13286: xmlSchemaTypeLinkPtr link, lastLink, newLink;
13287: xmlSchemaTypePtr memberType;
13288:
13289: /*
13290: * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13291: * define the explicit members as the type definitions �resolved�
13292: * to by the items in the �actual value� of the memberTypes [attribute],
13293: * if any, followed by the type definitions corresponding to the
13294: * <simpleType>s among the [children] of <union>, if any."
13295: */
13296: /*
13297: * Resolve references.
13298: */
13299: link = type->memberTypes;
13300: lastLink = NULL;
13301: while (link != NULL) {
13302: const xmlChar *name, *nsName;
13303:
13304: name = ((xmlSchemaQNameRefPtr) link->type)->name;
13305: nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13306:
13307: memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13308: if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13309: xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13310: WXS_BASIC_CAST type, type->node, "memberTypes",
13311: name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13312: /*
13313: * Remove the member type link.
13314: */
13315: if (lastLink == NULL)
13316: type->memberTypes = link->next;
13317: else
13318: lastLink->next = link->next;
13319: newLink = link;
13320: link = link->next;
13321: xmlFree(newLink);
13322: } else {
13323: link->type = memberType;
13324: lastLink = link;
13325: link = link->next;
13326: }
13327: }
13328: /*
13329: * Add local simple types,
13330: */
13331: memberType = type->subtypes;
13332: while (memberType != NULL) {
13333: link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13334: if (link == NULL) {
13335: xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13336: return (-1);
13337: }
13338: link->type = memberType;
13339: link->next = NULL;
13340: if (lastLink == NULL)
13341: type->memberTypes = link;
13342: else
13343: lastLink->next = link;
13344: lastLink = link;
13345: memberType = memberType->next;
13346: }
13347: return (0);
13348: }
13349:
13350: /**
13351: * xmlSchemaIsDerivedFromBuiltInType:
13352: * @ctxt: the schema parser context
13353: * @type: the type definition
13354: * @valType: the value type
13355: *
13356: *
13357: * Returns 1 if the type has the given value type, or
13358: * is derived from such a type.
13359: */
13360: static int
13361: xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13362: {
13363: if (type == NULL)
13364: return (0);
13365: if (WXS_IS_COMPLEX(type))
13366: return (0);
13367: if (type->type == XML_SCHEMA_TYPE_BASIC) {
13368: if (type->builtInType == valType)
13369: return(1);
13370: if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13371: (type->builtInType == XML_SCHEMAS_ANYTYPE))
13372: return (0);
13373: return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13374: }
13375: return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13376: }
13377:
13378: #if 0
13379: /**
13380: * xmlSchemaIsDerivedFromBuiltInType:
13381: * @ctxt: the schema parser context
13382: * @type: the type definition
13383: * @valType: the value type
13384: *
13385: *
13386: * Returns 1 if the type has the given value type, or
13387: * is derived from such a type.
13388: */
13389: static int
13390: xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13391: {
13392: if (type == NULL)
13393: return (0);
13394: if (WXS_IS_COMPLEX(type))
13395: return (0);
13396: if (type->type == XML_SCHEMA_TYPE_BASIC) {
13397: if (type->builtInType == valType)
13398: return(1);
13399: return (0);
13400: } else
13401: return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13402:
13403: return (0);
13404: }
13405:
13406: static xmlSchemaTypePtr
13407: xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13408: {
13409: if (type == NULL)
13410: return (NULL);
13411: if (WXS_IS_COMPLEX(type))
13412: return (NULL);
13413: if (type->type == XML_SCHEMA_TYPE_BASIC)
13414: return(type);
13415: return(xmlSchemaQueryBuiltInType(type->subtypes));
13416: }
13417: #endif
13418:
13419: /**
13420: * xmlSchemaGetPrimitiveType:
13421: * @type: the simpleType definition
13422: *
13423: * Returns the primitive type of the given type or
13424: * NULL in case of error.
13425: */
13426: static xmlSchemaTypePtr
13427: xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13428: {
13429:
13430: while (type != NULL) {
13431: /*
13432: * Note that anySimpleType is actually not a primitive type
13433: * but we need that here.
13434: */
13435: if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13436: (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13437: return (type);
13438: type = type->baseType;
13439: }
13440:
13441: return (NULL);
13442: }
13443:
13444: #if 0
13445: /**
13446: * xmlSchemaGetBuiltInTypeAncestor:
13447: * @type: the simpleType definition
13448: *
13449: * Returns the primitive type of the given type or
13450: * NULL in case of error.
13451: */
13452: static xmlSchemaTypePtr
13453: xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13454: {
13455: if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13456: return (0);
13457: while (type != NULL) {
13458: if (type->type == XML_SCHEMA_TYPE_BASIC)
13459: return (type);
13460: type = type->baseType;
13461: }
13462:
13463: return (NULL);
13464: }
13465: #endif
13466:
13467: /**
13468: * xmlSchemaCloneWildcardNsConstraints:
13469: * @ctxt: the schema parser context
13470: * @dest: the destination wildcard
13471: * @source: the source wildcard
13472: *
13473: * Clones the namespace constraints of source
13474: * and assignes them to dest.
13475: * Returns -1 on internal error, 0 otherwise.
13476: */
13477: static int
13478: xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13479: xmlSchemaWildcardPtr dest,
13480: xmlSchemaWildcardPtr source)
13481: {
13482: xmlSchemaWildcardNsPtr cur, tmp, last;
13483:
13484: if ((source == NULL) || (dest == NULL))
13485: return(-1);
13486: dest->any = source->any;
13487: cur = source->nsSet;
13488: last = NULL;
13489: while (cur != NULL) {
13490: tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13491: if (tmp == NULL)
13492: return(-1);
13493: tmp->value = cur->value;
13494: if (last == NULL)
13495: dest->nsSet = tmp;
13496: else
13497: last->next = tmp;
13498: last = tmp;
13499: cur = cur->next;
13500: }
13501: if (dest->negNsSet != NULL)
13502: xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13503: if (source->negNsSet != NULL) {
13504: dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13505: if (dest->negNsSet == NULL)
13506: return(-1);
13507: dest->negNsSet->value = source->negNsSet->value;
13508: } else
13509: dest->negNsSet = NULL;
13510: return(0);
13511: }
13512:
13513: /**
13514: * xmlSchemaUnionWildcards:
13515: * @ctxt: the schema parser context
13516: * @completeWild: the first wildcard
13517: * @curWild: the second wildcard
13518: *
13519: * Unions the namespace constraints of the given wildcards.
13520: * @completeWild will hold the resulting union.
13521: * Returns a positive error code on failure, -1 in case of an
13522: * internal error, 0 otherwise.
13523: */
13524: static int
13525: xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13526: xmlSchemaWildcardPtr completeWild,
13527: xmlSchemaWildcardPtr curWild)
13528: {
13529: xmlSchemaWildcardNsPtr cur, curB, tmp;
13530:
13531: /*
13532: * 1 If O1 and O2 are the same value, then that value must be the
13533: * value.
13534: */
13535: if ((completeWild->any == curWild->any) &&
13536: ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13537: ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13538:
13539: if ((completeWild->negNsSet == NULL) ||
13540: (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13541:
13542: if (completeWild->nsSet != NULL) {
13543: int found = 0;
13544:
13545: /*
13546: * Check equality of sets.
13547: */
13548: cur = completeWild->nsSet;
13549: while (cur != NULL) {
13550: found = 0;
13551: curB = curWild->nsSet;
13552: while (curB != NULL) {
13553: if (cur->value == curB->value) {
13554: found = 1;
13555: break;
13556: }
13557: curB = curB->next;
13558: }
13559: if (!found)
13560: break;
13561: cur = cur->next;
13562: }
13563: if (found)
13564: return(0);
13565: } else
13566: return(0);
13567: }
13568: }
13569: /*
13570: * 2 If either O1 or O2 is any, then any must be the value
13571: */
13572: if (completeWild->any != curWild->any) {
13573: if (completeWild->any == 0) {
13574: completeWild->any = 1;
13575: if (completeWild->nsSet != NULL) {
13576: xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13577: completeWild->nsSet = NULL;
13578: }
13579: if (completeWild->negNsSet != NULL) {
13580: xmlFree(completeWild->negNsSet);
13581: completeWild->negNsSet = NULL;
13582: }
13583: }
13584: return (0);
13585: }
13586: /*
13587: * 3 If both O1 and O2 are sets of (namespace names or �absent�),
13588: * then the union of those sets must be the value.
13589: */
13590: if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13591: int found;
13592: xmlSchemaWildcardNsPtr start;
13593:
13594: cur = curWild->nsSet;
13595: start = completeWild->nsSet;
13596: while (cur != NULL) {
13597: found = 0;
13598: curB = start;
13599: while (curB != NULL) {
13600: if (cur->value == curB->value) {
13601: found = 1;
13602: break;
13603: }
13604: curB = curB->next;
13605: }
13606: if (!found) {
13607: tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13608: if (tmp == NULL)
13609: return (-1);
13610: tmp->value = cur->value;
13611: tmp->next = completeWild->nsSet;
13612: completeWild->nsSet = tmp;
13613: }
13614: cur = cur->next;
13615: }
13616:
13617: return(0);
13618: }
13619: /*
13620: * 4 If the two are negations of different values (namespace names
13621: * or �absent�), then a pair of not and �absent� must be the value.
13622: */
13623: if ((completeWild->negNsSet != NULL) &&
13624: (curWild->negNsSet != NULL) &&
13625: (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13626: completeWild->negNsSet->value = NULL;
13627:
13628: return(0);
13629: }
13630: /*
13631: * 5.
13632: */
13633: if (((completeWild->negNsSet != NULL) &&
13634: (completeWild->negNsSet->value != NULL) &&
13635: (curWild->nsSet != NULL)) ||
13636: ((curWild->negNsSet != NULL) &&
13637: (curWild->negNsSet->value != NULL) &&
13638: (completeWild->nsSet != NULL))) {
13639:
13640: int nsFound, absentFound = 0;
13641:
13642: if (completeWild->nsSet != NULL) {
13643: cur = completeWild->nsSet;
13644: curB = curWild->negNsSet;
13645: } else {
13646: cur = curWild->nsSet;
13647: curB = completeWild->negNsSet;
13648: }
13649: nsFound = 0;
13650: while (cur != NULL) {
13651: if (cur->value == NULL)
13652: absentFound = 1;
13653: else if (cur->value == curB->value)
13654: nsFound = 1;
13655: if (nsFound && absentFound)
13656: break;
13657: cur = cur->next;
13658: }
13659:
13660: if (nsFound && absentFound) {
13661: /*
13662: * 5.1 If the set S includes both the negated namespace
13663: * name and �absent�, then any must be the value.
13664: */
13665: completeWild->any = 1;
13666: if (completeWild->nsSet != NULL) {
13667: xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13668: completeWild->nsSet = NULL;
13669: }
13670: if (completeWild->negNsSet != NULL) {
13671: xmlFree(completeWild->negNsSet);
13672: completeWild->negNsSet = NULL;
13673: }
13674: } else if (nsFound && (!absentFound)) {
13675: /*
13676: * 5.2 If the set S includes the negated namespace name
13677: * but not �absent�, then a pair of not and �absent� must
13678: * be the value.
13679: */
13680: if (completeWild->nsSet != NULL) {
13681: xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13682: completeWild->nsSet = NULL;
13683: }
13684: if (completeWild->negNsSet == NULL) {
13685: completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13686: if (completeWild->negNsSet == NULL)
13687: return (-1);
13688: }
13689: completeWild->negNsSet->value = NULL;
13690: } else if ((!nsFound) && absentFound) {
13691: /*
13692: * 5.3 If the set S includes �absent� but not the negated
13693: * namespace name, then the union is not expressible.
13694: */
13695: xmlSchemaPErr(ctxt, completeWild->node,
13696: XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13697: "The union of the wilcard is not expressible.\n",
13698: NULL, NULL);
13699: return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13700: } else if ((!nsFound) && (!absentFound)) {
13701: /*
13702: * 5.4 If the set S does not include either the negated namespace
13703: * name or �absent�, then whichever of O1 or O2 is a pair of not
13704: * and a namespace name must be the value.
13705: */
13706: if (completeWild->negNsSet == NULL) {
13707: if (completeWild->nsSet != NULL) {
13708: xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13709: completeWild->nsSet = NULL;
13710: }
13711: completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13712: if (completeWild->negNsSet == NULL)
13713: return (-1);
13714: completeWild->negNsSet->value = curWild->negNsSet->value;
13715: }
13716: }
13717: return (0);
13718: }
13719: /*
13720: * 6.
13721: */
13722: if (((completeWild->negNsSet != NULL) &&
13723: (completeWild->negNsSet->value == NULL) &&
13724: (curWild->nsSet != NULL)) ||
13725: ((curWild->negNsSet != NULL) &&
13726: (curWild->negNsSet->value == NULL) &&
13727: (completeWild->nsSet != NULL))) {
13728:
13729: if (completeWild->nsSet != NULL) {
13730: cur = completeWild->nsSet;
13731: } else {
13732: cur = curWild->nsSet;
13733: }
13734: while (cur != NULL) {
13735: if (cur->value == NULL) {
13736: /*
13737: * 6.1 If the set S includes �absent�, then any must be the
13738: * value.
13739: */
13740: completeWild->any = 1;
13741: if (completeWild->nsSet != NULL) {
13742: xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13743: completeWild->nsSet = NULL;
13744: }
13745: if (completeWild->negNsSet != NULL) {
13746: xmlFree(completeWild->negNsSet);
13747: completeWild->negNsSet = NULL;
13748: }
13749: return (0);
13750: }
13751: cur = cur->next;
13752: }
13753: if (completeWild->negNsSet == NULL) {
13754: /*
13755: * 6.2 If the set S does not include �absent�, then a pair of not
13756: * and �absent� must be the value.
13757: */
13758: if (completeWild->nsSet != NULL) {
13759: xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13760: completeWild->nsSet = NULL;
13761: }
13762: completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13763: if (completeWild->negNsSet == NULL)
13764: return (-1);
13765: completeWild->negNsSet->value = NULL;
13766: }
13767: return (0);
13768: }
13769: return (0);
13770:
13771: }
13772:
13773: /**
13774: * xmlSchemaIntersectWildcards:
13775: * @ctxt: the schema parser context
13776: * @completeWild: the first wildcard
13777: * @curWild: the second wildcard
13778: *
13779: * Intersects the namespace constraints of the given wildcards.
13780: * @completeWild will hold the resulting intersection.
13781: * Returns a positive error code on failure, -1 in case of an
13782: * internal error, 0 otherwise.
13783: */
13784: static int
13785: xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13786: xmlSchemaWildcardPtr completeWild,
13787: xmlSchemaWildcardPtr curWild)
13788: {
13789: xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
13790:
13791: /*
13792: * 1 If O1 and O2 are the same value, then that value must be the
13793: * value.
13794: */
13795: if ((completeWild->any == curWild->any) &&
13796: ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13797: ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13798:
13799: if ((completeWild->negNsSet == NULL) ||
13800: (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13801:
13802: if (completeWild->nsSet != NULL) {
13803: int found = 0;
13804:
13805: /*
13806: * Check equality of sets.
13807: */
13808: cur = completeWild->nsSet;
13809: while (cur != NULL) {
13810: found = 0;
13811: curB = curWild->nsSet;
13812: while (curB != NULL) {
13813: if (cur->value == curB->value) {
13814: found = 1;
13815: break;
13816: }
13817: curB = curB->next;
13818: }
13819: if (!found)
13820: break;
13821: cur = cur->next;
13822: }
13823: if (found)
13824: return(0);
13825: } else
13826: return(0);
13827: }
13828: }
13829: /*
13830: * 2 If either O1 or O2 is any, then the other must be the value.
13831: */
13832: if ((completeWild->any != curWild->any) && (completeWild->any)) {
13833: if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13834: return(-1);
13835: return(0);
13836: }
13837: /*
13838: * 3 If either O1 or O2 is a pair of not and a value (a namespace
13839: * name or �absent�) and the other is a set of (namespace names or
13840: * �absent�), then that set, minus the negated value if it was in
13841: * the set, minus �absent� if it was in the set, must be the value.
13842: */
13843: if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13844: ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13845: const xmlChar *neg;
13846:
13847: if (completeWild->nsSet == NULL) {
13848: neg = completeWild->negNsSet->value;
13849: if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13850: return(-1);
13851: } else
13852: neg = curWild->negNsSet->value;
13853: /*
13854: * Remove absent and negated.
13855: */
13856: prev = NULL;
13857: cur = completeWild->nsSet;
13858: while (cur != NULL) {
13859: if (cur->value == NULL) {
13860: if (prev == NULL)
13861: completeWild->nsSet = cur->next;
13862: else
13863: prev->next = cur->next;
13864: xmlFree(cur);
13865: break;
13866: }
13867: prev = cur;
13868: cur = cur->next;
13869: }
13870: if (neg != NULL) {
13871: prev = NULL;
13872: cur = completeWild->nsSet;
13873: while (cur != NULL) {
13874: if (cur->value == neg) {
13875: if (prev == NULL)
13876: completeWild->nsSet = cur->next;
13877: else
13878: prev->next = cur->next;
13879: xmlFree(cur);
13880: break;
13881: }
13882: prev = cur;
13883: cur = cur->next;
13884: }
13885: }
13886:
13887: return(0);
13888: }
13889: /*
13890: * 4 If both O1 and O2 are sets of (namespace names or �absent�),
13891: * then the intersection of those sets must be the value.
13892: */
13893: if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13894: int found;
13895:
13896: cur = completeWild->nsSet;
13897: prev = NULL;
13898: while (cur != NULL) {
13899: found = 0;
13900: curB = curWild->nsSet;
13901: while (curB != NULL) {
13902: if (cur->value == curB->value) {
13903: found = 1;
13904: break;
13905: }
13906: curB = curB->next;
13907: }
13908: if (!found) {
13909: if (prev == NULL)
13910: completeWild->nsSet = cur->next;
13911: else
13912: prev->next = cur->next;
13913: tmp = cur->next;
13914: xmlFree(cur);
13915: cur = tmp;
13916: continue;
13917: }
13918: prev = cur;
13919: cur = cur->next;
13920: }
13921:
13922: return(0);
13923: }
13924: /* 5 If the two are negations of different namespace names,
13925: * then the intersection is not expressible
13926: */
13927: if ((completeWild->negNsSet != NULL) &&
13928: (curWild->negNsSet != NULL) &&
13929: (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13930: (completeWild->negNsSet->value != NULL) &&
13931: (curWild->negNsSet->value != NULL)) {
13932:
13933: xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13934: "The intersection of the wilcard is not expressible.\n",
13935: NULL, NULL);
13936: return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13937: }
13938: /*
13939: * 6 If the one is a negation of a namespace name and the other
13940: * is a negation of �absent�, then the one which is the negation
13941: * of a namespace name must be the value.
13942: */
13943: if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13944: (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13945: (completeWild->negNsSet->value == NULL)) {
13946: completeWild->negNsSet->value = curWild->negNsSet->value;
13947: }
13948: return(0);
13949: }
13950:
13951: /**
13952: * xmlSchemaIsWildcardNsConstraintSubset:
13953: * @ctxt: the schema parser context
13954: * @sub: the first wildcard
13955: * @super: the second wildcard
13956: *
13957: * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13958: *
13959: * Returns 0 if the namespace constraint of @sub is an intensional
13960: * subset of @super, 1 otherwise.
13961: */
13962: static int
13963: xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13964: xmlSchemaWildcardPtr super)
13965: {
13966: /*
13967: * 1 super must be any.
13968: */
13969: if (super->any)
13970: return (0);
13971: /*
13972: * 2.1 sub must be a pair of not and a namespace name or �absent�.
13973: * 2.2 super must be a pair of not and the same value.
13974: */
13975: if ((sub->negNsSet != NULL) &&
13976: (super->negNsSet != NULL) &&
1.1.1.2 misho 13977: (sub->negNsSet->value == super->negNsSet->value))
1.1 misho 13978: return (0);
13979: /*
13980: * 3.1 sub must be a set whose members are either namespace names or �absent�.
13981: */
13982: if (sub->nsSet != NULL) {
13983: /*
13984: * 3.2.1 super must be the same set or a superset thereof.
13985: */
13986: if (super->nsSet != NULL) {
13987: xmlSchemaWildcardNsPtr cur, curB;
13988: int found = 0;
13989:
13990: cur = sub->nsSet;
13991: while (cur != NULL) {
13992: found = 0;
13993: curB = super->nsSet;
13994: while (curB != NULL) {
13995: if (cur->value == curB->value) {
13996: found = 1;
13997: break;
13998: }
13999: curB = curB->next;
14000: }
14001: if (!found)
14002: return (1);
14003: cur = cur->next;
14004: }
14005: if (found)
14006: return (0);
14007: } else if (super->negNsSet != NULL) {
14008: xmlSchemaWildcardNsPtr cur;
14009: /*
14010: * 3.2.2 super must be a pair of not and a namespace name or
14011: * �absent� and that value must not be in sub's set.
14012: */
14013: cur = sub->nsSet;
14014: while (cur != NULL) {
14015: if (cur->value == super->negNsSet->value)
14016: return (1);
14017: cur = cur->next;
14018: }
14019: return (0);
14020: }
14021: }
14022: return (1);
14023: }
14024:
14025: static int
14026: xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14027: int *fixed,
14028: const xmlChar **value,
14029: xmlSchemaValPtr *val)
14030: {
14031: *fixed = 0;
14032: *value = NULL;
14033: if (val != 0)
14034: *val = NULL;
14035:
14036: if (attruse->defValue != NULL) {
14037: *value = attruse->defValue;
14038: if (val != NULL)
14039: *val = attruse->defVal;
14040: if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14041: *fixed = 1;
14042: return(1);
14043: } else if ((attruse->attrDecl != NULL) &&
14044: (attruse->attrDecl->defValue != NULL)) {
14045: *value = attruse->attrDecl->defValue;
14046: if (val != NULL)
14047: *val = attruse->attrDecl->defVal;
14048: if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14049: *fixed = 1;
14050: return(1);
14051: }
14052: return(0);
14053: }
14054: /**
14055: * xmlSchemaCheckCVCWildcardNamespace:
14056: * @wild: the wildcard
14057: * @ns: the namespace
14058: *
14059: * Validation Rule: Wildcard allows Namespace Name
14060: * (cvc-wildcard-namespace)
14061: *
14062: * Returns 0 if the given namespace matches the wildcard,
14063: * 1 otherwise and -1 on API errors.
14064: */
14065: static int
14066: xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14067: const xmlChar* ns)
14068: {
14069: if (wild == NULL)
14070: return(-1);
14071:
14072: if (wild->any)
14073: return(0);
14074: else if (wild->nsSet != NULL) {
14075: xmlSchemaWildcardNsPtr cur;
14076:
14077: cur = wild->nsSet;
14078: while (cur != NULL) {
14079: if (xmlStrEqual(cur->value, ns))
14080: return(0);
14081: cur = cur->next;
14082: }
14083: } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14084: (!xmlStrEqual(wild->negNsSet->value, ns)))
14085: return(0);
14086:
14087: return(1);
14088: }
14089:
14090: #define XML_SCHEMA_ACTION_DERIVE 0
14091: #define XML_SCHEMA_ACTION_REDEFINE 1
14092:
14093: #define WXS_ACTION_STR(a) \
14094: ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14095:
14096: /*
14097: * Schema Component Constraint:
14098: * Derivation Valid (Restriction, Complex)
14099: * derivation-ok-restriction (2) - (4)
14100: *
14101: * ATTENTION:
14102: * In XML Schema 1.1 this will be:
14103: * Validation Rule:
14104: * Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14105: *
14106: */
14107: static int
14108: xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14109: int action,
14110: xmlSchemaBasicItemPtr item,
14111: xmlSchemaBasicItemPtr baseItem,
14112: xmlSchemaItemListPtr uses,
14113: xmlSchemaItemListPtr baseUses,
14114: xmlSchemaWildcardPtr wild,
14115: xmlSchemaWildcardPtr baseWild)
14116: {
14117: xmlSchemaAttributeUsePtr cur = NULL, bcur;
14118: int i, j, found; /* err = 0; */
14119: const xmlChar *bEffValue;
14120: int effFixed;
14121:
14122: if (uses != NULL) {
14123: for (i = 0; i < uses->nbItems; i++) {
14124: cur = uses->items[i];
14125: found = 0;
14126: if (baseUses == NULL)
14127: goto not_found;
14128: for (j = 0; j < baseUses->nbItems; j++) {
14129: bcur = baseUses->items[j];
14130: if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14131: WXS_ATTRUSE_DECL_NAME(bcur)) &&
14132: (WXS_ATTRUSE_DECL_TNS(cur) ==
14133: WXS_ATTRUSE_DECL_TNS(bcur)))
14134: {
14135: /*
14136: * (2.1) "If there is an attribute use in the {attribute
14137: * uses} of the {base type definition} (call this B) whose
14138: * {attribute declaration} has the same {name} and {target
14139: * namespace}, then all of the following must be true:"
14140: */
14141: found = 1;
14142:
14143: if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14144: (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14145: {
14146: xmlChar *str = NULL;
14147: /*
14148: * (2.1.1) "one of the following must be true:"
14149: * (2.1.1.1) "B's {required} is false."
14150: * (2.1.1.2) "R's {required} is true."
14151: */
14152: xmlSchemaPAttrUseErr4(pctxt,
14153: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14154: WXS_ITEM_NODE(item), item, cur,
14155: "The 'optional' attribute use is inconsistent "
14156: "with the corresponding 'required' attribute use of "
14157: "the %s %s",
14158: WXS_ACTION_STR(action),
14159: xmlSchemaGetComponentDesignation(&str, baseItem),
14160: NULL, NULL);
14161: FREE_AND_NULL(str);
14162: /* err = pctxt->err; */
14163: } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14164: WXS_ATTRUSE_TYPEDEF(cur),
14165: WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14166: {
14167: xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14168:
14169: /*
14170: * SPEC (2.1.2) "R's {attribute declaration}'s
14171: * {type definition} must be validly derived from
14172: * B's {type definition} given the empty set as
14173: * defined in Type Derivation OK (Simple) (�3.14.6)."
14174: */
14175: xmlSchemaPAttrUseErr4(pctxt,
14176: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14177: WXS_ITEM_NODE(item), item, cur,
14178: "The attribute declaration's %s "
14179: "is not validly derived from "
14180: "the corresponding %s of the "
14181: "attribute declaration in the %s %s",
14182: xmlSchemaGetComponentDesignation(&strA,
14183: WXS_ATTRUSE_TYPEDEF(cur)),
14184: xmlSchemaGetComponentDesignation(&strB,
14185: WXS_ATTRUSE_TYPEDEF(bcur)),
14186: WXS_ACTION_STR(action),
14187: xmlSchemaGetComponentDesignation(&strC, baseItem));
14188: /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14189: FREE_AND_NULL(strA);
14190: FREE_AND_NULL(strB);
14191: FREE_AND_NULL(strC);
14192: /* err = pctxt->err; */
14193: } else {
14194: /*
14195: * 2.1.3 [Definition:] Let the effective value
14196: * constraint of an attribute use be its {value
14197: * constraint}, if present, otherwise its {attribute
14198: * declaration}'s {value constraint} .
14199: */
14200: xmlSchemaGetEffectiveValueConstraint(bcur,
14201: &effFixed, &bEffValue, NULL);
14202: /*
14203: * 2.1.3 ... one of the following must be true
14204: *
14205: * 2.1.3.1 B's �effective value constraint� is
14206: * �absent� or default.
14207: */
14208: if ((bEffValue != NULL) &&
14209: (effFixed == 1)) {
14210: const xmlChar *rEffValue = NULL;
14211:
14212: xmlSchemaGetEffectiveValueConstraint(bcur,
14213: &effFixed, &rEffValue, NULL);
14214: /*
14215: * 2.1.3.2 R's �effective value constraint� is
14216: * fixed with the same string as B's.
14217: * MAYBE TODO: Compare the computed values.
14218: * Hmm, it says "same string" so
14219: * string-equality might really be sufficient.
14220: */
14221: if ((effFixed == 0) ||
14222: (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14223: {
14224: xmlChar *str = NULL;
14225:
14226: xmlSchemaPAttrUseErr4(pctxt,
14227: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14228: WXS_ITEM_NODE(item), item, cur,
14229: "The effective value constraint of the "
14230: "attribute use is inconsistent with "
14231: "its correspondent in the %s %s",
14232: WXS_ACTION_STR(action),
14233: xmlSchemaGetComponentDesignation(&str,
14234: baseItem),
14235: NULL, NULL);
14236: FREE_AND_NULL(str);
14237: /* err = pctxt->err; */
14238: }
14239: }
14240: }
14241: break;
14242: }
14243: }
14244: not_found:
14245: if (!found) {
14246: /*
14247: * (2.2) "otherwise the {base type definition} must have an
14248: * {attribute wildcard} and the {target namespace} of the
14249: * R's {attribute declaration} must be �valid� with respect
14250: * to that wildcard, as defined in Wildcard allows Namespace
14251: * Name (�3.10.4)."
14252: */
14253: if ((baseWild == NULL) ||
14254: (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14255: (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14256: {
14257: xmlChar *str = NULL;
14258:
14259: xmlSchemaPAttrUseErr4(pctxt,
14260: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14261: WXS_ITEM_NODE(item), item, cur,
14262: "Neither a matching attribute use, "
14263: "nor a matching wildcard exists in the %s %s",
14264: WXS_ACTION_STR(action),
14265: xmlSchemaGetComponentDesignation(&str, baseItem),
14266: NULL, NULL);
14267: FREE_AND_NULL(str);
14268: /* err = pctxt->err; */
14269: }
14270: }
14271: }
14272: }
14273: /*
14274: * SPEC derivation-ok-restriction (3):
14275: * (3) "For each attribute use in the {attribute uses} of the {base type
14276: * definition} whose {required} is true, there must be an attribute
14277: * use with an {attribute declaration} with the same {name} and
14278: * {target namespace} as its {attribute declaration} in the {attribute
14279: * uses} of the complex type definition itself whose {required} is true.
14280: */
14281: if (baseUses != NULL) {
14282: for (j = 0; j < baseUses->nbItems; j++) {
14283: bcur = baseUses->items[j];
14284: if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14285: continue;
14286: found = 0;
14287: if (uses != NULL) {
14288: for (i = 0; i < uses->nbItems; i++) {
14289: cur = uses->items[i];
14290: if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14291: WXS_ATTRUSE_DECL_NAME(bcur)) &&
14292: (WXS_ATTRUSE_DECL_TNS(cur) ==
14293: WXS_ATTRUSE_DECL_TNS(bcur))) {
14294: found = 1;
14295: break;
14296: }
14297: }
14298: }
14299: if (!found) {
14300: xmlChar *strA = NULL, *strB = NULL;
14301:
14302: xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14303: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14304: NULL, item,
14305: "A matching attribute use for the "
14306: "'required' %s of the %s %s is missing",
14307: xmlSchemaGetComponentDesignation(&strA, bcur),
14308: WXS_ACTION_STR(action),
14309: xmlSchemaGetComponentDesignation(&strB, baseItem),
14310: NULL);
14311: FREE_AND_NULL(strA);
14312: FREE_AND_NULL(strB);
14313: }
14314: }
14315: }
14316: /*
14317: * derivation-ok-restriction (4)
14318: */
14319: if (wild != NULL) {
14320: /*
14321: * (4) "If there is an {attribute wildcard}, all of the
14322: * following must be true:"
14323: */
14324: if (baseWild == NULL) {
14325: xmlChar *str = NULL;
14326:
14327: /*
14328: * (4.1) "The {base type definition} must also have one."
14329: */
14330: xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14331: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14332: NULL, item,
14333: "The %s has an attribute wildcard, "
14334: "but the %s %s '%s' does not have one",
14335: WXS_ITEM_TYPE_NAME(item),
14336: WXS_ACTION_STR(action),
14337: WXS_ITEM_TYPE_NAME(baseItem),
14338: xmlSchemaGetComponentQName(&str, baseItem));
14339: FREE_AND_NULL(str);
14340: return(pctxt->err);
14341: } else if ((baseWild->any == 0) &&
14342: xmlSchemaCheckCOSNSSubset(wild, baseWild))
14343: {
14344: xmlChar *str = NULL;
14345: /*
14346: * (4.2) "The complex type definition's {attribute wildcard}'s
14347: * {namespace constraint} must be a subset of the {base type
14348: * definition}'s {attribute wildcard}'s {namespace constraint},
14349: * as defined by Wildcard Subset (�3.10.6)."
14350: */
14351: xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14352: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14353: NULL, item,
14354: "The attribute wildcard is not a valid "
14355: "subset of the wildcard in the %s %s '%s'",
14356: WXS_ACTION_STR(action),
14357: WXS_ITEM_TYPE_NAME(baseItem),
14358: xmlSchemaGetComponentQName(&str, baseItem),
14359: NULL);
14360: FREE_AND_NULL(str);
14361: return(pctxt->err);
14362: }
14363: /* 4.3 Unless the {base type definition} is the �ur-type
14364: * definition�, the complex type definition's {attribute
14365: * wildcard}'s {process contents} must be identical to or
14366: * stronger than the {base type definition}'s {attribute
14367: * wildcard}'s {process contents}, where strict is stronger
14368: * than lax is stronger than skip.
14369: */
14370: if ((! WXS_IS_ANYTYPE(baseItem)) &&
14371: (wild->processContents < baseWild->processContents)) {
14372: xmlChar *str = NULL;
14373: xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14374: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14375: NULL, baseItem,
14376: "The {process contents} of the attribute wildcard is "
14377: "weaker than the one in the %s %s '%s'",
14378: WXS_ACTION_STR(action),
14379: WXS_ITEM_TYPE_NAME(baseItem),
14380: xmlSchemaGetComponentQName(&str, baseItem),
14381: NULL);
14382: FREE_AND_NULL(str)
14383: return(pctxt->err);
14384: }
14385: }
14386: return(0);
14387: }
14388:
14389:
14390: static int
14391: xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14392: xmlSchemaBasicItemPtr item,
14393: xmlSchemaWildcardPtr *completeWild,
14394: xmlSchemaItemListPtr list,
14395: xmlSchemaItemListPtr prohibs);
14396: /**
14397: * xmlSchemaFixupTypeAttributeUses:
14398: * @ctxt: the schema parser context
14399: * @type: the complex type definition
14400: *
14401: *
14402: * Builds the wildcard and the attribute uses on the given complex type.
14403: * Returns -1 if an internal error occurs, 0 otherwise.
14404: *
14405: * ATTENTION TODO: Experimantally this uses pointer comparisons for
14406: * strings, so recheck this if we start to hardcode some schemata, since
14407: * they might not be in the same dict.
14408: * NOTE: It is allowed to "extend" the xs:anyType type.
14409: */
14410: static int
14411: xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14412: xmlSchemaTypePtr type)
14413: {
14414: xmlSchemaTypePtr baseType = NULL;
14415: xmlSchemaAttributeUsePtr use;
14416: xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14417:
14418: if (type->baseType == NULL) {
14419: PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14420: "no base type");
14421: return (-1);
14422: }
14423: baseType = type->baseType;
14424: if (WXS_IS_TYPE_NOT_FIXED(baseType))
14425: if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14426: return(-1);
14427:
14428: uses = type->attrUses;
14429: baseUses = baseType->attrUses;
14430: /*
14431: * Expand attribute group references. And build the 'complete'
14432: * wildcard, i.e. intersect multiple wildcards.
14433: * Move attribute prohibitions into a separate list.
14434: */
14435: if (uses != NULL) {
14436: if (WXS_IS_RESTRICTION(type)) {
14437: /*
14438: * This one will transfer all attr. prohibitions
14439: * into pctxt->attrProhibs.
14440: */
14441: if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14442: WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14443: pctxt->attrProhibs) == -1)
14444: {
14445: PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14446: "failed to expand attributes");
14447: }
14448: if (pctxt->attrProhibs->nbItems != 0)
14449: prohibs = pctxt->attrProhibs;
14450: } else {
14451: if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14452: WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14453: NULL) == -1)
14454: {
14455: PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14456: "failed to expand attributes");
14457: }
14458: }
14459: }
14460: /*
14461: * Inherit the attribute uses of the base type.
14462: */
14463: if (baseUses != NULL) {
14464: int i, j;
14465: xmlSchemaAttributeUseProhibPtr pro;
14466:
14467: if (WXS_IS_RESTRICTION(type)) {
14468: int usesCount;
14469: xmlSchemaAttributeUsePtr tmp;
14470:
14471: if (uses != NULL)
14472: usesCount = uses->nbItems;
14473: else
14474: usesCount = 0;
14475:
14476: /* Restriction. */
14477: for (i = 0; i < baseUses->nbItems; i++) {
14478: use = baseUses->items[i];
14479: if (prohibs) {
14480: /*
14481: * Filter out prohibited uses.
14482: */
14483: for (j = 0; j < prohibs->nbItems; j++) {
14484: pro = prohibs->items[j];
14485: if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14486: (WXS_ATTRUSE_DECL_TNS(use) ==
14487: pro->targetNamespace))
14488: {
14489: goto inherit_next;
14490: }
14491: }
14492: }
14493: if (usesCount) {
14494: /*
14495: * Filter out existing uses.
14496: */
14497: for (j = 0; j < usesCount; j++) {
14498: tmp = uses->items[j];
14499: if ((WXS_ATTRUSE_DECL_NAME(use) ==
14500: WXS_ATTRUSE_DECL_NAME(tmp)) &&
14501: (WXS_ATTRUSE_DECL_TNS(use) ==
14502: WXS_ATTRUSE_DECL_TNS(tmp)))
14503: {
14504: goto inherit_next;
14505: }
14506: }
14507: }
14508: if (uses == NULL) {
14509: type->attrUses = xmlSchemaItemListCreate();
14510: if (type->attrUses == NULL)
14511: goto exit_failure;
14512: uses = type->attrUses;
14513: }
14514: xmlSchemaItemListAddSize(uses, 2, use);
14515: inherit_next: {}
14516: }
14517: } else {
14518: /* Extension. */
14519: for (i = 0; i < baseUses->nbItems; i++) {
14520: use = baseUses->items[i];
14521: if (uses == NULL) {
14522: type->attrUses = xmlSchemaItemListCreate();
14523: if (type->attrUses == NULL)
14524: goto exit_failure;
14525: uses = type->attrUses;
14526: }
14527: xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14528: }
14529: }
14530: }
14531: /*
14532: * Shrink attr. uses.
14533: */
14534: if (uses) {
14535: if (uses->nbItems == 0) {
14536: xmlSchemaItemListFree(uses);
14537: type->attrUses = NULL;
14538: }
14539: /*
14540: * TODO: We could shrink the size of the array
14541: * to fit the actual number of items.
14542: */
14543: }
14544: /*
14545: * Compute the complete wildcard.
14546: */
14547: if (WXS_IS_EXTENSION(type)) {
14548: if (baseType->attributeWildcard != NULL) {
14549: /*
14550: * (3.2.2.1) "If the �base wildcard� is non-�absent�, then
14551: * the appropriate case among the following:"
14552: */
14553: if (type->attributeWildcard != NULL) {
14554: /*
14555: * Union the complete wildcard with the base wildcard.
14556: * SPEC {attribute wildcard}
14557: * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14558: * and {annotation} are those of the �complete wildcard�,
14559: * and whose {namespace constraint} is the intensional union
14560: * of the {namespace constraint} of the �complete wildcard�
14561: * and of the �base wildcard�, as defined in Attribute
14562: * Wildcard Union (�3.10.6)."
14563: */
14564: if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14565: baseType->attributeWildcard) == -1)
14566: goto exit_failure;
14567: } else {
14568: /*
14569: * (3.2.2.1.1) "If the �complete wildcard� is �absent�,
14570: * then the �base wildcard�."
14571: */
14572: type->attributeWildcard = baseType->attributeWildcard;
14573: }
14574: } else {
14575: /*
14576: * (3.2.2.2) "otherwise (the �base wildcard� is �absent�) the
14577: * �complete wildcard"
14578: * NOOP
14579: */
14580: }
14581: } else {
14582: /*
14583: * SPEC {attribute wildcard}
14584: * (3.1) "If the <restriction> alternative is chosen, then the
14585: * �complete wildcard�;"
14586: * NOOP
14587: */
14588: }
14589:
14590: return (0);
14591:
14592: exit_failure:
14593: return(-1);
14594: }
14595:
14596: /**
14597: * xmlSchemaTypeFinalContains:
14598: * @schema: the schema
14599: * @type: the type definition
14600: * @final: the final
14601: *
14602: * Evaluates if a type definition contains the given "final".
14603: * This does take "finalDefault" into account as well.
14604: *
14605: * Returns 1 if the type does containt the given "final",
14606: * 0 otherwise.
14607: */
14608: static int
14609: xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14610: {
14611: if (type == NULL)
14612: return (0);
14613: if (type->flags & final)
14614: return (1);
14615: else
14616: return (0);
14617: }
14618:
14619: /**
14620: * xmlSchemaGetUnionSimpleTypeMemberTypes:
14621: * @type: the Union Simple Type
14622: *
14623: * Returns a list of member types of @type if existing,
14624: * returns NULL otherwise.
14625: */
14626: static xmlSchemaTypeLinkPtr
14627: xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14628: {
14629: while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14630: if (type->memberTypes != NULL)
14631: return (type->memberTypes);
14632: else
14633: type = type->baseType;
14634: }
14635: return (NULL);
14636: }
14637:
14638: /**
14639: * xmlSchemaGetParticleTotalRangeMin:
14640: * @particle: the particle
14641: *
14642: * Schema Component Constraint: Effective Total Range
14643: * (all and sequence) + (choice)
14644: *
14645: * Returns the minimun Effective Total Range.
14646: */
14647: static int
14648: xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14649: {
14650: if ((particle->children == NULL) ||
14651: (particle->minOccurs == 0))
14652: return (0);
14653: if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14654: int min = -1, cur;
14655: xmlSchemaParticlePtr part =
14656: (xmlSchemaParticlePtr) particle->children->children;
14657:
14658: if (part == NULL)
14659: return (0);
14660: while (part != NULL) {
14661: if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14662: (part->children->type == XML_SCHEMA_TYPE_ANY))
14663: cur = part->minOccurs;
14664: else
14665: cur = xmlSchemaGetParticleTotalRangeMin(part);
14666: if (cur == 0)
14667: return (0);
14668: if ((min > cur) || (min == -1))
14669: min = cur;
14670: part = (xmlSchemaParticlePtr) part->next;
14671: }
14672: return (particle->minOccurs * min);
14673: } else {
14674: /* <all> and <sequence> */
14675: int sum = 0;
14676: xmlSchemaParticlePtr part =
14677: (xmlSchemaParticlePtr) particle->children->children;
14678:
14679: if (part == NULL)
14680: return (0);
14681: do {
14682: if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14683: (part->children->type == XML_SCHEMA_TYPE_ANY))
14684: sum += part->minOccurs;
14685: else
14686: sum += xmlSchemaGetParticleTotalRangeMin(part);
14687: part = (xmlSchemaParticlePtr) part->next;
14688: } while (part != NULL);
14689: return (particle->minOccurs * sum);
14690: }
14691: }
14692:
14693: #if 0
14694: /**
14695: * xmlSchemaGetParticleTotalRangeMax:
14696: * @particle: the particle
14697: *
14698: * Schema Component Constraint: Effective Total Range
14699: * (all and sequence) + (choice)
14700: *
14701: * Returns the maximum Effective Total Range.
14702: */
14703: static int
14704: xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14705: {
14706: if ((particle->children == NULL) ||
14707: (particle->children->children == NULL))
14708: return (0);
14709: if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14710: int max = -1, cur;
14711: xmlSchemaParticlePtr part =
14712: (xmlSchemaParticlePtr) particle->children->children;
14713:
14714: for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14715: if (part->children == NULL)
14716: continue;
14717: if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14718: (part->children->type == XML_SCHEMA_TYPE_ANY))
14719: cur = part->maxOccurs;
14720: else
14721: cur = xmlSchemaGetParticleTotalRangeMax(part);
14722: if (cur == UNBOUNDED)
14723: return (UNBOUNDED);
14724: if ((max < cur) || (max == -1))
14725: max = cur;
14726: }
14727: /* TODO: Handle overflows? */
14728: return (particle->maxOccurs * max);
14729: } else {
14730: /* <all> and <sequence> */
14731: int sum = 0, cur;
14732: xmlSchemaParticlePtr part =
14733: (xmlSchemaParticlePtr) particle->children->children;
14734:
14735: for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14736: if (part->children == NULL)
14737: continue;
14738: if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14739: (part->children->type == XML_SCHEMA_TYPE_ANY))
14740: cur = part->maxOccurs;
14741: else
14742: cur = xmlSchemaGetParticleTotalRangeMax(part);
14743: if (cur == UNBOUNDED)
14744: return (UNBOUNDED);
14745: if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14746: return (UNBOUNDED);
14747: sum += cur;
14748: }
14749: /* TODO: Handle overflows? */
14750: return (particle->maxOccurs * sum);
14751: }
14752: }
14753: #endif
14754:
14755: /**
14756: * xmlSchemaIsParticleEmptiable:
14757: * @particle: the particle
14758: *
14759: * Schema Component Constraint: Particle Emptiable
14760: * Checks whether the given particle is emptiable.
14761: *
14762: * Returns 1 if emptiable, 0 otherwise.
14763: */
14764: static int
14765: xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14766: {
14767: /*
14768: * SPEC (1) "Its {min occurs} is 0."
14769: */
14770: if ((particle == NULL) || (particle->minOccurs == 0) ||
14771: (particle->children == NULL))
14772: return (1);
14773: /*
14774: * SPEC (2) "Its {term} is a group and the minimum part of the
14775: * effective total range of that group, [...] is 0."
14776: */
14777: if (WXS_IS_MODEL_GROUP(particle->children)) {
14778: if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14779: return (1);
14780: }
14781: return (0);
14782: }
14783:
14784: /**
14785: * xmlSchemaCheckCOSSTDerivedOK:
14786: * @actxt: a context
14787: * @type: the derived simple type definition
14788: * @baseType: the base type definition
14789: * @subset: the subset of ('restriction', ect.)
14790: *
14791: * Schema Component Constraint:
14792: * Type Derivation OK (Simple) (cos-st-derived-OK)
14793: *
14794: * Checks wheter @type can be validly
14795: * derived from @baseType.
14796: *
14797: * Returns 0 on success, an positive error code otherwise.
14798: */
14799: static int
14800: xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14801: xmlSchemaTypePtr type,
14802: xmlSchemaTypePtr baseType,
14803: int subset)
14804: {
14805: /*
14806: * 1 They are the same type definition.
14807: * TODO: The identy check might have to be more complex than this.
14808: */
14809: if (type == baseType)
14810: return (0);
14811: /*
14812: * 2.1 restriction is not in the subset, or in the {final}
14813: * of its own {base type definition};
14814: *
14815: * NOTE that this will be used also via "xsi:type".
14816: *
14817: * TODO: Revise this, it looks strange. How can the "type"
14818: * not be fixed or *in* fixing?
14819: */
14820: if (WXS_IS_TYPE_NOT_FIXED(type))
14821: if (xmlSchemaTypeFixup(type, actxt) == -1)
14822: return(-1);
14823: if (WXS_IS_TYPE_NOT_FIXED(baseType))
14824: if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14825: return(-1);
14826: if ((subset & SUBSET_RESTRICTION) ||
14827: (xmlSchemaTypeFinalContains(type->baseType,
14828: XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14829: return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14830: }
14831: /* 2.2 */
14832: if (type->baseType == baseType) {
14833: /*
14834: * 2.2.1 D's �base type definition� is B.
14835: */
14836: return (0);
14837: }
14838: /*
14839: * 2.2.2 D's �base type definition� is not the �ur-type definition�
14840: * and is validly derived from B given the subset, as defined by this
14841: * constraint.
14842: */
14843: if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14844: (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14845: baseType, subset) == 0)) {
14846: return (0);
14847: }
14848: /*
14849: * 2.2.3 D's {variety} is list or union and B is the �simple ur-type
14850: * definition�.
14851: */
14852: if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14853: (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14854: return (0);
14855: }
14856: /*
14857: * 2.2.4 B's {variety} is union and D is validly derived from a type
14858: * definition in B's {member type definitions} given the subset, as
14859: * defined by this constraint.
14860: *
14861: * NOTE: This seems not to involve built-in types, since there is no
14862: * built-in Union Simple Type.
14863: */
14864: if (WXS_IS_UNION(baseType)) {
14865: xmlSchemaTypeLinkPtr cur;
14866:
14867: cur = baseType->memberTypes;
14868: while (cur != NULL) {
14869: if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14870: if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14871: return(-1);
14872: if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14873: type, cur->type, subset) == 0)
14874: {
14875: /*
14876: * It just has to be validly derived from at least one
14877: * member-type.
14878: */
14879: return (0);
14880: }
14881: cur = cur->next;
14882: }
14883: }
14884: return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14885: }
14886:
14887: /**
14888: * xmlSchemaCheckTypeDefCircularInternal:
14889: * @pctxt: the schema parser context
14890: * @ctxtType: the type definition
14891: * @ancestor: an ancestor of @ctxtType
14892: *
14893: * Checks st-props-correct (2) + ct-props-correct (3).
14894: * Circular type definitions are not allowed.
14895: *
14896: * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14897: * circular, 0 otherwise.
14898: */
14899: static int
14900: xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14901: xmlSchemaTypePtr ctxtType,
14902: xmlSchemaTypePtr ancestor)
14903: {
14904: int ret;
14905:
14906: if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14907: return (0);
14908:
14909: if (ctxtType == ancestor) {
14910: xmlSchemaPCustomErr(pctxt,
14911: XML_SCHEMAP_ST_PROPS_CORRECT_2,
14912: WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14913: "The definition is circular", NULL);
14914: return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14915: }
14916: if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14917: /*
14918: * Avoid inifinite recursion on circular types not yet checked.
14919: */
14920: return (0);
14921: }
14922: ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14923: ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14924: ancestor->baseType);
14925: ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14926: return (ret);
14927: }
14928:
14929: /**
14930: * xmlSchemaCheckTypeDefCircular:
14931: * @item: the complex/simple type definition
14932: * @ctxt: the parser context
14933: * @name: the name
14934: *
14935: * Checks for circular type definitions.
14936: */
14937: static void
14938: xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14939: xmlSchemaParserCtxtPtr ctxt)
14940: {
14941: if ((item == NULL) ||
14942: (item->type == XML_SCHEMA_TYPE_BASIC) ||
14943: (item->baseType == NULL))
14944: return;
14945: xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14946: item->baseType);
14947: }
14948:
14949: /*
14950: * Simple Type Definition Representation OK (src-simple-type) 4
14951: *
14952: * "4 Circular union type definition is disallowed. That is, if the
14953: * <union> alternative is chosen, there must not be any entries in the
14954: * memberTypes [attribute] at any depth which resolve to the component
14955: * corresponding to the <simpleType>."
14956: *
14957: * Note that this should work on the *representation* of a component,
14958: * thus assumes any union types in the member types not being yet
14959: * substituted. At this stage we need the variety of the types
14960: * to be already computed.
14961: */
14962: static int
14963: xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14964: xmlSchemaTypePtr ctxType,
14965: xmlSchemaTypeLinkPtr members)
14966: {
14967: xmlSchemaTypeLinkPtr member;
14968: xmlSchemaTypePtr memberType;
14969:
14970: member = members;
14971: while (member != NULL) {
14972: memberType = member->type;
14973: while ((memberType != NULL) &&
14974: (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14975: if (memberType == ctxType) {
14976: xmlSchemaPCustomErr(pctxt,
14977: XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14978: WXS_BASIC_CAST ctxType, NULL,
14979: "The union type definition is circular", NULL);
14980: return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14981: }
14982: if ((WXS_IS_UNION(memberType)) &&
14983: ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14984: {
14985: int res;
14986: memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14987: res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14988: ctxType,
14989: xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14990: memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14991: if (res != 0)
14992: return(res);
14993: }
14994: memberType = memberType->baseType;
14995: }
14996: member = member->next;
14997: }
14998: return(0);
14999: }
15000:
15001: static int
15002: xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15003: xmlSchemaTypePtr type)
15004: {
15005: if (! WXS_IS_UNION(type))
15006: return(0);
15007: return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15008: type->memberTypes));
15009: }
15010:
15011: /**
15012: * xmlSchemaResolveTypeReferences:
15013: * @item: the complex/simple type definition
15014: * @ctxt: the parser context
15015: * @name: the name
15016: *
15017: * Resolvese type definition references
15018: */
15019: static void
15020: xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15021: xmlSchemaParserCtxtPtr ctxt)
15022: {
15023: if (typeDef == NULL)
15024: return;
15025:
15026: /*
15027: * Resolve the base type.
15028: */
15029: if (typeDef->baseType == NULL) {
15030: typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15031: typeDef->base, typeDef->baseNs);
15032: if (typeDef->baseType == NULL) {
15033: xmlSchemaPResCompAttrErr(ctxt,
15034: XML_SCHEMAP_SRC_RESOLVE,
15035: WXS_BASIC_CAST typeDef, typeDef->node,
15036: "base", typeDef->base, typeDef->baseNs,
15037: XML_SCHEMA_TYPE_SIMPLE, NULL);
15038: return;
15039: }
15040: }
15041: if (WXS_IS_SIMPLE(typeDef)) {
15042: if (WXS_IS_UNION(typeDef)) {
15043: /*
15044: * Resolve the memberTypes.
15045: */
15046: xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15047: return;
15048: } else if (WXS_IS_LIST(typeDef)) {
15049: /*
15050: * Resolve the itemType.
15051: */
15052: if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15053:
15054: typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15055: typeDef->base, typeDef->baseNs);
15056:
15057: if ((typeDef->subtypes == NULL) ||
15058: (! WXS_IS_SIMPLE(typeDef->subtypes)))
15059: {
15060: typeDef->subtypes = NULL;
15061: xmlSchemaPResCompAttrErr(ctxt,
15062: XML_SCHEMAP_SRC_RESOLVE,
15063: WXS_BASIC_CAST typeDef, typeDef->node,
15064: "itemType", typeDef->base, typeDef->baseNs,
15065: XML_SCHEMA_TYPE_SIMPLE, NULL);
15066: }
15067: }
15068: return;
15069: }
15070: }
15071: /*
15072: * The ball of letters below means, that if we have a particle
15073: * which has a QName-helper component as its {term}, we want
15074: * to resolve it...
15075: */
15076: else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15077: ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15078: XML_SCHEMA_TYPE_PARTICLE) &&
15079: (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15080: ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15081: XML_SCHEMA_EXTRA_QNAMEREF))
15082: {
15083: xmlSchemaQNameRefPtr ref =
15084: WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15085: xmlSchemaModelGroupDefPtr groupDef;
15086:
15087: /*
15088: * URGENT TODO: Test this.
15089: */
15090: WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15091: /*
15092: * Resolve the MG definition reference.
15093: */
15094: groupDef =
15095: WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15096: ref->itemType, ref->name, ref->targetNamespace);
15097: if (groupDef == NULL) {
15098: xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15099: NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15100: "ref", ref->name, ref->targetNamespace, ref->itemType,
15101: NULL);
15102: /* Remove the particle. */
15103: WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15104: } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15105: /* Remove the particle. */
15106: WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15107: else {
15108: /*
15109: * Assign the MG definition's {model group} to the
15110: * particle's {term}.
15111: */
15112: WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15113:
15114: if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15115: /*
15116: * SPEC cos-all-limited (1.2)
15117: * "1.2 the {term} property of a particle with
15118: * {max occurs}=1 which is part of a pair which constitutes
15119: * the {content type} of a complex type definition."
15120: */
15121: if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15122: xmlSchemaCustomErr(ACTXT_CAST ctxt,
15123: /* TODO: error code */
15124: XML_SCHEMAP_COS_ALL_LIMITED,
15125: WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15126: "The particle's {max occurs} must be 1, since the "
15127: "reference resolves to an 'all' model group",
15128: NULL, NULL);
15129: }
15130: }
15131: }
15132: }
15133: }
15134:
15135:
15136:
15137: /**
15138: * xmlSchemaCheckSTPropsCorrect:
15139: * @ctxt: the schema parser context
15140: * @type: the simple type definition
15141: *
15142: * Checks st-props-correct.
15143: *
15144: * Returns 0 if the properties are correct,
15145: * if not, a positive error code and -1 on internal
15146: * errors.
15147: */
15148: static int
15149: xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15150: xmlSchemaTypePtr type)
15151: {
15152: xmlSchemaTypePtr baseType = type->baseType;
15153: xmlChar *str = NULL;
15154:
15155: /* STATE: error funcs converted. */
15156: /*
15157: * Schema Component Constraint: Simple Type Definition Properties Correct
15158: *
15159: * NOTE: This is somehow redundant, since we actually built a simple type
15160: * to have all the needed information; this acts as an self test.
15161: */
15162: /* Base type: If the datatype has been �derived� by �restriction�
15163: * then the Simple Type Definition component from which it is �derived�,
15164: * otherwise the Simple Type Definition for anySimpleType (�4.1.6).
15165: */
15166: if (baseType == NULL) {
15167: /*
15168: * TODO: Think about: "modulo the impact of Missing
15169: * Sub-components (�5.3)."
15170: */
15171: xmlSchemaPCustomErr(ctxt,
15172: XML_SCHEMAP_ST_PROPS_CORRECT_1,
15173: WXS_BASIC_CAST type, NULL,
15174: "No base type existent", NULL);
15175: return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15176:
15177: }
15178: if (! WXS_IS_SIMPLE(baseType)) {
15179: xmlSchemaPCustomErr(ctxt,
15180: XML_SCHEMAP_ST_PROPS_CORRECT_1,
15181: WXS_BASIC_CAST type, NULL,
15182: "The base type '%s' is not a simple type",
15183: xmlSchemaGetComponentQName(&str, baseType));
15184: FREE_AND_NULL(str)
15185: return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15186: }
1.1.1.2 misho 15187: if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15188: (WXS_IS_RESTRICTION(type) == 0) &&
15189: ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15190: (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
1.1 misho 15191: xmlSchemaPCustomErr(ctxt,
15192: XML_SCHEMAP_ST_PROPS_CORRECT_1,
15193: WXS_BASIC_CAST type, NULL,
15194: "A type, derived by list or union, must have "
15195: "the simple ur-type definition as base type, not '%s'",
15196: xmlSchemaGetComponentQName(&str, baseType));
15197: FREE_AND_NULL(str)
15198: return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15199: }
15200: /*
15201: * Variety: One of {atomic, list, union}.
15202: */
15203: if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15204: (! WXS_IS_LIST(type))) {
15205: xmlSchemaPCustomErr(ctxt,
15206: XML_SCHEMAP_ST_PROPS_CORRECT_1,
15207: WXS_BASIC_CAST type, NULL,
15208: "The variety is absent", NULL);
15209: return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15210: }
15211: /* TODO: Finish this. Hmm, is this finished? */
15212:
15213: /*
15214: * 3 The {final} of the {base type definition} must not contain restriction.
15215: */
15216: if (xmlSchemaTypeFinalContains(baseType,
15217: XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15218: xmlSchemaPCustomErr(ctxt,
15219: XML_SCHEMAP_ST_PROPS_CORRECT_3,
15220: WXS_BASIC_CAST type, NULL,
15221: "The 'final' of its base type '%s' must not contain "
15222: "'restriction'",
15223: xmlSchemaGetComponentQName(&str, baseType));
15224: FREE_AND_NULL(str)
15225: return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15226: }
15227:
15228: /*
15229: * 2 All simple type definitions must be derived ultimately from the �simple
15230: * ur-type definition (so� circular definitions are disallowed). That is, it
15231: * must be possible to reach a built-in primitive datatype or the �simple
15232: * ur-type definition� by repeatedly following the {base type definition}.
15233: *
15234: * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15235: */
15236: return (0);
15237: }
15238:
15239: /**
15240: * xmlSchemaCheckCOSSTRestricts:
15241: * @ctxt: the schema parser context
15242: * @type: the simple type definition
15243: *
15244: * Schema Component Constraint:
15245: * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15246:
15247: * Checks if the given @type (simpleType) is derived validly by restriction.
15248: * STATUS:
15249: *
15250: * Returns -1 on internal errors, 0 if the type is validly derived,
15251: * a positive error code otherwise.
15252: */
15253: static int
15254: xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15255: xmlSchemaTypePtr type)
15256: {
15257: xmlChar *str = NULL;
15258:
15259: if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15260: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15261: "given type is not a user-derived simpleType");
15262: return (-1);
15263: }
15264:
15265: if (WXS_IS_ATOMIC(type)) {
15266: xmlSchemaTypePtr primitive;
15267: /*
15268: * 1.1 The {base type definition} must be an atomic simple
15269: * type definition or a built-in primitive datatype.
15270: */
15271: if (! WXS_IS_ATOMIC(type->baseType)) {
15272: xmlSchemaPCustomErr(pctxt,
15273: XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15274: WXS_BASIC_CAST type, NULL,
15275: "The base type '%s' is not an atomic simple type",
15276: xmlSchemaGetComponentQName(&str, type->baseType));
15277: FREE_AND_NULL(str)
15278: return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15279: }
15280: /* 1.2 The {final} of the {base type definition} must not contain
15281: * restriction.
15282: */
15283: /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15284: if (xmlSchemaTypeFinalContains(type->baseType,
15285: XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15286: xmlSchemaPCustomErr(pctxt,
15287: XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15288: WXS_BASIC_CAST type, NULL,
15289: "The final of its base type '%s' must not contain 'restriction'",
15290: xmlSchemaGetComponentQName(&str, type->baseType));
15291: FREE_AND_NULL(str)
15292: return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15293: }
15294:
15295: /*
15296: * 1.3.1 DF must be an allowed constraining facet for the {primitive
15297: * type definition}, as specified in the appropriate subsection of 3.2
15298: * Primitive datatypes.
15299: */
15300: if (type->facets != NULL) {
15301: xmlSchemaFacetPtr facet;
15302: int ok = 1;
15303:
15304: primitive = xmlSchemaGetPrimitiveType(type);
15305: if (primitive == NULL) {
15306: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15307: "failed to get primitive type");
15308: return (-1);
15309: }
15310: facet = type->facets;
15311: do {
15312: if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15313: ok = 0;
15314: xmlSchemaPIllegalFacetAtomicErr(pctxt,
15315: XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15316: type, primitive, facet);
15317: }
15318: facet = facet->next;
15319: } while (facet != NULL);
15320: if (ok == 0)
15321: return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15322: }
15323: /*
15324: * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15325: * of the {base type definition} (call this BF),then the DF's {value}
15326: * must be a valid restriction of BF's {value} as defined in
15327: * [XML Schemas: Datatypes]."
15328: *
15329: * NOTE (1.3.2) Facet derivation constraints are currently handled in
15330: * xmlSchemaDeriveAndValidateFacets()
15331: */
15332: } else if (WXS_IS_LIST(type)) {
15333: xmlSchemaTypePtr itemType = NULL;
15334:
15335: itemType = type->subtypes;
15336: if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15337: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15338: "failed to evaluate the item type");
15339: return (-1);
15340: }
15341: if (WXS_IS_TYPE_NOT_FIXED(itemType))
15342: xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15343: /*
15344: * 2.1 The {item type definition} must have a {variety} of atomic or
15345: * union (in which case all the {member type definitions}
15346: * must be atomic).
15347: */
15348: if ((! WXS_IS_ATOMIC(itemType)) &&
15349: (! WXS_IS_UNION(itemType))) {
15350: xmlSchemaPCustomErr(pctxt,
15351: XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15352: WXS_BASIC_CAST type, NULL,
15353: "The item type '%s' does not have a variety of atomic or union",
15354: xmlSchemaGetComponentQName(&str, itemType));
15355: FREE_AND_NULL(str)
15356: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15357: } else if (WXS_IS_UNION(itemType)) {
15358: xmlSchemaTypeLinkPtr member;
15359:
15360: member = itemType->memberTypes;
15361: while (member != NULL) {
15362: if (! WXS_IS_ATOMIC(member->type)) {
15363: xmlSchemaPCustomErr(pctxt,
15364: XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15365: WXS_BASIC_CAST type, NULL,
15366: "The item type is a union type, but the "
15367: "member type '%s' of this item type is not atomic",
15368: xmlSchemaGetComponentQName(&str, member->type));
15369: FREE_AND_NULL(str)
15370: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15371: }
15372: member = member->next;
15373: }
15374: }
15375:
15376: if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15377: xmlSchemaFacetPtr facet;
15378: /*
15379: * This is the case if we have: <simpleType><list ..
15380: */
15381: /*
15382: * 2.3.1
15383: * 2.3.1.1 The {final} of the {item type definition} must not
15384: * contain list.
15385: */
15386: if (xmlSchemaTypeFinalContains(itemType,
15387: XML_SCHEMAS_TYPE_FINAL_LIST)) {
15388: xmlSchemaPCustomErr(pctxt,
15389: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15390: WXS_BASIC_CAST type, NULL,
15391: "The final of its item type '%s' must not contain 'list'",
15392: xmlSchemaGetComponentQName(&str, itemType));
15393: FREE_AND_NULL(str)
15394: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15395: }
15396: /*
15397: * 2.3.1.2 The {facets} must only contain the whiteSpace
15398: * facet component.
15399: * OPTIMIZE TODO: the S4S already disallows any facet
15400: * to be specified.
15401: */
15402: if (type->facets != NULL) {
15403: facet = type->facets;
15404: do {
15405: if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15406: xmlSchemaPIllegalFacetListUnionErr(pctxt,
15407: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15408: type, facet);
15409: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15410: }
15411: facet = facet->next;
15412: } while (facet != NULL);
15413: }
15414: /*
15415: * MAYBE TODO: (Hmm, not really) Datatypes states:
15416: * A �list� datatype can be �derived� from an �atomic� datatype
15417: * whose �lexical space� allows space (such as string or anyURI)or
15418: * a �union� datatype any of whose {member type definitions}'s
15419: * �lexical space� allows space.
15420: */
15421: } else {
15422: /*
15423: * This is the case if we have: <simpleType><restriction ...
15424: * I.e. the variety of "list" is inherited.
15425: */
15426: /*
15427: * 2.3.2
15428: * 2.3.2.1 The {base type definition} must have a {variety} of list.
15429: */
15430: if (! WXS_IS_LIST(type->baseType)) {
15431: xmlSchemaPCustomErr(pctxt,
15432: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15433: WXS_BASIC_CAST type, NULL,
15434: "The base type '%s' must be a list type",
15435: xmlSchemaGetComponentQName(&str, type->baseType));
15436: FREE_AND_NULL(str)
15437: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15438: }
15439: /*
15440: * 2.3.2.2 The {final} of the {base type definition} must not
15441: * contain restriction.
15442: */
15443: if (xmlSchemaTypeFinalContains(type->baseType,
15444: XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15445: xmlSchemaPCustomErr(pctxt,
15446: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15447: WXS_BASIC_CAST type, NULL,
15448: "The 'final' of the base type '%s' must not contain 'restriction'",
15449: xmlSchemaGetComponentQName(&str, type->baseType));
15450: FREE_AND_NULL(str)
15451: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15452: }
15453: /*
15454: * 2.3.2.3 The {item type definition} must be validly derived
15455: * from the {base type definition}'s {item type definition} given
15456: * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15457: */
15458: {
15459: xmlSchemaTypePtr baseItemType;
15460:
15461: baseItemType = type->baseType->subtypes;
15462: if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15463: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15464: "failed to eval the item type of a base type");
15465: return (-1);
15466: }
15467: if ((itemType != baseItemType) &&
15468: (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15469: baseItemType, 0) != 0)) {
15470: xmlChar *strBIT = NULL, *strBT = NULL;
15471: xmlSchemaPCustomErrExt(pctxt,
15472: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15473: WXS_BASIC_CAST type, NULL,
15474: "The item type '%s' is not validly derived from "
15475: "the item type '%s' of the base type '%s'",
15476: xmlSchemaGetComponentQName(&str, itemType),
15477: xmlSchemaGetComponentQName(&strBIT, baseItemType),
15478: xmlSchemaGetComponentQName(&strBT, type->baseType));
15479:
15480: FREE_AND_NULL(str)
15481: FREE_AND_NULL(strBIT)
15482: FREE_AND_NULL(strBT)
15483: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15484: }
15485: }
15486:
15487: if (type->facets != NULL) {
15488: xmlSchemaFacetPtr facet;
15489: int ok = 1;
15490: /*
15491: * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15492: * and enumeration facet components are allowed among the {facets}.
15493: */
15494: facet = type->facets;
15495: do {
15496: switch (facet->type) {
15497: case XML_SCHEMA_FACET_LENGTH:
15498: case XML_SCHEMA_FACET_MINLENGTH:
15499: case XML_SCHEMA_FACET_MAXLENGTH:
15500: case XML_SCHEMA_FACET_WHITESPACE:
15501: /*
15502: * TODO: 2.5.1.2 List datatypes
15503: * The value of �whiteSpace� is fixed to the value collapse.
15504: */
15505: case XML_SCHEMA_FACET_PATTERN:
15506: case XML_SCHEMA_FACET_ENUMERATION:
15507: break;
15508: default: {
15509: xmlSchemaPIllegalFacetListUnionErr(pctxt,
15510: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15511: type, facet);
15512: /*
15513: * We could return, but it's nicer to report all
15514: * invalid facets.
15515: */
15516: ok = 0;
15517: }
15518: }
15519: facet = facet->next;
15520: } while (facet != NULL);
15521: if (ok == 0)
15522: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15523: /*
15524: * SPEC (2.3.2.5) (same as 1.3.2)
15525: *
15526: * NOTE (2.3.2.5) This is currently done in
15527: * xmlSchemaDeriveAndValidateFacets()
15528: */
15529: }
15530: }
15531: } else if (WXS_IS_UNION(type)) {
15532: /*
15533: * 3.1 The {member type definitions} must all have {variety} of
15534: * atomic or list.
15535: */
15536: xmlSchemaTypeLinkPtr member;
15537:
15538: member = type->memberTypes;
15539: while (member != NULL) {
15540: if (WXS_IS_TYPE_NOT_FIXED(member->type))
15541: xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15542:
15543: if ((! WXS_IS_ATOMIC(member->type)) &&
15544: (! WXS_IS_LIST(member->type))) {
15545: xmlSchemaPCustomErr(pctxt,
15546: XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15547: WXS_BASIC_CAST type, NULL,
15548: "The member type '%s' is neither an atomic, nor a list type",
15549: xmlSchemaGetComponentQName(&str, member->type));
15550: FREE_AND_NULL(str)
15551: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15552: }
15553: member = member->next;
15554: }
15555: /*
15556: * 3.3.1 If the {base type definition} is the �simple ur-type
15557: * definition�
15558: */
15559: if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15560: /*
15561: * 3.3.1.1 All of the {member type definitions} must have a
15562: * {final} which does not contain union.
15563: */
15564: member = type->memberTypes;
15565: while (member != NULL) {
15566: if (xmlSchemaTypeFinalContains(member->type,
15567: XML_SCHEMAS_TYPE_FINAL_UNION)) {
15568: xmlSchemaPCustomErr(pctxt,
15569: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15570: WXS_BASIC_CAST type, NULL,
15571: "The 'final' of member type '%s' contains 'union'",
15572: xmlSchemaGetComponentQName(&str, member->type));
15573: FREE_AND_NULL(str)
15574: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15575: }
15576: member = member->next;
15577: }
15578: /*
15579: * 3.3.1.2 The {facets} must be empty.
15580: */
15581: if (type->facetSet != NULL) {
15582: xmlSchemaPCustomErr(pctxt,
15583: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15584: WXS_BASIC_CAST type, NULL,
15585: "No facets allowed", NULL);
15586: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15587: }
15588: } else {
15589: /*
15590: * 3.3.2.1 The {base type definition} must have a {variety} of union.
15591: * I.e. the variety of "list" is inherited.
15592: */
15593: if (! WXS_IS_UNION(type->baseType)) {
15594: xmlSchemaPCustomErr(pctxt,
15595: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15596: WXS_BASIC_CAST type, NULL,
15597: "The base type '%s' is not a union type",
15598: xmlSchemaGetComponentQName(&str, type->baseType));
15599: FREE_AND_NULL(str)
15600: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15601: }
15602: /*
15603: * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15604: */
15605: if (xmlSchemaTypeFinalContains(type->baseType,
15606: XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15607: xmlSchemaPCustomErr(pctxt,
15608: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15609: WXS_BASIC_CAST type, NULL,
15610: "The 'final' of its base type '%s' must not contain 'restriction'",
15611: xmlSchemaGetComponentQName(&str, type->baseType));
15612: FREE_AND_NULL(str)
15613: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15614: }
15615: /*
15616: * 3.3.2.3 The {member type definitions}, in order, must be validly
15617: * derived from the corresponding type definitions in the {base
15618: * type definition}'s {member type definitions} given the empty set,
15619: * as defined in Type Derivation OK (Simple) (�3.14.6).
15620: */
15621: {
15622: xmlSchemaTypeLinkPtr baseMember;
15623:
15624: /*
15625: * OPTIMIZE: if the type is restricting, it has no local defined
15626: * member types and inherits the member types of the base type;
15627: * thus a check for equality can be skipped.
15628: */
15629: /*
15630: * Even worse: I cannot see a scenario where a restricting
15631: * union simple type can have other member types as the member
15632: * types of it's base type. This check seems not necessary with
15633: * respect to the derivation process in libxml2.
15634: * But necessary if constructing types with an API.
15635: */
15636: if (type->memberTypes != NULL) {
15637: member = type->memberTypes;
15638: baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15639: if ((member == NULL) && (baseMember != NULL)) {
15640: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15641: "different number of member types in base");
15642: }
15643: while (member != NULL) {
15644: if (baseMember == NULL) {
15645: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15646: "different number of member types in base");
15647: } else if ((member->type != baseMember->type) &&
15648: (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15649: member->type, baseMember->type, 0) != 0)) {
15650: xmlChar *strBMT = NULL, *strBT = NULL;
15651:
15652: xmlSchemaPCustomErrExt(pctxt,
15653: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15654: WXS_BASIC_CAST type, NULL,
15655: "The member type %s is not validly "
15656: "derived from its corresponding member "
15657: "type %s of the base type %s",
15658: xmlSchemaGetComponentQName(&str, member->type),
15659: xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15660: xmlSchemaGetComponentQName(&strBT, type->baseType));
15661: FREE_AND_NULL(str)
15662: FREE_AND_NULL(strBMT)
15663: FREE_AND_NULL(strBT)
15664: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15665: }
15666: member = member->next;
15667: if (baseMember != NULL)
15668: baseMember = baseMember->next;
15669: }
15670: }
15671: }
15672: /*
15673: * 3.3.2.4 Only pattern and enumeration facet components are
15674: * allowed among the {facets}.
15675: */
15676: if (type->facets != NULL) {
15677: xmlSchemaFacetPtr facet;
15678: int ok = 1;
15679:
15680: facet = type->facets;
15681: do {
15682: if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15683: (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15684: xmlSchemaPIllegalFacetListUnionErr(pctxt,
15685: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15686: type, facet);
15687: ok = 0;
15688: }
15689: facet = facet->next;
15690: } while (facet != NULL);
15691: if (ok == 0)
15692: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15693:
15694: }
15695: /*
15696: * SPEC (3.3.2.5) (same as 1.3.2)
15697: *
15698: * NOTE (3.3.2.5) This is currently done in
15699: * xmlSchemaDeriveAndValidateFacets()
15700: */
15701: }
15702: }
15703:
15704: return (0);
15705: }
15706:
15707: /**
15708: * xmlSchemaCheckSRCSimpleType:
15709: * @ctxt: the schema parser context
15710: * @type: the simple type definition
15711: *
15712: * Checks crc-simple-type constraints.
15713: *
15714: * Returns 0 if the constraints are satisfied,
15715: * if not a positive error code and -1 on internal
15716: * errors.
15717: */
15718: #if 0
15719: static int
15720: xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15721: xmlSchemaTypePtr type)
15722: {
15723: /*
15724: * src-simple-type.1 The corresponding simple type definition, if any,
15725: * must satisfy the conditions set out in Constraints on Simple Type
15726: * Definition Schema Components (�3.14.6).
15727: */
15728: if (WXS_IS_RESTRICTION(type)) {
15729: /*
15730: * src-simple-type.2 "If the <restriction> alternative is chosen,
15731: * either it must have a base [attribute] or a <simpleType> among its
15732: * [children], but not both."
15733: * NOTE: This is checked in the parse function of <restriction>.
15734: */
15735: /*
15736: *
15737: */
15738: } else if (WXS_IS_LIST(type)) {
15739: /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15740: * an itemType [attribute] or a <simpleType> among its [children],
15741: * but not both."
15742: *
15743: * NOTE: This is checked in the parse function of <list>.
15744: */
15745: } else if (WXS_IS_UNION(type)) {
15746: /*
15747: * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15748: */
15749: }
15750: return (0);
15751: }
15752: #endif
15753:
15754: static int
15755: xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15756: {
15757: if (ctxt->vctxt == NULL) {
15758: ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15759: if (ctxt->vctxt == NULL) {
15760: xmlSchemaPErr(ctxt, NULL,
15761: XML_SCHEMAP_INTERNAL,
15762: "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15763: "failed to create a temp. validation context.\n",
15764: NULL, NULL);
15765: return (-1);
15766: }
15767: /* TODO: Pass user data. */
15768: xmlSchemaSetValidErrors(ctxt->vctxt,
15769: ctxt->error, ctxt->warning, ctxt->errCtxt);
15770: xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15771: ctxt->serror, ctxt->errCtxt);
15772: }
15773: return (0);
15774: }
15775:
15776: static int
15777: xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15778: xmlNodePtr node,
15779: xmlSchemaTypePtr type,
15780: const xmlChar *value,
15781: xmlSchemaValPtr *retVal,
15782: int fireErrors,
15783: int normalize,
15784: int isNormalized);
15785:
15786: /**
15787: * xmlSchemaParseCheckCOSValidDefault:
15788: * @pctxt: the schema parser context
15789: * @type: the simple type definition
15790: * @value: the default value
15791: * @node: an optional node (the holder of the value)
15792: *
15793: * Schema Component Constraint: Element Default Valid (Immediate)
15794: * (cos-valid-default)
15795: * This will be used by the parser only. For the validator there's
15796: * an other version.
15797: *
15798: * Returns 0 if the constraints are satisfied,
15799: * if not, a positive error code and -1 on internal
15800: * errors.
15801: */
15802: static int
15803: xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15804: xmlNodePtr node,
15805: xmlSchemaTypePtr type,
15806: const xmlChar *value,
15807: xmlSchemaValPtr *val)
15808: {
15809: int ret = 0;
15810:
15811: /*
15812: * cos-valid-default:
15813: * Schema Component Constraint: Element Default Valid (Immediate)
15814: * For a string to be a valid default with respect to a type
15815: * definition the appropriate case among the following must be true:
15816: */
15817: if WXS_IS_COMPLEX(type) {
15818: /*
15819: * Complex type.
15820: *
15821: * SPEC (2.1) "its {content type} must be a simple type definition
15822: * or mixed."
15823: * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15824: * type}'s particle must be �emptiable� as defined by
15825: * Particle Emptiable (�3.9.6)."
15826: */
15827: if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15828: ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15829: /* NOTE that this covers (2.2.2) as well. */
15830: xmlSchemaPCustomErr(pctxt,
15831: XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15832: WXS_BASIC_CAST type, type->node,
15833: "For a string to be a valid default, the type definition "
15834: "must be a simple type or a complex type with mixed content "
15835: "and a particle emptiable", NULL);
15836: return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15837: }
15838: }
15839: /*
15840: * 1 If the type definition is a simple type definition, then the string
15841: * must be �valid� with respect to that definition as defined by String
15842: * Valid (�3.14.4).
15843: *
15844: * AND
15845: *
15846: * 2.2.1 If the {content type} is a simple type definition, then the
15847: * string must be �valid� with respect to that simple type definition
15848: * as defined by String Valid (�3.14.4).
15849: */
15850: if (WXS_IS_SIMPLE(type))
15851: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15852: type, value, val, 1, 1, 0);
15853: else if (WXS_HAS_SIMPLE_CONTENT(type))
15854: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15855: type->contentTypeDef, value, val, 1, 1, 0);
15856: else
15857: return (ret);
15858:
15859: if (ret < 0) {
15860: PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15861: "calling xmlSchemaVCheckCVCSimpleType()");
15862: }
15863:
15864: return (ret);
15865: }
15866:
15867: /**
15868: * xmlSchemaCheckCTPropsCorrect:
15869: * @ctxt: the schema parser context
15870: * @type: the complex type definition
15871: *
15872: *.(4.6) Constraints on Complex Type Definition Schema Components
15873: * Schema Component Constraint:
15874: * Complex Type Definition Properties Correct (ct-props-correct)
15875: * STATUS: (seems) complete
15876: *
15877: * Returns 0 if the constraints are satisfied, a positive
15878: * error code if not and -1 if an internal error occured.
15879: */
15880: static int
15881: xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15882: xmlSchemaTypePtr type)
15883: {
15884: /*
15885: * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15886: *
15887: * SPEC (1) "The values of the properties of a complex type definition must
15888: * be as described in the property tableau in The Complex Type Definition
15889: * Schema Component (�3.4.1), modulo the impact of Missing
15890: * Sub-components (�5.3)."
15891: */
15892: if ((type->baseType != NULL) &&
15893: (WXS_IS_SIMPLE(type->baseType)) &&
15894: (WXS_IS_EXTENSION(type) == 0)) {
15895: /*
15896: * SPEC (2) "If the {base type definition} is a simple type definition,
15897: * the {derivation method} must be extension."
15898: */
15899: xmlSchemaCustomErr(ACTXT_CAST pctxt,
15900: XML_SCHEMAP_SRC_CT_1,
15901: NULL, WXS_BASIC_CAST type,
15902: "If the base type is a simple type, the derivation method must be "
15903: "'extension'", NULL, NULL);
15904: return (XML_SCHEMAP_SRC_CT_1);
15905: }
15906: /*
15907: * SPEC (3) "Circular definitions are disallowed, except for the �ur-type
15908: * definition�. That is, it must be possible to reach the �ur-type
15909: * definition by repeatedly following the {base type definition}."
15910: *
15911: * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15912: */
15913: /*
15914: * NOTE that (4) and (5) need the following:
15915: * - attribute uses need to be already inherited (apply attr. prohibitions)
15916: * - attribute group references need to be expanded already
15917: * - simple types need to be typefixed already
15918: */
15919: if (type->attrUses &&
15920: (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15921: {
15922: xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15923: xmlSchemaAttributeUsePtr use, tmp;
15924: int i, j, hasId = 0;
15925:
15926: for (i = uses->nbItems -1; i >= 0; i--) {
15927: use = uses->items[i];
15928:
15929: /*
15930: * SPEC ct-props-correct
15931: * (4) "Two distinct attribute declarations in the
15932: * {attribute uses} must not have identical {name}s and
15933: * {target namespace}s."
15934: */
15935: if (i > 0) {
15936: for (j = i -1; j >= 0; j--) {
15937: tmp = uses->items[j];
15938: if ((WXS_ATTRUSE_DECL_NAME(use) ==
15939: WXS_ATTRUSE_DECL_NAME(tmp)) &&
15940: (WXS_ATTRUSE_DECL_TNS(use) ==
15941: WXS_ATTRUSE_DECL_TNS(tmp)))
15942: {
15943: xmlChar *str = NULL;
15944:
15945: xmlSchemaCustomErr(ACTXT_CAST pctxt,
15946: XML_SCHEMAP_AG_PROPS_CORRECT,
15947: NULL, WXS_BASIC_CAST type,
15948: "Duplicate %s",
15949: xmlSchemaGetComponentDesignation(&str, use),
15950: NULL);
15951: FREE_AND_NULL(str);
15952: /*
15953: * Remove the duplicate.
15954: */
15955: if (xmlSchemaItemListRemove(uses, i) == -1)
15956: goto exit_failure;
15957: goto next_use;
15958: }
15959: }
15960: }
15961: /*
15962: * SPEC ct-props-correct
15963: * (5) "Two distinct attribute declarations in the
15964: * {attribute uses} must not have {type definition}s which
15965: * are or are derived from ID."
15966: */
15967: if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15968: if (xmlSchemaIsDerivedFromBuiltInType(
15969: WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15970: {
15971: if (hasId) {
15972: xmlChar *str = NULL;
15973:
15974: xmlSchemaCustomErr(ACTXT_CAST pctxt,
15975: XML_SCHEMAP_AG_PROPS_CORRECT,
15976: NULL, WXS_BASIC_CAST type,
15977: "There must not exist more than one attribute "
15978: "declaration of type 'xs:ID' "
15979: "(or derived from 'xs:ID'). The %s violates this "
15980: "constraint",
15981: xmlSchemaGetComponentDesignation(&str, use),
15982: NULL);
15983: FREE_AND_NULL(str);
15984: if (xmlSchemaItemListRemove(uses, i) == -1)
15985: goto exit_failure;
15986: }
15987:
15988: hasId = 1;
15989: }
15990: }
15991: next_use: {}
15992: }
15993: }
15994: return (0);
15995: exit_failure:
15996: return(-1);
15997: }
15998:
15999: static int
16000: xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16001: xmlSchemaTypePtr typeB)
16002: {
16003: /*
16004: * TODO: This should implement component-identity
16005: * in the future.
16006: */
16007: if ((typeA == NULL) || (typeB == NULL))
16008: return (0);
16009: return (typeA == typeB);
16010: }
16011:
16012: /**
16013: * xmlSchemaCheckCOSCTDerivedOK:
16014: * @ctxt: the schema parser context
16015: * @type: the to-be derived complex type definition
16016: * @baseType: the base complex type definition
16017: * @set: the given set
16018: *
16019: * Schema Component Constraint:
16020: * Type Derivation OK (Complex) (cos-ct-derived-ok)
16021: *
16022: * STATUS: completed
16023: *
16024: * Returns 0 if the constraints are satisfied, or 1
16025: * if not.
16026: */
16027: static int
16028: xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16029: xmlSchemaTypePtr type,
16030: xmlSchemaTypePtr baseType,
16031: int set)
16032: {
16033: int equal = xmlSchemaAreEqualTypes(type, baseType);
16034: /* TODO: Error codes. */
16035: /*
16036: * SPEC "For a complex type definition (call it D, for derived)
16037: * to be validly derived from a type definition (call this
16038: * B, for base) given a subset of {extension, restriction}
16039: * all of the following must be true:"
16040: */
16041: if (! equal) {
16042: /*
16043: * SPEC (1) "If B and D are not the same type definition, then the
16044: * {derivation method} of D must not be in the subset."
16045: */
16046: if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16047: ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16048: return (1);
16049: } else {
16050: /*
16051: * SPEC (2.1) "B and D must be the same type definition."
16052: */
16053: return (0);
16054: }
16055: /*
16056: * SPEC (2.2) "B must be D's {base type definition}."
16057: */
16058: if (type->baseType == baseType)
16059: return (0);
16060: /*
16061: * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type
16062: * definition�."
16063: */
16064: if (WXS_IS_ANYTYPE(type->baseType))
16065: return (1);
16066:
16067: if (WXS_IS_COMPLEX(type->baseType)) {
16068: /*
16069: * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16070: * must be validly derived from B given the subset as defined by this
16071: * constraint."
16072: */
16073: return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16074: baseType, set));
16075: } else {
16076: /*
16077: * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16078: * must be validly derived from B given the subset as defined in Type
16079: * Derivation OK (Simple) (�3.14.6).
16080: */
16081: return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16082: baseType, set));
16083: }
16084: }
16085:
16086: /**
16087: * xmlSchemaCheckCOSDerivedOK:
16088: * @type: the derived simple type definition
16089: * @baseType: the base type definition
16090: *
16091: * Calls:
16092: * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16093: *
16094: * Checks wheter @type can be validly derived from @baseType.
16095: *
16096: * Returns 0 on success, an positive error code otherwise.
16097: */
16098: static int
16099: xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16100: xmlSchemaTypePtr type,
16101: xmlSchemaTypePtr baseType,
16102: int set)
16103: {
16104: if (WXS_IS_SIMPLE(type))
16105: return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16106: else
16107: return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16108: }
16109:
16110: /**
16111: * xmlSchemaCheckCOSCTExtends:
16112: * @ctxt: the schema parser context
16113: * @type: the complex type definition
16114: *
16115: * (3.4.6) Constraints on Complex Type Definition Schema Components
16116: * Schema Component Constraint:
16117: * Derivation Valid (Extension) (cos-ct-extends)
16118: *
16119: * STATUS:
16120: * missing:
16121: * (1.5)
16122: * (1.4.3.2.2.2) "Particle Valid (Extension)"
16123: *
16124: * Returns 0 if the constraints are satisfied, a positive
16125: * error code if not and -1 if an internal error occured.
16126: */
16127: static int
16128: xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16129: xmlSchemaTypePtr type)
16130: {
16131: xmlSchemaTypePtr base = type->baseType;
16132: /*
16133: * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16134: * temporarily only.
16135: */
16136: /*
16137: * SPEC (1) "If the {base type definition} is a complex type definition,
16138: * then all of the following must be true:"
16139: */
16140: if (WXS_IS_COMPLEX(base)) {
16141: /*
16142: * SPEC (1.1) "The {final} of the {base type definition} must not
16143: * contain extension."
16144: */
16145: if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16146: xmlSchemaPCustomErr(ctxt,
16147: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16148: WXS_BASIC_CAST type, NULL,
16149: "The 'final' of the base type definition "
16150: "contains 'extension'", NULL);
16151: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16152: }
16153:
16154: /*
16155: * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16156: * since they are automatically satisfied through the
16157: * inheriting mechanism.
16158: * Note that even if redefining components, the inheriting mechanism
16159: * is used.
16160: */
16161: #if 0
16162: /*
16163: * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16164: * uses}
16165: * of the complex type definition itself, that is, for every attribute
16166: * use in the {attribute uses} of the {base type definition}, there
16167: * must be an attribute use in the {attribute uses} of the complex
16168: * type definition itself whose {attribute declaration} has the same
16169: * {name}, {target namespace} and {type definition} as its attribute
16170: * declaration"
16171: */
16172: if (base->attrUses != NULL) {
16173: int i, j, found;
16174: xmlSchemaAttributeUsePtr use, buse;
16175:
16176: for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16177: buse = (WXS_LIST_CAST base->attrUses)->items[i];
16178: found = 0;
16179: if (type->attrUses != NULL) {
16180: use = (WXS_LIST_CAST type->attrUses)->items[j];
16181: for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16182: {
16183: if ((WXS_ATTRUSE_DECL_NAME(use) ==
16184: WXS_ATTRUSE_DECL_NAME(buse)) &&
16185: (WXS_ATTRUSE_DECL_TNS(use) ==
16186: WXS_ATTRUSE_DECL_TNS(buse)) &&
16187: (WXS_ATTRUSE_TYPEDEF(use) ==
16188: WXS_ATTRUSE_TYPEDEF(buse))
16189: {
16190: found = 1;
16191: break;
16192: }
16193: }
16194: }
16195: if (! found) {
16196: xmlChar *str = NULL;
16197:
16198: xmlSchemaCustomErr(ACTXT_CAST ctxt,
16199: XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16200: NULL, WXS_BASIC_CAST type,
16201: /*
16202: * TODO: The report does not indicate that also the
16203: * type needs to be the same.
16204: */
16205: "This type is missing a matching correspondent "
16206: "for its {base type}'s %s in its {attribute uses}",
16207: xmlSchemaGetComponentDesignation(&str,
16208: buse->children),
16209: NULL);
16210: FREE_AND_NULL(str)
16211: }
16212: }
16213: }
16214: /*
16215: * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16216: * definition must also have one, and the base type definition's
16217: * {attribute wildcard}'s {namespace constraint} must be a subset
16218: * of the complex type definition's {attribute wildcard}'s {namespace
16219: * constraint}, as defined by Wildcard Subset (�3.10.6)."
16220: */
16221:
16222: /*
16223: * MAYBE TODO: Enable if ever needed. But this will be needed only
16224: * if created the type via a schema construction API.
16225: */
16226: if (base->attributeWildcard != NULL) {
16227: if (type->attributeWilcard == NULL) {
16228: xmlChar *str = NULL;
16229:
16230: xmlSchemaCustomErr(ACTXT_CAST pctxt,
16231: XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16232: NULL, type,
16233: "The base %s has an attribute wildcard, "
16234: "but this type is missing an attribute wildcard",
16235: xmlSchemaGetComponentDesignation(&str, base));
16236: FREE_AND_NULL(str)
16237:
16238: } else if (xmlSchemaCheckCOSNSSubset(
16239: base->attributeWildcard, type->attributeWildcard))
16240: {
16241: xmlChar *str = NULL;
16242:
16243: xmlSchemaCustomErr(ACTXT_CAST pctxt,
16244: XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16245: NULL, type,
16246: "The attribute wildcard is not a valid "
16247: "superset of the one in the base %s",
16248: xmlSchemaGetComponentDesignation(&str, base));
16249: FREE_AND_NULL(str)
16250: }
16251: }
16252: #endif
16253: /*
16254: * SPEC (1.4) "One of the following must be true:"
16255: */
16256: if ((type->contentTypeDef != NULL) &&
16257: (type->contentTypeDef == base->contentTypeDef)) {
16258: /*
16259: * SPEC (1.4.1) "The {content type} of the {base type definition}
16260: * and the {content type} of the complex type definition itself
16261: * must be the same simple type definition"
16262: * PASS
16263: */
16264: } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16265: (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16266: /*
16267: * SPEC (1.4.2) "The {content type} of both the {base type
16268: * definition} and the complex type definition itself must
16269: * be empty."
16270: * PASS
16271: */
16272: } else {
16273: /*
16274: * SPEC (1.4.3) "All of the following must be true:"
16275: */
16276: if (type->subtypes == NULL) {
16277: /*
16278: * SPEC 1.4.3.1 The {content type} of the complex type
16279: * definition itself must specify a particle.
16280: */
16281: xmlSchemaPCustomErr(ctxt,
16282: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16283: WXS_BASIC_CAST type, NULL,
16284: "The content type must specify a particle", NULL);
16285: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16286: }
16287: /*
16288: * SPEC (1.4.3.2) "One of the following must be true:"
16289: */
16290: if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16291: /*
16292: * SPEC (1.4.3.2.1) "The {content type} of the {base type
16293: * definition} must be empty.
16294: * PASS
16295: */
16296: } else {
16297: /*
16298: * SPEC (1.4.3.2.2) "All of the following must be true:"
16299: */
16300: if ((type->contentType != base->contentType) ||
16301: ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16302: (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16303: /*
16304: * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16305: * or both must be element-only."
16306: */
16307: xmlSchemaPCustomErr(ctxt,
16308: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16309: WXS_BASIC_CAST type, NULL,
16310: "The content type of both, the type and its base "
16311: "type, must either 'mixed' or 'element-only'", NULL);
16312: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16313: }
16314: /*
16315: * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16316: * complex type definition must be a �valid extension�
16317: * of the {base type definition}'s particle, as defined
16318: * in Particle Valid (Extension) (�3.9.6)."
16319: *
16320: * NOTE that we won't check "Particle Valid (Extension)",
16321: * since it is ensured by the derivation process in
16322: * xmlSchemaTypeFixup(). We need to implement this when heading
16323: * for a construction API
16324: * TODO: !! This is needed to be checked if redefining a type !!
16325: */
16326: }
16327: /*
16328: * URGENT TODO (1.5)
16329: */
16330: }
16331: } else {
16332: /*
16333: * SPEC (2) "If the {base type definition} is a simple type definition,
16334: * then all of the following must be true:"
16335: */
16336: if (type->contentTypeDef != base) {
16337: /*
16338: * SPEC (2.1) "The {content type} must be the same simple type
16339: * definition."
16340: */
16341: xmlSchemaPCustomErr(ctxt,
16342: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16343: WXS_BASIC_CAST type, NULL,
16344: "The content type must be the simple base type", NULL);
16345: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16346: }
16347: if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16348: /*
16349: * SPEC (2.2) "The {final} of the {base type definition} must not
16350: * contain extension"
16351: * NOTE that this is the same as (1.1).
16352: */
16353: xmlSchemaPCustomErr(ctxt,
16354: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16355: WXS_BASIC_CAST type, NULL,
16356: "The 'final' of the base type definition "
16357: "contains 'extension'", NULL);
16358: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16359: }
16360: }
16361: return (0);
16362: }
16363:
16364: /**
16365: * xmlSchemaCheckDerivationOKRestriction:
16366: * @ctxt: the schema parser context
16367: * @type: the complex type definition
16368: *
16369: * (3.4.6) Constraints on Complex Type Definition Schema Components
16370: * Schema Component Constraint:
16371: * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16372: *
16373: * STATUS:
16374: * missing:
16375: * (5.4.2) ???
16376: *
16377: * ATTENTION:
16378: * In XML Schema 1.1 this will be:
16379: * Validation Rule: Checking complex type subsumption
16380: *
16381: * Returns 0 if the constraints are satisfied, a positive
16382: * error code if not and -1 if an internal error occured.
16383: */
16384: static int
16385: xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16386: xmlSchemaTypePtr type)
16387: {
16388: xmlSchemaTypePtr base;
16389:
16390: /*
16391: * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16392: * temporarily only.
16393: */
16394: base = type->baseType;
16395: if (! WXS_IS_COMPLEX(base)) {
16396: xmlSchemaCustomErr(ACTXT_CAST ctxt,
16397: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16398: type->node, WXS_BASIC_CAST type,
16399: "The base type must be a complex type", NULL, NULL);
16400: return(ctxt->err);
16401: }
16402: if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16403: /*
16404: * SPEC (1) "The {base type definition} must be a complex type
16405: * definition whose {final} does not contain restriction."
16406: */
16407: xmlSchemaCustomErr(ACTXT_CAST ctxt,
16408: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16409: type->node, WXS_BASIC_CAST type,
16410: "The 'final' of the base type definition "
16411: "contains 'restriction'", NULL, NULL);
16412: return (ctxt->err);
16413: }
16414: /*
16415: * SPEC (2), (3) and (4)
16416: * Those are handled in a separate function, since the
16417: * same constraints are needed for redefinition of
16418: * attribute groups as well.
16419: */
16420: if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16421: XML_SCHEMA_ACTION_DERIVE,
16422: WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16423: type->attrUses, base->attrUses,
16424: type->attributeWildcard,
16425: base->attributeWildcard) == -1)
16426: {
16427: return(-1);
16428: }
16429: /*
16430: * SPEC (5) "One of the following must be true:"
16431: */
16432: if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16433: /*
16434: * SPEC (5.1) "The {base type definition} must be the
16435: * �ur-type definition�."
16436: * PASS
16437: */
16438: } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16439: (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16440: /*
16441: * SPEC (5.2.1) "The {content type} of the complex type definition
16442: * must be a simple type definition"
16443: *
16444: * SPEC (5.2.2) "One of the following must be true:"
16445: */
16446: if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16447: (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16448: {
16449: int err;
16450: /*
16451: * SPEC (5.2.2.1) "The {content type} of the {base type
16452: * definition} must be a simple type definition from which
16453: * the {content type} is validly derived given the empty
16454: * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16455: *
16456: * ATTENTION TODO: This seems not needed if the type implicitely
16457: * derived from the base type.
16458: *
16459: */
16460: err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16461: type->contentTypeDef, base->contentTypeDef, 0);
16462: if (err != 0) {
16463: xmlChar *strA = NULL, *strB = NULL;
16464:
16465: if (err == -1)
16466: return(-1);
16467: xmlSchemaCustomErr(ACTXT_CAST ctxt,
16468: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16469: NULL, WXS_BASIC_CAST type,
16470: "The {content type} %s is not validly derived from the "
16471: "base type's {content type} %s",
16472: xmlSchemaGetComponentDesignation(&strA,
16473: type->contentTypeDef),
16474: xmlSchemaGetComponentDesignation(&strB,
16475: base->contentTypeDef));
16476: FREE_AND_NULL(strA);
16477: FREE_AND_NULL(strB);
16478: return(ctxt->err);
16479: }
16480: } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16481: (xmlSchemaIsParticleEmptiable(
16482: (xmlSchemaParticlePtr) base->subtypes))) {
16483: /*
16484: * SPEC (5.2.2.2) "The {base type definition} must be mixed
16485: * and have a particle which is �emptiable� as defined in
16486: * 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: "a simple type or 'mixed' and an emptiable particle", NULL);
16495: return (ctxt->err);
16496: }
16497: } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16498: /*
16499: * SPEC (5.3.1) "The {content type} of the complex type itself must
16500: * be empty"
16501: */
16502: if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16503: /*
16504: * SPEC (5.3.2.1) "The {content type} of the {base type
16505: * definition} must also be empty."
16506: * PASS
16507: */
16508: } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16509: (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16510: xmlSchemaIsParticleEmptiable(
16511: (xmlSchemaParticlePtr) base->subtypes)) {
16512: /*
16513: * SPEC (5.3.2.2) "The {content type} of the {base type
16514: * definition} must be elementOnly or mixed and have a particle
16515: * which is �emptiable� as defined in Particle Emptiable (�3.9.6)."
16516: * PASS
16517: */
16518: } else {
16519: xmlSchemaPCustomErr(ctxt,
16520: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16521: WXS_BASIC_CAST type, NULL,
16522: "The content type of the base type must be either "
16523: "empty or 'mixed' (or 'elements-only') and an emptiable "
16524: "particle", NULL);
16525: return (ctxt->err);
16526: }
16527: } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16528: WXS_HAS_MIXED_CONTENT(type)) {
16529: /*
16530: * SPEC (5.4.1.1) "The {content type} of the complex type definition
16531: * itself must be element-only"
16532: */
16533: if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16534: /*
16535: * SPEC (5.4.1.2) "The {content type} of the complex type
16536: * definition itself and of the {base type definition} must be
16537: * mixed"
16538: */
16539: xmlSchemaPCustomErr(ctxt,
16540: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16541: WXS_BASIC_CAST type, NULL,
16542: "If the content type is 'mixed', then the content type of the "
16543: "base type must also be 'mixed'", NULL);
16544: return (ctxt->err);
16545: }
16546: /*
16547: * SPEC (5.4.2) "The particle of the complex type definition itself
16548: * must be a �valid restriction� of the particle of the {content
16549: * type} of the {base type definition} as defined in Particle Valid
16550: * (Restriction) (�3.9.6).
16551: *
16552: * URGENT TODO: (5.4.2)
16553: */
16554: } else {
16555: xmlSchemaPCustomErr(ctxt,
16556: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16557: WXS_BASIC_CAST type, NULL,
16558: "The type is not a valid restriction of its base type", NULL);
16559: return (ctxt->err);
16560: }
16561: return (0);
16562: }
16563:
16564: /**
16565: * xmlSchemaCheckCTComponent:
16566: * @ctxt: the schema parser context
16567: * @type: the complex type definition
16568: *
16569: * (3.4.6) Constraints on Complex Type Definition Schema Components
16570: *
16571: * Returns 0 if the constraints are satisfied, a positive
16572: * error code if not and -1 if an internal error occured.
16573: */
16574: static int
16575: xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16576: xmlSchemaTypePtr type)
16577: {
16578: int ret;
16579: /*
16580: * Complex Type Definition Properties Correct
16581: */
16582: ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16583: if (ret != 0)
16584: return (ret);
16585: if (WXS_IS_EXTENSION(type))
16586: ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16587: else
16588: ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16589: return (ret);
16590: }
16591:
16592: /**
16593: * xmlSchemaCheckSRCCT:
16594: * @ctxt: the schema parser context
16595: * @type: the complex type definition
16596: *
16597: * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16598: * Schema Representation Constraint:
16599: * Complex Type Definition Representation OK (src-ct)
16600: *
16601: * Returns 0 if the constraints are satisfied, a positive
16602: * error code if not and -1 if an internal error occured.
16603: */
16604: static int
16605: xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16606: xmlSchemaTypePtr type)
16607: {
16608: xmlSchemaTypePtr base;
16609: int ret = 0;
16610:
16611: /*
16612: * TODO: Adjust the error codes here, as I used
16613: * XML_SCHEMAP_SRC_CT_1 only yet.
16614: */
16615: base = type->baseType;
16616: if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16617: /*
16618: * 1 If the <complexContent> alternative is chosen, the type definition
16619: * �resolved� to by the �actual value� of the base [attribute]
16620: * must be a complex type definition;
16621: */
16622: if (! WXS_IS_COMPLEX(base)) {
16623: xmlChar *str = NULL;
16624: xmlSchemaPCustomErr(ctxt,
16625: XML_SCHEMAP_SRC_CT_1,
16626: WXS_BASIC_CAST type, type->node,
16627: "If using <complexContent>, the base type is expected to be "
16628: "a complex type. The base type '%s' is a simple type",
16629: xmlSchemaFormatQName(&str, base->targetNamespace,
16630: base->name));
16631: FREE_AND_NULL(str)
16632: return (XML_SCHEMAP_SRC_CT_1);
16633: }
16634: } else {
16635: /*
16636: * SPEC
16637: * 2 If the <simpleContent> alternative is chosen, all of the
16638: * following must be true:
16639: * 2.1 The type definition �resolved� to by the �actual value� of the
16640: * base [attribute] must be one of the following:
16641: */
16642: if (WXS_IS_SIMPLE(base)) {
16643: if (WXS_IS_EXTENSION(type) == 0) {
16644: xmlChar *str = NULL;
16645: /*
16646: * 2.1.3 only if the <extension> alternative is also
16647: * chosen, a simple type definition.
16648: */
16649: /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16650: xmlSchemaPCustomErr(ctxt,
16651: XML_SCHEMAP_SRC_CT_1,
16652: WXS_BASIC_CAST type, NULL,
16653: "If using <simpleContent> and <restriction>, the base "
16654: "type must be a complex type. The base type '%s' is "
16655: "a simple type",
16656: xmlSchemaFormatQName(&str, base->targetNamespace,
16657: base->name));
16658: FREE_AND_NULL(str)
16659: return (XML_SCHEMAP_SRC_CT_1);
16660: }
16661: } else {
16662: /* Base type is a complex type. */
16663: if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16664: (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16665: /*
16666: * 2.1.1 a complex type definition whose {content type} is a
16667: * simple type definition;
16668: * PASS
16669: */
16670: if (base->contentTypeDef == NULL) {
16671: xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16672: WXS_BASIC_CAST type, NULL,
16673: "Internal error: xmlSchemaCheckSRCCT, "
16674: "'%s', base type has no content type",
16675: type->name);
16676: return (-1);
16677: }
16678: } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16679: (WXS_IS_RESTRICTION(type))) {
16680:
16681: /*
16682: * 2.1.2 only if the <restriction> alternative is also
16683: * chosen, a complex type definition whose {content type}
16684: * is mixed and a particle emptiable.
16685: */
16686: if (! xmlSchemaIsParticleEmptiable(
16687: (xmlSchemaParticlePtr) base->subtypes)) {
16688: ret = XML_SCHEMAP_SRC_CT_1;
16689: } else
16690: /*
16691: * Attention: at this point the <simpleType> child is in
16692: * ->contentTypeDef (put there during parsing).
16693: */
16694: if (type->contentTypeDef == NULL) {
16695: xmlChar *str = NULL;
16696: /*
16697: * 2.2 If clause 2.1.2 above is satisfied, then there
16698: * must be a <simpleType> among the [children] of
16699: * <restriction>.
16700: */
16701: /* TODO: Change error code to ..._SRC_CT_2_2. */
16702: xmlSchemaPCustomErr(ctxt,
16703: XML_SCHEMAP_SRC_CT_1,
16704: WXS_BASIC_CAST type, NULL,
16705: "A <simpleType> is expected among the children "
16706: "of <restriction>, if <simpleContent> is used and "
16707: "the base type '%s' is a complex type",
16708: xmlSchemaFormatQName(&str, base->targetNamespace,
16709: base->name));
16710: FREE_AND_NULL(str)
16711: return (XML_SCHEMAP_SRC_CT_1);
16712: }
16713: } else {
16714: ret = XML_SCHEMAP_SRC_CT_1;
16715: }
16716: }
16717: if (ret > 0) {
16718: xmlChar *str = NULL;
16719: if (WXS_IS_RESTRICTION(type)) {
16720: xmlSchemaPCustomErr(ctxt,
16721: XML_SCHEMAP_SRC_CT_1,
16722: WXS_BASIC_CAST type, NULL,
16723: "If <simpleContent> and <restriction> is used, the "
16724: "base type must be a simple type or a complex type with "
16725: "mixed content and particle emptiable. The base type "
16726: "'%s' is none of those",
16727: xmlSchemaFormatQName(&str, base->targetNamespace,
16728: base->name));
16729: } else {
16730: xmlSchemaPCustomErr(ctxt,
16731: XML_SCHEMAP_SRC_CT_1,
16732: WXS_BASIC_CAST type, NULL,
16733: "If <simpleContent> and <extension> is used, the "
16734: "base type must be a simple type. The base type '%s' "
16735: "is a complex type",
16736: xmlSchemaFormatQName(&str, base->targetNamespace,
16737: base->name));
16738: }
16739: FREE_AND_NULL(str)
16740: }
16741: }
16742: /*
16743: * SPEC (3) "The corresponding complex type definition component must
16744: * satisfy the conditions set out in Constraints on Complex Type
16745: * Definition Schema Components (�3.4.6);"
16746: * NOTE (3) will be done in xmlSchemaTypeFixup().
16747: */
16748: /*
16749: * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16750: * above for {attribute wildcard} is satisfied, the intensional
16751: * intersection must be expressible, as defined in Attribute Wildcard
16752: * Intersection (�3.10.6).
16753: * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16754: */
16755: return (ret);
16756: }
16757:
16758: #ifdef ENABLE_PARTICLE_RESTRICTION
16759: /**
16760: * xmlSchemaCheckParticleRangeOK:
16761: * @ctxt: the schema parser context
16762: * @type: the complex type definition
16763: *
16764: * (3.9.6) Constraints on Particle Schema Components
16765: * Schema Component Constraint:
16766: * Occurrence Range OK (range-ok)
16767: *
16768: * STATUS: complete
16769: *
16770: * Returns 0 if the constraints are satisfied, a positive
16771: * error code if not and -1 if an internal error occured.
16772: */
16773: static int
16774: xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16775: int bmin, int bmax)
16776: {
16777: if (rmin < bmin)
16778: return (1);
16779: if ((bmax != UNBOUNDED) &&
16780: (rmax > bmax))
16781: return (1);
16782: return (0);
16783: }
16784:
16785: /**
16786: * xmlSchemaCheckRCaseNameAndTypeOK:
16787: * @ctxt: the schema parser context
16788: * @r: the restricting element declaration particle
16789: * @b: the base element declaration particle
16790: *
16791: * (3.9.6) Constraints on Particle Schema Components
16792: * Schema Component Constraint:
16793: * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16794: * (rcase-NameAndTypeOK)
16795: *
16796: * STATUS:
16797: * MISSING (3.2.3)
16798: * CLARIFY: (3.2.2)
16799: *
16800: * Returns 0 if the constraints are satisfied, a positive
16801: * error code if not and -1 if an internal error occured.
16802: */
16803: static int
16804: xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16805: xmlSchemaParticlePtr r,
16806: xmlSchemaParticlePtr b)
16807: {
16808: xmlSchemaElementPtr elemR, elemB;
16809:
16810: /* TODO: Error codes (rcase-NameAndTypeOK). */
16811: elemR = (xmlSchemaElementPtr) r->children;
16812: elemB = (xmlSchemaElementPtr) b->children;
16813: /*
16814: * SPEC (1) "The declarations' {name}s and {target namespace}s are
16815: * the same."
16816: */
16817: if ((elemR != elemB) &&
16818: ((! xmlStrEqual(elemR->name, elemB->name)) ||
16819: (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16820: return (1);
16821: /*
16822: * SPEC (2) "R's occurrence range is a valid restriction of B's
16823: * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16824: */
16825: if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16826: b->minOccurs, b->maxOccurs) != 0)
16827: return (1);
16828: /*
16829: * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16830: * {scope} are global."
16831: */
16832: if (elemR == elemB)
16833: return (0);
16834: /*
16835: * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16836: */
16837: if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16838: (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16839: return (1);
16840: /*
16841: * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16842: * or is not fixed, or R's declaration's {value constraint} is fixed
16843: * with the same value."
16844: */
16845: if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16846: ((elemR->value == NULL) ||
16847: ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16848: /* TODO: Equality of the initial value or normalized or canonical? */
16849: (! xmlStrEqual(elemR->value, elemB->value))))
16850: return (1);
16851: /*
16852: * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16853: * definitions} is a subset of B's declaration's {identity-constraint
16854: * definitions}, if any."
16855: */
16856: if (elemB->idcs != NULL) {
16857: /* TODO */
16858: }
16859: /*
16860: * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16861: * superset of B's declaration's {disallowed substitutions}."
16862: */
16863: if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16864: ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16865: ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16866: ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16867: ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16868: ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16869: return (1);
16870: /*
16871: * SPEC (3.2.5) "R's {type definition} is validly derived given
16872: * {extension, list, union} from B's {type definition}"
16873: *
16874: * BADSPEC TODO: What's the point of adding "list" and "union" to the
16875: * set, if the corresponding constraints handle "restriction" and
16876: * "extension" only?
16877: *
16878: */
16879: {
16880: int set = 0;
16881:
16882: set |= SUBSET_EXTENSION;
16883: set |= SUBSET_LIST;
16884: set |= SUBSET_UNION;
16885: if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16886: elemB->subtypes, set) != 0)
16887: return (1);
16888: }
16889: return (0);
16890: }
16891:
16892: /**
16893: * xmlSchemaCheckRCaseNSCompat:
16894: * @ctxt: the schema parser context
16895: * @r: the restricting element declaration particle
16896: * @b: the base wildcard particle
16897: *
16898: * (3.9.6) Constraints on Particle Schema Components
16899: * Schema Component Constraint:
16900: * Particle Derivation OK (Elt:Any -- NSCompat)
16901: * (rcase-NSCompat)
16902: *
16903: * STATUS: complete
16904: *
16905: * Returns 0 if the constraints are satisfied, a positive
16906: * error code if not and -1 if an internal error occured.
16907: */
16908: static int
16909: xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16910: xmlSchemaParticlePtr r,
16911: xmlSchemaParticlePtr b)
16912: {
16913: /* TODO:Error codes (rcase-NSCompat). */
16914: /*
16915: * SPEC "For an element declaration particle to be a �valid restriction�
16916: * of a wildcard particle all of the following must be true:"
16917: *
16918: * SPEC (1) "The element declaration's {target namespace} is �valid�
16919: * with respect to the wildcard's {namespace constraint} as defined by
16920: * Wildcard allows Namespace Name (�3.10.4)."
16921: */
16922: if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16923: ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16924: return (1);
16925: /*
16926: * SPEC (2) "R's occurrence range is a valid restriction of B's
16927: * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16928: */
16929: if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16930: b->minOccurs, b->maxOccurs) != 0)
16931: return (1);
16932:
16933: return (0);
16934: }
16935:
16936: /**
16937: * xmlSchemaCheckRCaseRecurseAsIfGroup:
16938: * @ctxt: the schema parser context
16939: * @r: the restricting element declaration particle
16940: * @b: the base model group particle
16941: *
16942: * (3.9.6) Constraints on Particle Schema Components
16943: * Schema Component Constraint:
16944: * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16945: * (rcase-RecurseAsIfGroup)
16946: *
16947: * STATUS: TODO
16948: *
16949: * Returns 0 if the constraints are satisfied, a positive
16950: * error code if not and -1 if an internal error occured.
16951: */
16952: static int
16953: xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16954: xmlSchemaParticlePtr r,
16955: xmlSchemaParticlePtr b)
16956: {
16957: /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16958: TODO
16959: return (0);
16960: }
16961:
16962: /**
16963: * xmlSchemaCheckRCaseNSSubset:
16964: * @ctxt: the schema parser context
16965: * @r: the restricting wildcard particle
16966: * @b: the base wildcard particle
16967: *
16968: * (3.9.6) Constraints on Particle Schema Components
16969: * Schema Component Constraint:
16970: * Particle Derivation OK (Any:Any -- NSSubset)
16971: * (rcase-NSSubset)
16972: *
16973: * STATUS: complete
16974: *
16975: * Returns 0 if the constraints are satisfied, a positive
16976: * error code if not and -1 if an internal error occured.
16977: */
16978: static int
16979: xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16980: xmlSchemaParticlePtr r,
16981: xmlSchemaParticlePtr b,
16982: int isAnyTypeBase)
16983: {
16984: /* TODO: Error codes (rcase-NSSubset). */
16985: /*
16986: * SPEC (1) "R's occurrence range is a valid restriction of B's
16987: * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16988: */
16989: if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16990: b->minOccurs, b->maxOccurs))
16991: return (1);
16992: /*
16993: * SPEC (2) "R's {namespace constraint} must be an intensional subset
16994: * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16995: */
16996: if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16997: (xmlSchemaWildcardPtr) b->children))
16998: return (1);
16999: /*
17000: * SPEC (3) "Unless B is the content model wildcard of the �ur-type
17001: * definition�, R's {process contents} must be identical to or stronger
17002: * than B's {process contents}, where strict is stronger than lax is
17003: * stronger than skip."
17004: */
17005: if (! isAnyTypeBase) {
17006: if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17007: ((xmlSchemaWildcardPtr) b->children)->processContents)
17008: return (1);
17009: }
17010:
17011: return (0);
17012: }
17013:
17014: /**
17015: * xmlSchemaCheckCOSParticleRestrict:
17016: * @ctxt: the schema parser context
17017: * @type: the complex type definition
17018: *
17019: * (3.9.6) Constraints on Particle Schema Components
17020: * Schema Component Constraint:
17021: * Particle Valid (Restriction) (cos-particle-restrict)
17022: *
17023: * STATUS: TODO
17024: *
17025: * Returns 0 if the constraints are satisfied, a positive
17026: * error code if not and -1 if an internal error occured.
17027: */
17028: static int
17029: xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17030: xmlSchemaParticlePtr r,
17031: xmlSchemaParticlePtr b)
17032: {
17033: int ret = 0;
17034:
17035: /*part = WXS_TYPE_PARTICLE(type);
17036: basePart = WXS_TYPE_PARTICLE(base);
17037: */
17038:
17039: TODO
17040:
17041: /*
17042: * SPEC (1) "They are the same particle."
17043: */
17044: if (r == b)
17045: return (0);
17046:
17047:
17048: return (0);
17049: }
17050:
17051: #if 0
17052: /**
17053: * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17054: * @ctxt: the schema parser context
17055: * @r: the model group particle
17056: * @b: the base wildcard particle
17057: *
17058: * (3.9.6) Constraints on Particle Schema Components
17059: * Schema Component Constraint:
17060: * Particle Derivation OK (All/Choice/Sequence:Any --
17061: * NSRecurseCheckCardinality)
17062: * (rcase-NSRecurseCheckCardinality)
17063: *
17064: * STATUS: TODO: subst-groups
17065: *
17066: * Returns 0 if the constraints are satisfied, a positive
17067: * error code if not and -1 if an internal error occured.
17068: */
17069: static int
17070: xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17071: xmlSchemaParticlePtr r,
17072: xmlSchemaParticlePtr b)
17073: {
17074: xmlSchemaParticlePtr part;
17075: /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17076: if ((r->children == NULL) || (r->children->children == NULL))
17077: return (-1);
17078: /*
17079: * SPEC "For a group particle to be a �valid restriction� of a
17080: * wildcard particle..."
17081: *
17082: * SPEC (1) "Every member of the {particles} of the group is a �valid
17083: * restriction� of the wildcard as defined by
17084: * Particle Valid (Restriction) (�3.9.6)."
17085: */
17086: part = (xmlSchemaParticlePtr) r->children->children;
17087: do {
17088: if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17089: return (1);
17090: part = (xmlSchemaParticlePtr) part->next;
17091: } while (part != NULL);
17092: /*
17093: * SPEC (2) "The effective total range of the group [...] is a
17094: * valid restriction of B's occurrence range as defined by
17095: * Occurrence Range OK (�3.9.6)."
17096: */
17097: if (xmlSchemaCheckParticleRangeOK(
17098: xmlSchemaGetParticleTotalRangeMin(r),
17099: xmlSchemaGetParticleTotalRangeMax(r),
17100: b->minOccurs, b->maxOccurs) != 0)
17101: return (1);
17102: return (0);
17103: }
17104: #endif
17105:
17106: /**
17107: * xmlSchemaCheckRCaseRecurse:
17108: * @ctxt: the schema parser context
17109: * @r: the <all> or <sequence> model group particle
17110: * @b: the base <all> or <sequence> model group particle
17111: *
17112: * (3.9.6) Constraints on Particle Schema Components
17113: * Schema Component Constraint:
17114: * Particle Derivation OK (All:All,Sequence:Sequence --
17115: Recurse)
17116: * (rcase-Recurse)
17117: *
17118: * STATUS: ?
17119: * TODO: subst-groups
17120: *
17121: * Returns 0 if the constraints are satisfied, a positive
17122: * error code if not and -1 if an internal error occured.
17123: */
17124: static int
17125: xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17126: xmlSchemaParticlePtr r,
17127: xmlSchemaParticlePtr b)
17128: {
17129: /* xmlSchemaParticlePtr part; */
17130: /* TODO: Error codes (rcase-Recurse). */
17131: if ((r->children == NULL) || (b->children == NULL) ||
17132: (r->children->type != b->children->type))
17133: return (-1);
17134: /*
17135: * SPEC "For an all or sequence group particle to be a �valid
17136: * restriction� of another group particle with the same {compositor}..."
17137: *
17138: * SPEC (1) "R's occurrence range is a valid restriction of B's
17139: * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17140: */
17141: if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17142: b->minOccurs, b->maxOccurs))
17143: return (1);
17144:
17145:
17146: return (0);
17147: }
17148:
17149: #endif
17150:
17151: #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17152: xmlSchemaPCustomErrExt(pctxt, \
17153: XML_SCHEMAP_INVALID_FACET_VALUE, \
17154: WXS_BASIC_CAST fac1, fac1->node, \
17155: "It is an error for both '%s' and '%s' to be specified on the "\
17156: "same type definition", \
17157: BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17158: BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17159:
17160: #define FACET_RESTR_ERR(fac1, msg) \
17161: xmlSchemaPCustomErr(pctxt, \
17162: XML_SCHEMAP_INVALID_FACET_VALUE, \
17163: WXS_BASIC_CAST fac1, fac1->node, \
17164: msg, NULL);
17165:
17166: #define FACET_RESTR_FIXED_ERR(fac) \
17167: xmlSchemaPCustomErr(pctxt, \
17168: XML_SCHEMAP_INVALID_FACET_VALUE, \
17169: WXS_BASIC_CAST fac, fac->node, \
17170: "The base type's facet is 'fixed', thus the value must not " \
17171: "differ", NULL);
17172:
17173: static void
17174: xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17175: xmlSchemaFacetPtr facet1,
17176: xmlSchemaFacetPtr facet2,
17177: int lessGreater,
17178: int orEqual,
17179: int ofBase)
17180: {
17181: xmlChar *msg = NULL;
17182:
17183: msg = xmlStrdup(BAD_CAST "'");
17184: msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17185: msg = xmlStrcat(msg, BAD_CAST "' has to be");
17186: if (lessGreater == 0)
17187: msg = xmlStrcat(msg, BAD_CAST " equal to");
17188: if (lessGreater == 1)
17189: msg = xmlStrcat(msg, BAD_CAST " greater than");
17190: else
17191: msg = xmlStrcat(msg, BAD_CAST " less than");
17192:
17193: if (orEqual)
17194: msg = xmlStrcat(msg, BAD_CAST " or equal to");
17195: msg = xmlStrcat(msg, BAD_CAST " '");
17196: msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17197: if (ofBase)
17198: msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17199: else
17200: msg = xmlStrcat(msg, BAD_CAST "'");
17201:
17202: xmlSchemaPCustomErr(pctxt,
17203: XML_SCHEMAP_INVALID_FACET_VALUE,
17204: WXS_BASIC_CAST facet1, NULL,
17205: (const char *) msg, NULL);
17206:
17207: if (msg != NULL)
17208: xmlFree(msg);
17209: }
17210:
17211: /*
17212: * xmlSchemaDeriveAndValidateFacets:
17213: *
17214: * Schema Component Constraint: Simple Type Restriction (Facets)
17215: * (st-restrict-facets)
17216: */
17217: static int
17218: xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17219: xmlSchemaTypePtr type)
17220: {
17221: xmlSchemaTypePtr base = type->baseType;
17222: xmlSchemaFacetLinkPtr link, cur, last = NULL;
17223: xmlSchemaFacetPtr facet, bfacet,
17224: flength = NULL, ftotdig = NULL, ffracdig = NULL,
17225: fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17226: fmininc = NULL, fmaxinc = NULL,
17227: fminexc = NULL, fmaxexc = NULL,
17228: bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17229: bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17230: bfmininc = NULL, bfmaxinc = NULL,
17231: bfminexc = NULL, bfmaxexc = NULL;
17232: int res; /* err = 0, fixedErr; */
17233:
17234: /*
17235: * SPEC st-restrict-facets 1:
17236: * "The {variety} of R is the same as that of B."
17237: */
17238: /*
17239: * SPEC st-restrict-facets 2:
17240: * "If {variety} is atomic, the {primitive type definition}
17241: * of R is the same as that of B."
17242: *
17243: * NOTE: we leave 1 & 2 out for now, since this will be
17244: * satisfied by the derivation process.
17245: * CONSTRUCTION TODO: Maybe needed if using a construction API.
17246: */
17247: /*
17248: * SPEC st-restrict-facets 3:
17249: * "The {facets} of R are the union of S and the {facets}
17250: * of B, eliminating duplicates. To eliminate duplicates,
17251: * when a facet of the same kind occurs in both S and the
17252: * {facets} of B, the one in the {facets} of B is not
17253: * included, with the exception of enumeration and pattern
17254: * facets, for which multiple occurrences with distinct values
17255: * are allowed."
17256: */
17257:
17258: if ((type->facetSet == NULL) && (base->facetSet == NULL))
17259: return (0);
17260:
17261: last = type->facetSet;
17262: if (last != NULL)
17263: while (last->next != NULL)
17264: last = last->next;
17265:
17266: for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17267: facet = cur->facet;
17268: switch (facet->type) {
17269: case XML_SCHEMA_FACET_LENGTH:
17270: flength = facet; break;
17271: case XML_SCHEMA_FACET_MINLENGTH:
17272: fminlen = facet; break;
17273: case XML_SCHEMA_FACET_MININCLUSIVE:
17274: fmininc = facet; break;
17275: case XML_SCHEMA_FACET_MINEXCLUSIVE:
17276: fminexc = facet; break;
17277: case XML_SCHEMA_FACET_MAXLENGTH:
17278: fmaxlen = facet; break;
17279: case XML_SCHEMA_FACET_MAXINCLUSIVE:
17280: fmaxinc = facet; break;
17281: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17282: fmaxexc = facet; break;
17283: case XML_SCHEMA_FACET_TOTALDIGITS:
17284: ftotdig = facet; break;
17285: case XML_SCHEMA_FACET_FRACTIONDIGITS:
17286: ffracdig = facet; break;
17287: default:
17288: break;
17289: }
17290: }
17291: for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17292: facet = cur->facet;
17293: switch (facet->type) {
17294: case XML_SCHEMA_FACET_LENGTH:
17295: bflength = facet; break;
17296: case XML_SCHEMA_FACET_MINLENGTH:
17297: bfminlen = facet; break;
17298: case XML_SCHEMA_FACET_MININCLUSIVE:
17299: bfmininc = facet; break;
17300: case XML_SCHEMA_FACET_MINEXCLUSIVE:
17301: bfminexc = facet; break;
17302: case XML_SCHEMA_FACET_MAXLENGTH:
17303: bfmaxlen = facet; break;
17304: case XML_SCHEMA_FACET_MAXINCLUSIVE:
17305: bfmaxinc = facet; break;
17306: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17307: bfmaxexc = facet; break;
17308: case XML_SCHEMA_FACET_TOTALDIGITS:
17309: bftotdig = facet; break;
17310: case XML_SCHEMA_FACET_FRACTIONDIGITS:
17311: bffracdig = facet; break;
17312: default:
17313: break;
17314: }
17315: }
17316: /*
17317: * length and minLength or maxLength (2.2) + (3.2)
17318: */
17319: if (flength && (fminlen || fmaxlen)) {
17320: FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17321: "either of 'minLength' or 'maxLength' to be specified on "
17322: "the same type definition")
17323: }
17324: /*
17325: * Mutual exclusions in the same derivation step.
17326: */
17327: if ((fmaxinc) && (fmaxexc)) {
17328: /*
17329: * SCC "maxInclusive and maxExclusive"
17330: */
17331: FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17332: }
17333: if ((fmininc) && (fminexc)) {
17334: /*
17335: * SCC "minInclusive and minExclusive"
17336: */
17337: FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17338: }
17339:
17340: if (flength && bflength) {
17341: /*
17342: * SCC "length valid restriction"
17343: * The values have to be equal.
17344: */
17345: res = xmlSchemaCompareValues(flength->val, bflength->val);
17346: if (res == -2)
17347: goto internal_error;
17348: if (res != 0)
17349: xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17350: if ((res != 0) && (bflength->fixed)) {
17351: FACET_RESTR_FIXED_ERR(flength)
17352: }
17353:
17354: }
17355: if (fminlen && bfminlen) {
17356: /*
17357: * SCC "minLength valid restriction"
17358: * minLength >= BASE minLength
17359: */
17360: res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17361: if (res == -2)
17362: goto internal_error;
17363: if (res == -1)
17364: xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17365: if ((res != 0) && (bfminlen->fixed)) {
17366: FACET_RESTR_FIXED_ERR(fminlen)
17367: }
17368: }
17369: if (fmaxlen && bfmaxlen) {
17370: /*
17371: * SCC "maxLength valid restriction"
17372: * maxLength <= BASE minLength
17373: */
17374: res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17375: if (res == -2)
17376: goto internal_error;
17377: if (res == 1)
17378: xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17379: if ((res != 0) && (bfmaxlen->fixed)) {
17380: FACET_RESTR_FIXED_ERR(fmaxlen)
17381: }
17382: }
17383: /*
17384: * SCC "length and minLength or maxLength"
17385: */
17386: if (! flength)
17387: flength = bflength;
17388: if (flength) {
17389: if (! fminlen)
17390: fminlen = bfminlen;
17391: if (fminlen) {
17392: /* (1.1) length >= minLength */
17393: res = xmlSchemaCompareValues(flength->val, fminlen->val);
17394: if (res == -2)
17395: goto internal_error;
17396: if (res == -1)
17397: xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17398: }
17399: if (! fmaxlen)
17400: fmaxlen = bfmaxlen;
17401: if (fmaxlen) {
17402: /* (2.1) length <= maxLength */
17403: res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17404: if (res == -2)
17405: goto internal_error;
17406: if (res == 1)
17407: xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17408: }
17409: }
17410: if (fmaxinc) {
17411: /*
17412: * "maxInclusive"
17413: */
17414: if (fmininc) {
17415: /* SCC "maxInclusive >= minInclusive" */
17416: res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17417: if (res == -2)
17418: goto internal_error;
17419: if (res == -1) {
17420: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17421: }
17422: }
17423: /*
17424: * SCC "maxInclusive valid restriction"
17425: */
17426: if (bfmaxinc) {
17427: /* maxInclusive <= BASE maxInclusive */
17428: res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17429: if (res == -2)
17430: goto internal_error;
17431: if (res == 1)
17432: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17433: if ((res != 0) && (bfmaxinc->fixed)) {
17434: FACET_RESTR_FIXED_ERR(fmaxinc)
17435: }
17436: }
17437: if (bfmaxexc) {
17438: /* maxInclusive < BASE maxExclusive */
17439: res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17440: if (res == -2)
17441: goto internal_error;
17442: if (res != -1) {
17443: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17444: }
17445: }
17446: if (bfmininc) {
17447: /* maxInclusive >= BASE minInclusive */
17448: res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17449: if (res == -2)
17450: goto internal_error;
17451: if (res == -1) {
17452: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17453: }
17454: }
17455: if (bfminexc) {
17456: /* maxInclusive > BASE minExclusive */
17457: res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17458: if (res == -2)
17459: goto internal_error;
17460: if (res != 1) {
17461: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17462: }
17463: }
17464: }
17465: if (fmaxexc) {
17466: /*
17467: * "maxExclusive >= minExclusive"
17468: */
17469: if (fminexc) {
17470: res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17471: if (res == -2)
17472: goto internal_error;
17473: if (res == -1) {
17474: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17475: }
17476: }
17477: /*
17478: * "maxExclusive valid restriction"
17479: */
17480: if (bfmaxexc) {
17481: /* maxExclusive <= BASE maxExclusive */
17482: res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17483: if (res == -2)
17484: goto internal_error;
17485: if (res == 1) {
17486: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17487: }
17488: if ((res != 0) && (bfmaxexc->fixed)) {
17489: FACET_RESTR_FIXED_ERR(fmaxexc)
17490: }
17491: }
17492: if (bfmaxinc) {
17493: /* maxExclusive <= BASE maxInclusive */
17494: res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17495: if (res == -2)
17496: goto internal_error;
17497: if (res == 1) {
17498: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17499: }
17500: }
17501: if (bfmininc) {
17502: /* maxExclusive > BASE minInclusive */
17503: res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17504: if (res == -2)
17505: goto internal_error;
17506: if (res != 1) {
17507: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17508: }
17509: }
17510: if (bfminexc) {
17511: /* maxExclusive > BASE minExclusive */
17512: res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17513: if (res == -2)
17514: goto internal_error;
17515: if (res != 1) {
17516: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17517: }
17518: }
17519: }
17520: if (fminexc) {
17521: /*
17522: * "minExclusive < maxInclusive"
17523: */
17524: if (fmaxinc) {
17525: res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17526: if (res == -2)
17527: goto internal_error;
17528: if (res != -1) {
17529: xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17530: }
17531: }
17532: /*
17533: * "minExclusive valid restriction"
17534: */
17535: if (bfminexc) {
17536: /* minExclusive >= BASE minExclusive */
17537: res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17538: if (res == -2)
17539: goto internal_error;
17540: if (res == -1) {
17541: xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17542: }
17543: if ((res != 0) && (bfminexc->fixed)) {
17544: FACET_RESTR_FIXED_ERR(fminexc)
17545: }
17546: }
17547: if (bfmaxinc) {
17548: /* minExclusive <= BASE maxInclusive */
17549: res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17550: if (res == -2)
17551: goto internal_error;
17552: if (res == 1) {
17553: xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17554: }
17555: }
17556: if (bfmininc) {
17557: /* minExclusive >= BASE minInclusive */
17558: res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17559: if (res == -2)
17560: goto internal_error;
17561: if (res == -1) {
17562: xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17563: }
17564: }
17565: if (bfmaxexc) {
17566: /* minExclusive < BASE maxExclusive */
17567: res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17568: if (res == -2)
17569: goto internal_error;
17570: if (res != -1) {
17571: xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17572: }
17573: }
17574: }
17575: if (fmininc) {
17576: /*
17577: * "minInclusive < maxExclusive"
17578: */
17579: if (fmaxexc) {
17580: res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17581: if (res == -2)
17582: goto internal_error;
17583: if (res != -1) {
17584: xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17585: }
17586: }
17587: /*
17588: * "minExclusive valid restriction"
17589: */
17590: if (bfmininc) {
17591: /* minInclusive >= BASE minInclusive */
17592: res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17593: if (res == -2)
17594: goto internal_error;
17595: if (res == -1) {
17596: xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17597: }
17598: if ((res != 0) && (bfmininc->fixed)) {
17599: FACET_RESTR_FIXED_ERR(fmininc)
17600: }
17601: }
17602: if (bfmaxinc) {
17603: /* minInclusive <= BASE maxInclusive */
17604: res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17605: if (res == -2)
17606: goto internal_error;
17607: if (res == 1) {
17608: xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17609: }
17610: }
17611: if (bfminexc) {
17612: /* minInclusive > BASE minExclusive */
17613: res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17614: if (res == -2)
17615: goto internal_error;
17616: if (res != 1)
17617: xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17618: }
17619: if (bfmaxexc) {
17620: /* minInclusive < BASE maxExclusive */
17621: res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17622: if (res == -2)
17623: goto internal_error;
17624: if (res != -1)
17625: xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17626: }
17627: }
17628: if (ftotdig && bftotdig) {
17629: /*
17630: * SCC " totalDigits valid restriction"
17631: * totalDigits <= BASE totalDigits
17632: */
17633: res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17634: if (res == -2)
17635: goto internal_error;
17636: if (res == 1)
17637: xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17638: -1, 1, 1);
17639: if ((res != 0) && (bftotdig->fixed)) {
17640: FACET_RESTR_FIXED_ERR(ftotdig)
17641: }
17642: }
17643: if (ffracdig && bffracdig) {
17644: /*
17645: * SCC "fractionDigits valid restriction"
17646: * fractionDigits <= BASE fractionDigits
17647: */
17648: res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17649: if (res == -2)
17650: goto internal_error;
17651: if (res == 1)
17652: xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17653: -1, 1, 1);
17654: if ((res != 0) && (bffracdig->fixed)) {
17655: FACET_RESTR_FIXED_ERR(ffracdig)
17656: }
17657: }
17658: /*
17659: * SCC "fractionDigits less than or equal to totalDigits"
17660: */
17661: if (! ftotdig)
17662: ftotdig = bftotdig;
17663: if (! ffracdig)
17664: ffracdig = bffracdig;
17665: if (ftotdig && ffracdig) {
17666: res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17667: if (res == -2)
17668: goto internal_error;
17669: if (res == 1)
17670: xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17671: -1, 1, 0);
17672: }
17673: /*
17674: * *Enumerations* won' be added here, since only the first set
17675: * of enumerations in the ancestor-or-self axis is used
17676: * for validation, plus we need to use the base type of those
17677: * enumerations for whitespace.
17678: *
17679: * *Patterns*: won't be add here, since they are ORed at
17680: * type level and ANDed at ancestor level. This will
17681: * happed during validation by walking the base axis
17682: * of the type.
17683: */
17684: for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17685: bfacet = cur->facet;
17686: /*
17687: * Special handling of enumerations and patterns.
17688: * TODO: hmm, they should not appear in the set, so remove this.
17689: */
17690: if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17691: (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17692: continue;
17693: /*
17694: * Search for a duplicate facet in the current type.
17695: */
17696: link = type->facetSet;
17697: /* err = 0; */
17698: /* fixedErr = 0; */
17699: while (link != NULL) {
17700: facet = link->facet;
17701: if (facet->type == bfacet->type) {
17702: switch (facet->type) {
17703: case XML_SCHEMA_FACET_WHITESPACE:
17704: /*
17705: * The whitespace must be stronger.
17706: */
17707: if (facet->whitespace < bfacet->whitespace) {
17708: FACET_RESTR_ERR(facet,
17709: "The 'whitespace' value has to be equal to "
17710: "or stronger than the 'whitespace' value of "
17711: "the base type")
17712: }
17713: if ((bfacet->fixed) &&
17714: (facet->whitespace != bfacet->whitespace)) {
17715: FACET_RESTR_FIXED_ERR(facet)
17716: }
17717: break;
17718: default:
17719: break;
17720: }
17721: /* Duplicate found. */
17722: break;
17723: }
17724: link = link->next;
17725: }
17726: /*
17727: * If no duplicate was found: add the base types's facet
17728: * to the set.
17729: */
17730: if (link == NULL) {
17731: link = (xmlSchemaFacetLinkPtr)
17732: xmlMalloc(sizeof(xmlSchemaFacetLink));
17733: if (link == NULL) {
17734: xmlSchemaPErrMemory(pctxt,
17735: "deriving facets, creating a facet link", NULL);
17736: return (-1);
17737: }
17738: link->facet = cur->facet;
17739: link->next = NULL;
17740: if (last == NULL)
17741: type->facetSet = link;
17742: else
17743: last->next = link;
17744: last = link;
17745: }
17746:
17747: }
17748:
17749: return (0);
17750: internal_error:
17751: PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17752: "an error occured");
17753: return (-1);
17754: }
17755:
17756: static int
17757: xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17758: xmlSchemaTypePtr type)
17759: {
17760: xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17761: /*
17762: * The actual value is then formed by replacing any union type
17763: * definition in the �explicit members� with the members of their
17764: * {member type definitions}, in order.
17765: *
17766: * TODO: There's a bug entry at
17767: * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17768: * which indicates that we'll keep the union types the future.
17769: */
17770: link = type->memberTypes;
17771: while (link != NULL) {
17772:
17773: if (WXS_IS_TYPE_NOT_FIXED(link->type))
17774: xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17775:
17776: if (WXS_IS_UNION(link->type)) {
17777: subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17778: if (subLink != NULL) {
17779: link->type = subLink->type;
17780: if (subLink->next != NULL) {
17781: lastLink = link->next;
17782: subLink = subLink->next;
17783: prevLink = link;
17784: while (subLink != NULL) {
17785: newLink = (xmlSchemaTypeLinkPtr)
17786: xmlMalloc(sizeof(xmlSchemaTypeLink));
17787: if (newLink == NULL) {
17788: xmlSchemaPErrMemory(pctxt, "allocating a type link",
17789: NULL);
17790: return (-1);
17791: }
17792: newLink->type = subLink->type;
17793: prevLink->next = newLink;
17794: prevLink = newLink;
17795: newLink->next = lastLink;
17796:
17797: subLink = subLink->next;
17798: }
17799: }
17800: }
17801: }
17802: link = link->next;
17803: }
17804: return (0);
17805: }
17806:
17807: static void
17808: xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17809: {
17810: int has = 0, needVal = 0, normVal = 0;
17811:
17812: has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17813: if (has) {
17814: needVal = (type->baseType->flags &
17815: XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17816: normVal = (type->baseType->flags &
17817: XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17818: }
17819: if (type->facets != NULL) {
17820: xmlSchemaFacetPtr fac;
17821:
17822: for (fac = type->facets; fac != NULL; fac = fac->next) {
17823: switch (fac->type) {
17824: case XML_SCHEMA_FACET_WHITESPACE:
17825: break;
17826: case XML_SCHEMA_FACET_PATTERN:
17827: normVal = 1;
17828: has = 1;
17829: break;
17830: case XML_SCHEMA_FACET_ENUMERATION:
17831: needVal = 1;
17832: normVal = 1;
17833: has = 1;
17834: break;
17835: default:
17836: has = 1;
17837: break;
17838: }
17839: }
17840: }
17841: if (normVal)
17842: type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17843: if (needVal)
17844: type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17845: if (has)
17846: type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17847:
17848: if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17849: xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17850: /*
17851: * OPTIMIZE VAL TODO: Some facets need a computed value.
17852: */
17853: if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17854: (prim->builtInType != XML_SCHEMAS_STRING)) {
17855: type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17856: }
17857: }
17858: }
17859:
17860: static int
17861: xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17862: {
17863:
17864:
17865: /*
17866: * Evaluate the whitespace-facet value.
17867: */
17868: if (WXS_IS_LIST(type)) {
17869: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17870: return (0);
17871: } else if (WXS_IS_UNION(type))
17872: return (0);
17873:
17874: if (type->facetSet != NULL) {
17875: xmlSchemaFacetLinkPtr lin;
17876:
17877: for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17878: if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17879: switch (lin->facet->whitespace) {
17880: case XML_SCHEMAS_FACET_PRESERVE:
17881: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17882: break;
17883: case XML_SCHEMAS_FACET_REPLACE:
17884: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17885: break;
17886: case XML_SCHEMAS_FACET_COLLAPSE:
17887: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17888: break;
17889: default:
17890: return (-1);
17891: }
17892: return (0);
17893: }
17894: }
17895: }
17896: /*
17897: * For all �atomic� datatypes other than string (and types �derived�
17898: * by �restriction� from it) the value of whiteSpace is fixed to
17899: * collapse
17900: */
17901: {
17902: xmlSchemaTypePtr anc;
17903:
17904: for (anc = type->baseType; anc != NULL &&
17905: anc->builtInType != XML_SCHEMAS_ANYTYPE;
17906: anc = anc->baseType) {
17907:
17908: if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17909: if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17910: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17911:
17912: } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17913: (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17914: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17915:
17916: } else
17917: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17918: break;
17919: }
17920: }
17921: }
17922: return (0);
17923: }
17924:
17925: static int
17926: xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17927: xmlSchemaTypePtr type)
17928: {
17929: if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17930: return(0);
17931: if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17932: return(0);
17933: type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17934:
17935: if (WXS_IS_LIST(type)) {
17936: /*
17937: * Corresponds to <simpleType><list>...
17938: */
17939: if (type->subtypes == NULL) {
17940: /*
17941: * This one is really needed, so get out.
17942: */
17943: PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17944: "list type has no item-type assigned");
17945: return(-1);
17946: }
17947: } else if (WXS_IS_UNION(type)) {
17948: /*
17949: * Corresponds to <simpleType><union>...
17950: */
17951: if (type->memberTypes == NULL) {
17952: /*
17953: * This one is really needed, so get out.
17954: */
17955: PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17956: "union type has no member-types assigned");
17957: return(-1);
17958: }
17959: } else {
17960: /*
17961: * Corresponds to <simpleType><restriction>...
17962: */
17963: if (type->baseType == NULL) {
17964: PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17965: "type has no base-type assigned");
17966: return(-1);
17967: }
17968: if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17969: if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17970: return(-1);
17971: /*
17972: * Variety
17973: * If the <restriction> alternative is chosen, then the
17974: * {variety} of the {base type definition}.
17975: */
17976: if (WXS_IS_ATOMIC(type->baseType))
17977: type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17978: else if (WXS_IS_LIST(type->baseType)) {
17979: type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17980: /*
17981: * Inherit the itemType.
17982: */
17983: type->subtypes = type->baseType->subtypes;
17984: } else if (WXS_IS_UNION(type->baseType)) {
17985: type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17986: /*
17987: * NOTE that we won't assign the memberTypes of the base,
17988: * since this will make trouble when freeing them; we will
17989: * use a lookup function to access them instead.
17990: */
17991: }
17992: }
17993: return(0);
17994: }
17995:
17996: #ifdef DEBUG_TYPE
17997: static void
17998: xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17999: xmlSchemaTypePtr type)
18000: {
18001: if (type->node != NULL) {
18002: xmlGenericError(xmlGenericErrorContext,
18003: "Type of %s : %s:%d :", name,
18004: type->node->doc->URL,
18005: xmlGetLineNo(type->node));
18006: } else {
18007: xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18008: }
18009: if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18010: switch (type->contentType) {
18011: case XML_SCHEMA_CONTENT_SIMPLE:
18012: xmlGenericError(xmlGenericErrorContext, "simple\n");
18013: break;
18014: case XML_SCHEMA_CONTENT_ELEMENTS:
18015: xmlGenericError(xmlGenericErrorContext, "elements\n");
18016: break;
18017: case XML_SCHEMA_CONTENT_UNKNOWN:
18018: xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18019: break;
18020: case XML_SCHEMA_CONTENT_EMPTY:
18021: xmlGenericError(xmlGenericErrorContext, "empty\n");
18022: break;
18023: case XML_SCHEMA_CONTENT_MIXED:
18024: if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18025: type->subtypes))
18026: xmlGenericError(xmlGenericErrorContext,
18027: "mixed as emptiable particle\n");
18028: else
18029: xmlGenericError(xmlGenericErrorContext, "mixed\n");
18030: break;
18031: /* Removed, since not used. */
18032: /*
18033: case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18034: xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18035: break;
18036: */
18037: case XML_SCHEMA_CONTENT_BASIC:
18038: xmlGenericError(xmlGenericErrorContext, "basic\n");
18039: break;
18040: default:
18041: xmlGenericError(xmlGenericErrorContext,
18042: "not registered !!!\n");
18043: break;
18044: }
18045: }
18046: }
18047: #endif
18048:
18049: /*
18050: * 3.14.6 Constraints on Simple Type Definition Schema Components
18051: */
18052: static int
18053: xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18054: xmlSchemaTypePtr type)
18055: {
18056: int res, olderrs = pctxt->nberrors;
18057:
18058: if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18059: return(-1);
18060:
18061: if (! WXS_IS_TYPE_NOT_FIXED(type))
18062: return(0);
18063:
18064: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18065: type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18066:
18067: if (type->baseType == NULL) {
18068: PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18069: "missing baseType");
18070: goto exit_failure;
18071: }
18072: if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18073: xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18074: /*
18075: * If a member type of a union is a union itself, we need to substitute
18076: * that member type for its member types.
18077: * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18078: * types in WXS 1.1.
18079: */
18080: if ((type->memberTypes != NULL) &&
18081: (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18082: return(-1);
18083: /*
18084: * SPEC src-simple-type 1
18085: * "The corresponding simple type definition, if any, must satisfy
18086: * the conditions set out in Constraints on Simple Type Definition
18087: * Schema Components (�3.14.6)."
18088: */
18089: /*
18090: * Schema Component Constraint: Simple Type Definition Properties Correct
18091: * (st-props-correct)
18092: */
18093: res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18094: HFAILURE HERROR
18095: /*
18096: * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18097: * (cos-st-restricts)
18098: */
18099: res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18100: HFAILURE HERROR
18101: /*
18102: * TODO: Removed the error report, since it got annoying to get an
18103: * extra error report, if anything failed until now.
18104: * Enable this if needed.
18105: *
18106: * xmlSchemaPErr(ctxt, type->node,
18107: * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18108: * "Simple type '%s' does not satisfy the constraints "
18109: * "on simple type definitions.\n",
18110: * type->name, NULL);
18111: */
18112: /*
18113: * Schema Component Constraint: Simple Type Restriction (Facets)
18114: * (st-restrict-facets)
18115: */
18116: res = xmlSchemaCheckFacetValues(type, pctxt);
18117: HFAILURE HERROR
18118: if ((type->facetSet != NULL) ||
18119: (type->baseType->facetSet != NULL)) {
18120: res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18121: HFAILURE HERROR
18122: }
18123: /*
18124: * Whitespace value.
18125: */
18126: res = xmlSchemaTypeFixupWhitespace(type);
18127: HFAILURE HERROR
18128: xmlSchemaTypeFixupOptimFacets(type);
18129:
18130: exit_error:
18131: #ifdef DEBUG_TYPE
18132: xmlSchemaDebugFixedType(pctxt, type);
18133: #endif
18134: if (olderrs != pctxt->nberrors)
18135: return(pctxt->err);
18136: return(0);
18137:
18138: exit_failure:
18139: #ifdef DEBUG_TYPE
18140: xmlSchemaDebugFixedType(pctxt, type);
18141: #endif
18142: return(-1);
18143: }
18144:
18145: static int
18146: xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18147: xmlSchemaTypePtr type)
18148: {
18149: int res = 0, olderrs = pctxt->nberrors;
18150: xmlSchemaTypePtr baseType = type->baseType;
18151:
18152: if (! WXS_IS_TYPE_NOT_FIXED(type))
18153: return(0);
18154: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18155: if (baseType == NULL) {
18156: PERROR_INT("xmlSchemaFixupComplexType",
18157: "missing baseType");
18158: goto exit_failure;
18159: }
18160: /*
18161: * Fixup the base type.
18162: */
18163: if (WXS_IS_TYPE_NOT_FIXED(baseType))
18164: xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18165: if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18166: /*
18167: * Skip fixup if the base type is invalid.
18168: * TODO: Generate a warning!
18169: */
18170: return(0);
18171: }
18172: /*
18173: * This basically checks if the base type can be derived.
18174: */
18175: res = xmlSchemaCheckSRCCT(pctxt, type);
18176: HFAILURE HERROR
18177: /*
18178: * Fixup the content type.
18179: */
18180: if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18181: /*
18182: * Corresponds to <complexType><simpleContent>...
18183: */
18184: if ((WXS_IS_COMPLEX(baseType)) &&
18185: (baseType->contentTypeDef != NULL) &&
18186: (WXS_IS_RESTRICTION(type))) {
18187: xmlSchemaTypePtr contentBase, content;
18188: #ifdef ENABLE_NAMED_LOCALS
18189: char buf[30];
18190: const xmlChar *tmpname;
18191: #endif
18192: /*
18193: * SPEC (1) If <restriction> + base type is <complexType>,
18194: * "whose own {content type} is a simple type..."
18195: */
18196: if (type->contentTypeDef != NULL) {
18197: /*
18198: * SPEC (1.1) "the simple type definition corresponding to the
18199: * <simpleType> among the [children] of <restriction> if there
18200: * is one;"
18201: * Note that this "<simpleType> among the [children]" was put
18202: * into ->contentTypeDef during parsing.
18203: */
18204: contentBase = type->contentTypeDef;
18205: type->contentTypeDef = NULL;
18206: } else {
18207: /*
18208: * (1.2) "...otherwise (<restriction> has no <simpleType>
18209: * among its [children]), the simple type definition which
18210: * is the {content type} of the ... base type."
18211: */
18212: contentBase = baseType->contentTypeDef;
18213: }
18214: /*
18215: * SPEC
18216: * "... a simple type definition which restricts the simple
18217: * type definition identified in clause 1.1 or clause 1.2
18218: * with a set of facet components"
18219: *
18220: * Create the anonymous simple type, which will be the content
18221: * type of the complex type.
18222: */
18223: #ifdef ENABLE_NAMED_LOCALS
18224: snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18225: tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18226: content = xmlSchemaAddType(pctxt, pctxt->schema,
18227: XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18228: type->node, 0);
18229: #else
18230: content = xmlSchemaAddType(pctxt, pctxt->schema,
18231: XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18232: type->node, 0);
18233: #endif
18234: if (content == NULL)
18235: goto exit_failure;
18236: /*
18237: * We will use the same node as for the <complexType>
18238: * to have it somehow anchored in the schema doc.
18239: */
18240: content->type = XML_SCHEMA_TYPE_SIMPLE;
18241: content->baseType = contentBase;
18242: /*
18243: * Move the facets, previously anchored on the
18244: * complexType during parsing.
18245: */
18246: content->facets = type->facets;
18247: type->facets = NULL;
18248: content->facetSet = type->facetSet;
18249: type->facetSet = NULL;
18250:
18251: type->contentTypeDef = content;
18252: if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18253: xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18254: /*
18255: * Fixup the newly created type. We don't need to check
18256: * for circularity here.
18257: */
18258: res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18259: HFAILURE HERROR
18260: res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18261: HFAILURE HERROR
18262:
18263: } else if ((WXS_IS_COMPLEX(baseType)) &&
18264: (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18265: (WXS_IS_RESTRICTION(type))) {
18266: /*
18267: * SPEC (2) If <restriction> + base is a mixed <complexType> with
18268: * an emptiable particle, then a simple type definition which
18269: * restricts the <restriction>'s <simpleType> child.
18270: */
18271: if ((type->contentTypeDef == NULL) ||
18272: (type->contentTypeDef->baseType == NULL)) {
18273: /*
18274: * TODO: Check if this ever happens.
18275: */
18276: xmlSchemaPCustomErr(pctxt,
18277: XML_SCHEMAP_INTERNAL,
18278: WXS_BASIC_CAST type, NULL,
18279: "Internal error: xmlSchemaTypeFixup, "
18280: "complex type '%s': the <simpleContent><restriction> "
18281: "is missing a <simpleType> child, but was not catched "
18282: "by xmlSchemaCheckSRCCT()", type->name);
18283: goto exit_failure;
18284: }
18285: } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18286: /*
18287: * SPEC (3) If <extension> + base is <complexType> with
18288: * <simpleType> content, "...then the {content type} of that
18289: * complex type definition"
18290: */
18291: if (baseType->contentTypeDef == NULL) {
18292: /*
18293: * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18294: * should have catched this already.
18295: */
18296: xmlSchemaPCustomErr(pctxt,
18297: XML_SCHEMAP_INTERNAL,
18298: WXS_BASIC_CAST type, NULL,
18299: "Internal error: xmlSchemaTypeFixup, "
18300: "complex type '%s': the <extension>ed base type is "
18301: "a complex type with no simple content type",
18302: type->name);
18303: goto exit_failure;
18304: }
18305: type->contentTypeDef = baseType->contentTypeDef;
18306: } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18307: /*
18308: * SPEC (4) <extension> + base is <simpleType>
18309: * "... then that simple type definition"
18310: */
18311: type->contentTypeDef = baseType;
18312: } else {
18313: /*
18314: * TODO: Check if this ever happens.
18315: */
18316: xmlSchemaPCustomErr(pctxt,
18317: XML_SCHEMAP_INTERNAL,
18318: WXS_BASIC_CAST type, NULL,
18319: "Internal error: xmlSchemaTypeFixup, "
18320: "complex type '%s' with <simpleContent>: unhandled "
18321: "derivation case", type->name);
18322: goto exit_failure;
18323: }
18324: } else {
18325: int dummySequence = 0;
18326: xmlSchemaParticlePtr particle =
18327: (xmlSchemaParticlePtr) type->subtypes;
18328: /*
18329: * Corresponds to <complexType><complexContent>...
18330: *
18331: * NOTE that the effective mixed was already set during parsing of
18332: * <complexType> and <complexContent>; its flag value is
18333: * XML_SCHEMAS_TYPE_MIXED.
18334: *
18335: * Compute the "effective content":
18336: * (2.1.1) + (2.1.2) + (2.1.3)
18337: */
18338: if ((particle == NULL) ||
18339: ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18340: ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18341: (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18342: ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18343: (particle->minOccurs == 0))) &&
18344: ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18345: if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18346: /*
18347: * SPEC (2.1.4) "If the �effective mixed� is true, then
18348: * a particle whose properties are as follows:..."
18349: *
18350: * Empty sequence model group with
18351: * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18352: * NOTE that we sill assign it the <complexType> node to
18353: * somehow anchor it in the doc.
18354: */
18355: if ((particle == NULL) ||
18356: (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18357: /*
18358: * Create the particle.
18359: */
18360: particle = xmlSchemaAddParticle(pctxt,
18361: type->node, 1, 1);
18362: if (particle == NULL)
18363: goto exit_failure;
18364: /*
18365: * Create the model group.
18366: */ /* URGENT TODO: avoid adding to pending items. */
18367: particle->children = (xmlSchemaTreeItemPtr)
18368: xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18369: XML_SCHEMA_TYPE_SEQUENCE, type->node);
18370: if (particle->children == NULL)
18371: goto exit_failure;
18372:
18373: type->subtypes = (xmlSchemaTypePtr) particle;
18374: }
18375: dummySequence = 1;
18376: type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18377: } else {
18378: /*
18379: * SPEC (2.1.5) "otherwise empty"
18380: */
18381: type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18382: }
18383: } else {
18384: /*
18385: * SPEC (2.2) "otherwise the particle corresponding to the
18386: * <all>, <choice>, <group> or <sequence> among the
18387: * [children]."
18388: */
18389: type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18390: }
18391: /*
18392: * Compute the "content type".
18393: */
18394: if (WXS_IS_RESTRICTION(type)) {
18395: /*
18396: * SPEC (3.1) "If <restriction>..."
18397: * (3.1.1) + (3.1.2) */
18398: if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18399: if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18400: type->contentType = XML_SCHEMA_CONTENT_MIXED;
18401: }
18402: } else {
18403: /*
18404: * SPEC (3.2) "If <extension>..."
18405: */
18406: if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18407: /*
18408: * SPEC (3.2.1)
18409: * "If the �effective content� is empty, then the
18410: * {content type} of the [...] base ..."
18411: */
18412: type->contentType = baseType->contentType;
18413: type->subtypes = baseType->subtypes;
18414: /*
18415: * Fixes bug #347316:
18416: * This is the case when the base type has a simple
18417: * type definition as content.
18418: */
18419: type->contentTypeDef = baseType->contentTypeDef;
18420: /*
18421: * NOTE that the effective mixed is ignored here.
18422: */
18423: } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18424: /*
18425: * SPEC (3.2.2)
18426: */
18427: if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18428: type->contentType = XML_SCHEMA_CONTENT_MIXED;
18429: } else {
18430: /*
18431: * SPEC (3.2.3)
18432: */
18433: if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18434: type->contentType = XML_SCHEMA_CONTENT_MIXED;
18435: /*
18436: * "A model group whose {compositor} is sequence and whose
18437: * {particles} are..."
18438: */
18439: if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18440: (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18441: ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18442: XML_SCHEMA_TYPE_ALL))
18443: {
18444: /*
18445: * SPEC cos-all-limited (1)
18446: */
18447: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18448: /* TODO: error code */
18449: XML_SCHEMAP_COS_ALL_LIMITED,
18450: WXS_ITEM_NODE(type), NULL,
18451: "The type has an 'all' model group in its "
18452: "{content type} and thus cannot be derived from "
18453: "a non-empty type, since this would produce a "
18454: "'sequence' model group containing the 'all' "
18455: "model group; 'all' model groups are not "
18456: "allowed to appear inside other model groups",
18457: NULL, NULL);
18458:
18459: } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18460: (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18461: ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18462: XML_SCHEMA_TYPE_ALL))
18463: {
18464: /*
18465: * SPEC cos-all-limited (1)
18466: */
18467: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18468: /* TODO: error code */
18469: XML_SCHEMAP_COS_ALL_LIMITED,
18470: WXS_ITEM_NODE(type), NULL,
18471: "A type cannot be derived by extension from a type "
18472: "which has an 'all' model group in its "
18473: "{content type}, since this would produce a "
18474: "'sequence' model group containing the 'all' "
18475: "model group; 'all' model groups are not "
18476: "allowed to appear inside other model groups",
18477: NULL, NULL);
18478:
18479: } else if (! dummySequence) {
18480: xmlSchemaTreeItemPtr effectiveContent =
18481: (xmlSchemaTreeItemPtr) type->subtypes;
18482: /*
18483: * Create the particle.
18484: */
18485: particle = xmlSchemaAddParticle(pctxt,
18486: type->node, 1, 1);
18487: if (particle == NULL)
18488: goto exit_failure;
18489: /*
18490: * Create the "sequence" model group.
18491: */
18492: particle->children = (xmlSchemaTreeItemPtr)
18493: xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18494: XML_SCHEMA_TYPE_SEQUENCE, type->node);
18495: if (particle->children == NULL)
18496: goto exit_failure;
18497: WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18498: /*
18499: * SPEC "the particle of the {content type} of
18500: * the ... base ..."
18501: * Create a duplicate of the base type's particle
18502: * and assign its "term" to it.
18503: */
18504: particle->children->children =
18505: (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18506: type->node,
1.1.1.2 misho 18507: ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18508: ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
1.1 misho 18509: if (particle->children->children == NULL)
18510: goto exit_failure;
18511: particle = (xmlSchemaParticlePtr)
18512: particle->children->children;
18513: particle->children =
18514: ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18515: /*
18516: * SPEC "followed by the �effective content�."
18517: */
18518: particle->next = effectiveContent;
18519: /*
18520: * This all will result in:
18521: * new-particle
18522: * --> new-sequence(
18523: * new-particle
18524: * --> base-model,
18525: * this-particle
18526: * --> this-model
18527: * )
18528: */
18529: } else {
18530: /*
18531: * This is the case when there is already an empty
18532: * <sequence> with minOccurs==maxOccurs==1.
18533: * Just add the base types's content type.
18534: * NOTE that, although we miss to add an intermediate
18535: * <sequence>, this should produce no difference to
18536: * neither the regex compilation of the content model,
18537: * nor to the complex type contraints.
18538: */
18539: particle->children->children =
18540: (xmlSchemaTreeItemPtr) baseType->subtypes;
18541: }
18542: }
18543: }
18544: }
18545: /*
18546: * Now fixup attribute uses:
18547: * - expand attr. group references
18548: * - intersect attribute wildcards
18549: * - inherit attribute uses of the base type
18550: * - inherit or union attr. wildcards if extending
18551: * - apply attr. use prohibitions if restricting
18552: */
18553: res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18554: HFAILURE HERROR
18555: /*
18556: * Apply the complex type component constraints; this will not
18557: * check attributes, since this is done in
18558: * xmlSchemaFixupTypeAttributeUses().
18559: */
18560: res = xmlSchemaCheckCTComponent(pctxt, type);
18561: HFAILURE HERROR
18562:
18563: #ifdef DEBUG_TYPE
18564: xmlSchemaDebugFixedType(pctxt, type);
18565: #endif
18566: if (olderrs != pctxt->nberrors)
18567: return(pctxt->err);
18568: else
18569: return(0);
18570:
18571: exit_error:
18572: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18573: #ifdef DEBUG_TYPE
18574: xmlSchemaDebugFixedType(pctxt, type);
18575: #endif
18576: return(pctxt->err);
18577:
18578: exit_failure:
18579: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18580: #ifdef DEBUG_TYPE
18581: xmlSchemaDebugFixedType(pctxt, type);
18582: #endif
18583: return(-1);
18584: }
18585:
18586:
18587: /**
18588: * xmlSchemaTypeFixup:
18589: * @typeDecl: the schema type definition
18590: * @ctxt: the schema parser context
18591: *
18592: * Fixes the content model of the type.
18593: * URGENT TODO: We need an int result!
18594: */
18595: static int
18596: xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18597: xmlSchemaAbstractCtxtPtr actxt)
18598: {
18599: if (type == NULL)
18600: return(0);
18601: if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18602: AERROR_INT("xmlSchemaTypeFixup",
18603: "this function needs a parser context");
18604: return(-1);
18605: }
18606: if (! WXS_IS_TYPE_NOT_FIXED(type))
18607: return(0);
18608: if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18609: return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18610: else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18611: return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18612: return(0);
18613: }
18614:
18615: /**
18616: * xmlSchemaCheckFacet:
18617: * @facet: the facet
18618: * @typeDecl: the schema type definition
18619: * @pctxt: the schema parser context or NULL
18620: * @name: the optional name of the type
18621: *
18622: * Checks and computes the values of facets.
18623: *
18624: * Returns 0 if valid, a positive error code if not valid and
18625: * -1 in case of an internal or API error.
18626: */
18627: int
18628: xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18629: xmlSchemaTypePtr typeDecl,
18630: xmlSchemaParserCtxtPtr pctxt,
18631: const xmlChar * name ATTRIBUTE_UNUSED)
18632: {
18633: int ret = 0, ctxtGiven;
18634:
18635: if ((facet == NULL) || (typeDecl == NULL))
18636: return(-1);
18637: /*
18638: * TODO: will the parser context be given if used from
18639: * the relaxNG module?
18640: */
18641: if (pctxt == NULL)
18642: ctxtGiven = 0;
18643: else
18644: ctxtGiven = 1;
18645:
18646: switch (facet->type) {
18647: case XML_SCHEMA_FACET_MININCLUSIVE:
18648: case XML_SCHEMA_FACET_MINEXCLUSIVE:
18649: case XML_SCHEMA_FACET_MAXINCLUSIVE:
18650: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18651: case XML_SCHEMA_FACET_ENUMERATION: {
18652: /*
18653: * Okay we need to validate the value
18654: * at that point.
18655: */
18656: xmlSchemaTypePtr base;
18657:
18658: /* 4.3.5.5 Constraints on enumeration Schema Components
18659: * Schema Component Constraint: enumeration valid restriction
18660: * It is an �error� if any member of {value} is not in the
18661: * �value space� of {base type definition}.
18662: *
18663: * minInclusive, maxInclusive, minExclusive, maxExclusive:
18664: * The value �must� be in the
18665: * �value space� of the �base type�.
18666: */
18667: /*
18668: * This function is intended to deliver a compiled value
18669: * on the facet. In this implementation of XML Schemata the
18670: * type holding a facet, won't be a built-in type.
18671: * Thus to ensure that other API
18672: * calls (relaxng) do work, if the given type is a built-in
18673: * type, we will assume that the given built-in type *is
18674: * already* the base type.
18675: */
18676: if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18677: base = typeDecl->baseType;
18678: if (base == NULL) {
18679: PERROR_INT("xmlSchemaCheckFacet",
18680: "a type user derived type has no base type");
18681: return (-1);
18682: }
18683: } else
18684: base = typeDecl;
18685:
18686: if (! ctxtGiven) {
18687: /*
18688: * A context is needed if called from RelaxNG.
18689: */
18690: pctxt = xmlSchemaNewParserCtxt("*");
18691: if (pctxt == NULL)
18692: return (-1);
18693: }
18694: /*
18695: * NOTE: This call does not check the content nodes,
18696: * since they are not available:
18697: * facet->node is just the node holding the facet
18698: * definition, *not* the attribute holding the *value*
18699: * of the facet.
18700: */
18701: ret = xmlSchemaVCheckCVCSimpleType(
18702: ACTXT_CAST pctxt, facet->node, base,
18703: facet->value, &(facet->val), 1, 1, 0);
18704: if (ret != 0) {
18705: if (ret < 0) {
18706: /* No error message for RelaxNG. */
18707: if (ctxtGiven) {
18708: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18709: XML_SCHEMAP_INTERNAL, facet->node, NULL,
18710: "Internal error: xmlSchemaCheckFacet, "
18711: "failed to validate the value '%s' of the "
18712: "facet '%s' against the base type",
18713: facet->value, xmlSchemaFacetTypeToString(facet->type));
18714: }
18715: goto internal_error;
18716: }
18717: ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18718: /* No error message for RelaxNG. */
18719: if (ctxtGiven) {
18720: xmlChar *str = NULL;
18721:
18722: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18723: ret, facet->node, WXS_BASIC_CAST facet,
18724: "The value '%s' of the facet does not validate "
18725: "against the base type '%s'",
18726: facet->value,
18727: xmlSchemaFormatQName(&str,
18728: base->targetNamespace, base->name));
18729: FREE_AND_NULL(str);
18730: }
18731: goto exit;
18732: } else if (facet->val == NULL) {
18733: if (ctxtGiven) {
18734: PERROR_INT("xmlSchemaCheckFacet",
18735: "value was not computed");
18736: }
18737: TODO
18738: }
18739: break;
18740: }
18741: case XML_SCHEMA_FACET_PATTERN:
18742: facet->regexp = xmlRegexpCompile(facet->value);
18743: if (facet->regexp == NULL) {
18744: ret = XML_SCHEMAP_REGEXP_INVALID;
18745: /* No error message for RelaxNG. */
18746: if (ctxtGiven) {
18747: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18748: ret, facet->node, WXS_BASIC_CAST typeDecl,
18749: "The value '%s' of the facet 'pattern' is not a "
18750: "valid regular expression",
18751: facet->value, NULL);
18752: }
18753: }
18754: break;
18755: case XML_SCHEMA_FACET_TOTALDIGITS:
18756: case XML_SCHEMA_FACET_FRACTIONDIGITS:
18757: case XML_SCHEMA_FACET_LENGTH:
18758: case XML_SCHEMA_FACET_MAXLENGTH:
18759: case XML_SCHEMA_FACET_MINLENGTH:
18760:
18761: if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18762: ret = xmlSchemaValidatePredefinedType(
18763: xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18764: facet->value, &(facet->val));
18765: } else {
18766: ret = xmlSchemaValidatePredefinedType(
18767: xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18768: facet->value, &(facet->val));
18769: }
18770: if (ret != 0) {
18771: if (ret < 0) {
18772: /* No error message for RelaxNG. */
18773: if (ctxtGiven) {
18774: PERROR_INT("xmlSchemaCheckFacet",
18775: "validating facet value");
18776: }
18777: goto internal_error;
18778: }
18779: ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18780: /* No error message for RelaxNG. */
18781: if (ctxtGiven) {
18782: /* error code */
18783: xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18784: ret, facet->node, WXS_BASIC_CAST typeDecl,
18785: "The value '%s' of the facet '%s' is not a valid '%s'",
18786: facet->value,
18787: xmlSchemaFacetTypeToString(facet->type),
18788: (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18789: BAD_CAST "nonNegativeInteger" :
18790: BAD_CAST "positiveInteger",
18791: NULL);
18792: }
18793: }
18794: break;
18795:
18796: case XML_SCHEMA_FACET_WHITESPACE:{
18797: if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18798: facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18799: } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18800: facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18801: } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18802: facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18803: } else {
18804: ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18805: /* No error message for RelaxNG. */
18806: if (ctxtGiven) {
18807: /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18808: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18809: ret, facet->node, WXS_BASIC_CAST typeDecl,
18810: "The value '%s' of the facet 'whitespace' is not "
18811: "valid", facet->value, NULL);
18812: }
18813: }
18814: }
18815: default:
18816: break;
18817: }
18818: exit:
18819: if ((! ctxtGiven) && (pctxt != NULL))
18820: xmlSchemaFreeParserCtxt(pctxt);
18821: return (ret);
18822: internal_error:
18823: if ((! ctxtGiven) && (pctxt != NULL))
18824: xmlSchemaFreeParserCtxt(pctxt);
18825: return (-1);
18826: }
18827:
18828: /**
18829: * xmlSchemaCheckFacetValues:
18830: * @typeDecl: the schema type definition
18831: * @ctxt: the schema parser context
18832: *
18833: * Checks the default values types, especially for facets
18834: */
18835: static int
18836: xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18837: xmlSchemaParserCtxtPtr pctxt)
18838: {
18839: int res, olderrs = pctxt->nberrors;
18840: const xmlChar *name = typeDecl->name;
18841: /*
18842: * NOTE: It is intended to use the facets list, instead
18843: * of facetSet.
18844: */
18845: if (typeDecl->facets != NULL) {
18846: xmlSchemaFacetPtr facet = typeDecl->facets;
18847:
18848: /*
18849: * Temporarily assign the "schema" to the validation context
18850: * of the parser context. This is needed for NOTATION validation.
18851: */
18852: if (pctxt->vctxt == NULL) {
18853: if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18854: return(-1);
18855: }
18856: pctxt->vctxt->schema = pctxt->schema;
18857: while (facet != NULL) {
18858: res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18859: HFAILURE
18860: facet = facet->next;
18861: }
18862: pctxt->vctxt->schema = NULL;
18863: }
18864: if (olderrs != pctxt->nberrors)
18865: return(pctxt->err);
18866: return(0);
18867: exit_failure:
18868: return(-1);
18869: }
18870:
18871: /**
18872: * xmlSchemaGetCircModelGrDefRef:
18873: * @ctxtMGroup: the searched model group
18874: * @selfMGroup: the second searched model group
18875: * @particle: the first particle
18876: *
18877: * This one is intended to be used by
18878: * xmlSchemaCheckGroupDefCircular only.
18879: *
18880: * Returns the particle with the circular model group definition reference,
18881: * otherwise NULL.
18882: */
18883: static xmlSchemaTreeItemPtr
18884: xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18885: xmlSchemaTreeItemPtr particle)
18886: {
18887: xmlSchemaTreeItemPtr circ = NULL;
18888: xmlSchemaTreeItemPtr term;
18889: xmlSchemaModelGroupDefPtr gdef;
18890:
18891: for (; particle != NULL; particle = particle->next) {
18892: term = particle->children;
18893: if (term == NULL)
18894: continue;
18895: switch (term->type) {
18896: case XML_SCHEMA_TYPE_GROUP:
18897: gdef = (xmlSchemaModelGroupDefPtr) term;
18898: if (gdef == groupDef)
18899: return (particle);
18900: /*
18901: * Mark this model group definition to avoid infinite
18902: * recursion on circular references not yet examined.
18903: */
18904: if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18905: continue;
18906: if (gdef->children != NULL) {
18907: gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18908: circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18909: gdef->children->children);
18910: gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18911: if (circ != NULL)
18912: return (circ);
18913: }
18914: break;
18915: case XML_SCHEMA_TYPE_SEQUENCE:
18916: case XML_SCHEMA_TYPE_CHOICE:
18917: case XML_SCHEMA_TYPE_ALL:
18918: circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18919: if (circ != NULL)
18920: return (circ);
18921: break;
18922: default:
18923: break;
18924: }
18925: }
18926: return (NULL);
18927: }
18928:
18929: /**
18930: * xmlSchemaCheckGroupDefCircular:
18931: * @item: the model group definition
18932: * @ctxt: the parser context
18933: * @name: the name
18934: *
18935: * Checks for circular references to model group definitions.
18936: */
18937: static void
18938: xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18939: xmlSchemaParserCtxtPtr ctxt)
18940: {
18941: /*
18942: * Schema Component Constraint: Model Group Correct
18943: * 2 Circular groups are disallowed. That is, within the {particles}
18944: * of a group there must not be at any depth a particle whose {term}
18945: * is the group itself.
18946: */
18947: if ((item == NULL) ||
18948: (item->type != XML_SCHEMA_TYPE_GROUP) ||
18949: (item->children == NULL))
18950: return;
18951: {
18952: xmlSchemaTreeItemPtr circ;
18953:
18954: circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18955: if (circ != NULL) {
18956: xmlChar *str = NULL;
18957: /*
18958: * TODO: The error report is not adequate: this constraint
18959: * is defined for model groups but not definitions, but since
18960: * there cannot be any circular model groups without a model group
18961: * definition (if not using a construction API), we check those
18962: * defintions only.
18963: */
18964: xmlSchemaPCustomErr(ctxt,
18965: XML_SCHEMAP_MG_PROPS_CORRECT_2,
18966: NULL, WXS_ITEM_NODE(circ),
18967: "Circular reference to the model group definition '%s' "
18968: "defined", xmlSchemaFormatQName(&str,
18969: item->targetNamespace, item->name));
18970: FREE_AND_NULL(str)
18971: /*
18972: * NOTE: We will cut the reference to avoid further
18973: * confusion of the processor. This is a fatal error.
18974: */
18975: circ->children = NULL;
18976: }
18977: }
18978: }
18979:
18980: /**
18981: * xmlSchemaModelGroupToModelGroupDefFixup:
18982: * @ctxt: the parser context
18983: * @mg: the model group
18984: *
18985: * Assigns the model group of model group definitions to the "term"
18986: * of the referencing particle.
18987: * In xmlSchemaResolveModelGroupParticleReferences the model group
18988: * definitions were assigned to the "term", since needed for the
18989: * circularity check.
18990: *
18991: * Schema Component Constraint:
18992: * All Group Limited (cos-all-limited) (1.2)
18993: */
18994: static void
18995: xmlSchemaModelGroupToModelGroupDefFixup(
18996: xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18997: xmlSchemaModelGroupPtr mg)
18998: {
18999: xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19000:
19001: while (particle != NULL) {
19002: if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19003: ((WXS_PARTICLE_TERM(particle))->type !=
19004: XML_SCHEMA_TYPE_GROUP))
19005: {
19006: particle = WXS_PTC_CAST particle->next;
19007: continue;
19008: }
19009: if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19010: /*
19011: * TODO: Remove the particle.
19012: */
19013: WXS_PARTICLE_TERM(particle) = NULL;
19014: particle = WXS_PTC_CAST particle->next;
19015: continue;
19016: }
19017: /*
19018: * Assign the model group to the {term} of the particle.
19019: */
19020: WXS_PARTICLE_TERM(particle) =
19021: WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19022:
19023: particle = WXS_PTC_CAST particle->next;
19024: }
19025: }
19026:
19027: /**
19028: * xmlSchemaCheckAttrGroupCircularRecur:
19029: * @ctxtGr: the searched attribute group
19030: * @attr: the current attribute list to be processed
19031: *
19032: * This one is intended to be used by
19033: * xmlSchemaCheckAttrGroupCircular only.
19034: *
19035: * Returns the circular attribute grou reference, otherwise NULL.
19036: */
19037: static xmlSchemaQNameRefPtr
19038: xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19039: xmlSchemaItemListPtr list)
19040: {
19041: xmlSchemaAttributeGroupPtr gr;
19042: xmlSchemaQNameRefPtr ref, circ;
19043: int i;
19044: /*
19045: * We will search for an attribute group reference which
19046: * references the context attribute group.
19047: */
19048: for (i = 0; i < list->nbItems; i++) {
19049: ref = list->items[i];
19050: if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19051: (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19052: (ref->item != NULL))
19053: {
19054: gr = WXS_ATTR_GROUP_CAST ref->item;
19055: if (gr == ctxtGr)
19056: return(ref);
19057: if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19058: continue;
19059: /*
19060: * Mark as visited to avoid infinite recursion on
19061: * circular references not yet examined.
19062: */
19063: if ((gr->attrUses) &&
19064: (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19065: {
19066: gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19067: circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19068: (xmlSchemaItemListPtr) gr->attrUses);
19069: gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19070: if (circ != NULL)
19071: return (circ);
19072: }
19073:
19074: }
19075: }
19076: return (NULL);
19077: }
19078:
19079: /**
19080: * xmlSchemaCheckAttrGroupCircular:
19081: * attrGr: the attribute group definition
19082: * @ctxt: the parser context
19083: * @name: the name
19084: *
19085: * Checks for circular references of attribute groups.
19086: */
19087: static int
19088: xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19089: xmlSchemaParserCtxtPtr ctxt)
19090: {
19091: /*
19092: * Schema Representation Constraint:
19093: * Attribute Group Definition Representation OK
19094: * 3 Circular group reference is disallowed outside <redefine>.
19095: * That is, unless this element information item's parent is
19096: * <redefine>, then among the [children], if any, there must
19097: * not be an <attributeGroup> with ref [attribute] which resolves
19098: * to the component corresponding to this <attributeGroup>. Indirect
19099: * circularity is also ruled out. That is, when QName resolution
19100: * (Schema Document) (�3.15.3) is applied to a �QName� arising from
19101: * any <attributeGroup>s with a ref [attribute] among the [children],
19102: * it must not be the case that a �QName� is encountered at any depth
19103: * which resolves to the component corresponding to this <attributeGroup>.
19104: */
19105: if (attrGr->attrUses == NULL)
19106: return(0);
19107: else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19108: return(0);
19109: else {
19110: xmlSchemaQNameRefPtr circ;
19111:
19112: circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19113: (xmlSchemaItemListPtr) attrGr->attrUses);
19114: if (circ != NULL) {
19115: xmlChar *str = NULL;
19116: /*
19117: * TODO: Report the referenced attr group as QName.
19118: */
19119: xmlSchemaPCustomErr(ctxt,
19120: XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19121: NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19122: "Circular reference to the attribute group '%s' "
19123: "defined", xmlSchemaGetComponentQName(&str, attrGr));
19124: FREE_AND_NULL(str);
19125: /*
19126: * NOTE: We will cut the reference to avoid further
19127: * confusion of the processor.
19128: * BADSPEC TODO: The spec should define how to process in this case.
19129: */
19130: circ->item = NULL;
19131: return(ctxt->err);
19132: }
19133: }
19134: return(0);
19135: }
19136:
19137: static int
19138: xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19139: xmlSchemaAttributeGroupPtr attrGr);
19140:
19141: /**
19142: * xmlSchemaExpandAttributeGroupRefs:
19143: * @pctxt: the parser context
19144: * @node: the node of the component holding the attribute uses
19145: * @completeWild: the intersected wildcard to be returned
19146: * @list: the attribute uses
19147: *
19148: * Substitutes contained attribute group references
19149: * for their attribute uses. Wilcards are intersected.
19150: * Attribute use prohibitions are removed from the list
19151: * and returned via the @prohibs list.
19152: * Pointlessness of attr. prohibs, if a matching attr. decl
19153: * is existent a well, are checked.
19154: */
19155: static int
19156: xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19157: xmlSchemaBasicItemPtr item,
19158: xmlSchemaWildcardPtr *completeWild,
19159: xmlSchemaItemListPtr list,
19160: xmlSchemaItemListPtr prohibs)
19161: {
19162: xmlSchemaAttributeGroupPtr gr;
19163: xmlSchemaAttributeUsePtr use;
19164: xmlSchemaItemListPtr sublist;
19165: int i, j;
19166: int created = (*completeWild == NULL) ? 0 : 1;
19167:
19168: if (prohibs)
19169: prohibs->nbItems = 0;
19170:
19171: for (i = 0; i < list->nbItems; i++) {
19172: use = list->items[i];
19173:
19174: if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19175: if (prohibs == NULL) {
19176: PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19177: "unexpected attr prohibition found");
19178: return(-1);
19179: }
19180: /*
19181: * Remove from attribute uses.
19182: */
19183: if (xmlSchemaItemListRemove(list, i) == -1)
19184: return(-1);
19185: i--;
19186: /*
19187: * Note that duplicate prohibitions were already
19188: * handled at parsing time.
19189: */
19190: /*
19191: * Add to list of prohibitions.
19192: */
19193: xmlSchemaItemListAddSize(prohibs, 2, use);
19194: continue;
19195: }
19196: if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19197: ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19198: {
19199: if ((WXS_QNAME_CAST use)->item == NULL)
19200: return(-1);
19201: gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19202: /*
19203: * Expand the referenced attr. group.
19204: * TODO: remove this, this is done in a previous step, so
19205: * already done here.
19206: */
19207: if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19208: if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19209: return(-1);
19210: }
19211: /*
19212: * Build the 'complete' wildcard; i.e. intersect multiple
19213: * wildcards.
19214: */
19215: if (gr->attributeWildcard != NULL) {
19216: if (*completeWild == NULL) {
19217: *completeWild = gr->attributeWildcard;
19218: } else {
19219: if (! created) {
19220: xmlSchemaWildcardPtr tmpWild;
19221:
19222: /*
19223: * Copy the first encountered wildcard as context,
19224: * except for the annotation.
19225: *
19226: * Although the complete wildcard might not correspond
19227: * to any node in the schema, we will anchor it on
19228: * the node of the owner component.
19229: */
19230: tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19231: XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19232: WXS_ITEM_NODE(item));
19233: if (tmpWild == NULL)
19234: return(-1);
19235: if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19236: tmpWild, *completeWild) == -1)
19237: return (-1);
19238: tmpWild->processContents = (*completeWild)->processContents;
19239: *completeWild = tmpWild;
19240: created = 1;
19241: }
19242:
19243: if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19244: gr->attributeWildcard) == -1)
19245: return(-1);
19246: }
19247: }
19248: /*
19249: * Just remove the reference if the referenced group does not
19250: * contain any attribute uses.
19251: */
19252: sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19253: if ((sublist == NULL) || sublist->nbItems == 0) {
19254: if (xmlSchemaItemListRemove(list, i) == -1)
19255: return(-1);
19256: i--;
19257: continue;
19258: }
19259: /*
19260: * Add the attribute uses.
19261: */
19262: list->items[i] = sublist->items[0];
19263: if (sublist->nbItems != 1) {
19264: for (j = 1; j < sublist->nbItems; j++) {
19265: i++;
19266: if (xmlSchemaItemListInsert(list,
19267: sublist->items[j], i) == -1)
19268: return(-1);
19269: }
19270: }
19271: }
19272:
19273: }
19274: /*
19275: * Handle pointless prohibitions of declared attributes.
19276: */
19277: if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19278: xmlSchemaAttributeUseProhibPtr prohib;
19279:
19280: for (i = prohibs->nbItems -1; i >= 0; i--) {
19281: prohib = prohibs->items[i];
19282: for (j = 0; j < list->nbItems; j++) {
19283: use = list->items[j];
19284:
19285: if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19286: (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19287: {
19288: xmlChar *str = NULL;
19289:
19290: xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19291: XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19292: prohib->node, NULL,
19293: "Skipping pointless attribute use prohibition "
19294: "'%s', since a corresponding attribute use "
19295: "exists already in the type definition",
19296: xmlSchemaFormatQName(&str,
19297: prohib->targetNamespace, prohib->name),
19298: NULL, NULL);
19299: FREE_AND_NULL(str);
19300: /*
19301: * Remove the prohibition.
19302: */
19303: if (xmlSchemaItemListRemove(prohibs, i) == -1)
19304: return(-1);
19305: break;
19306: }
19307: }
19308: }
19309: }
19310: return(0);
19311: }
19312:
19313: /**
19314: * xmlSchemaAttributeGroupExpandRefs:
19315: * @pctxt: the parser context
19316: * @attrGr: the attribute group definition
19317: *
19318: * Computation of:
19319: * {attribute uses} property
19320: * {attribute wildcard} property
19321: *
19322: * Substitutes contained attribute group references
19323: * for their attribute uses. Wilcards are intersected.
19324: */
19325: static int
19326: xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19327: xmlSchemaAttributeGroupPtr attrGr)
19328: {
19329: if ((attrGr->attrUses == NULL) ||
19330: (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19331: return(0);
19332:
19333: attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19334: if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19335: &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19336: return(-1);
19337: return(0);
19338: }
19339:
19340: /**
19341: * xmlSchemaAttributeGroupExpandRefs:
19342: * @pctxt: the parser context
19343: * @attrGr: the attribute group definition
19344: *
19345: * Substitutes contained attribute group references
19346: * for their attribute uses. Wilcards are intersected.
19347: *
19348: * Schema Component Constraint:
19349: * Attribute Group Definition Properties Correct (ag-props-correct)
19350: */
19351: static int
19352: xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19353: xmlSchemaAttributeGroupPtr attrGr)
19354: {
19355: /*
19356: * SPEC ag-props-correct
19357: * (1) "The values of the properties of an attribute group definition
19358: * must be as described in the property tableau in The Attribute
19359: * Group Definition Schema Component (�3.6.1), modulo the impact of
19360: * Missing Sub-components (�5.3);"
19361: */
19362:
19363: if ((attrGr->attrUses != NULL) &&
19364: (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19365: {
19366: xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19367: xmlSchemaAttributeUsePtr use, tmp;
19368: int i, j, hasId = 0;
19369:
19370: for (i = uses->nbItems -1; i >= 0; i--) {
19371: use = uses->items[i];
19372: /*
19373: * SPEC ag-props-correct
19374: * (2) "Two distinct members of the {attribute uses} must not have
19375: * {attribute declaration}s both of whose {name}s match and whose
19376: * {target namespace}s are identical."
19377: */
19378: if (i > 0) {
19379: for (j = i -1; j >= 0; j--) {
19380: tmp = uses->items[j];
19381: if ((WXS_ATTRUSE_DECL_NAME(use) ==
19382: WXS_ATTRUSE_DECL_NAME(tmp)) &&
19383: (WXS_ATTRUSE_DECL_TNS(use) ==
19384: WXS_ATTRUSE_DECL_TNS(tmp)))
19385: {
19386: xmlChar *str = NULL;
19387:
19388: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19389: XML_SCHEMAP_AG_PROPS_CORRECT,
19390: attrGr->node, WXS_BASIC_CAST attrGr,
19391: "Duplicate %s",
19392: xmlSchemaGetComponentDesignation(&str, use),
19393: NULL);
19394: FREE_AND_NULL(str);
19395: /*
19396: * Remove the duplicate.
19397: */
19398: if (xmlSchemaItemListRemove(uses, i) == -1)
19399: return(-1);
19400: goto next_use;
19401: }
19402: }
19403: }
19404: /*
19405: * SPEC ag-props-correct
19406: * (3) "Two distinct members of the {attribute uses} must not have
19407: * {attribute declaration}s both of whose {type definition}s are or
19408: * are derived from ID."
19409: * TODO: Does 'derived' include member-types of unions?
19410: */
19411: if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19412: if (xmlSchemaIsDerivedFromBuiltInType(
19413: WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19414: {
19415: if (hasId) {
19416: xmlChar *str = NULL;
19417:
19418: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19419: XML_SCHEMAP_AG_PROPS_CORRECT,
19420: attrGr->node, WXS_BASIC_CAST attrGr,
19421: "There must not exist more than one attribute "
19422: "declaration of type 'xs:ID' "
19423: "(or derived from 'xs:ID'). The %s violates this "
19424: "constraint",
19425: xmlSchemaGetComponentDesignation(&str, use),
19426: NULL);
19427: FREE_AND_NULL(str);
19428: if (xmlSchemaItemListRemove(uses, i) == -1)
19429: return(-1);
19430: }
19431: hasId = 1;
19432: }
19433: }
19434: next_use: {}
19435: }
19436: }
19437: return(0);
19438: }
19439:
19440: /**
19441: * xmlSchemaResolveAttrGroupReferences:
19442: * @attrgrpDecl: the schema attribute definition
19443: * @ctxt: the schema parser context
19444: * @name: the attribute name
19445: *
19446: * Resolves references to attribute group definitions.
19447: */
19448: static int
19449: xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19450: xmlSchemaParserCtxtPtr ctxt)
19451: {
19452: xmlSchemaAttributeGroupPtr group;
19453:
19454: if (ref->item != NULL)
19455: return(0);
19456: group = xmlSchemaGetAttributeGroup(ctxt->schema,
19457: ref->name,
19458: ref->targetNamespace);
19459: if (group == NULL) {
19460: xmlSchemaPResCompAttrErr(ctxt,
19461: XML_SCHEMAP_SRC_RESOLVE,
19462: NULL, ref->node,
19463: "ref", ref->name, ref->targetNamespace,
19464: ref->itemType, NULL);
19465: return(ctxt->err);
19466: }
19467: ref->item = WXS_BASIC_CAST group;
19468: return(0);
19469: }
19470:
19471: /**
19472: * xmlSchemaCheckAttrPropsCorrect:
19473: * @item: an schema attribute declaration/use
19474: * @ctxt: a schema parser context
19475: * @name: the name of the attribute
19476: *
19477: *
19478: * Schema Component Constraint:
19479: * Attribute Declaration Properties Correct (a-props-correct)
19480: *
19481: * Validates the value constraints of an attribute declaration/use.
19482: * NOTE that this needs the simle type definitions to be already
19483: * builded and checked.
19484: */
19485: static int
19486: xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19487: xmlSchemaAttributePtr attr)
19488: {
19489:
19490: /*
19491: * SPEC a-props-correct (1)
19492: * "The values of the properties of an attribute declaration must
19493: * be as described in the property tableau in The Attribute
19494: * Declaration Schema Component (�3.2.1), modulo the impact of
19495: * Missing Sub-components (�5.3)."
19496: */
19497:
19498: if (WXS_ATTR_TYPEDEF(attr) == NULL)
19499: return(0);
19500:
19501: if (attr->defValue != NULL) {
19502: int ret;
19503:
19504: /*
19505: * SPEC a-props-correct (3)
19506: * "If the {type definition} is or is derived from ID then there
19507: * must not be a {value constraint}."
19508: */
19509: if (xmlSchemaIsDerivedFromBuiltInType(
19510: WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19511: {
19512: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19513: XML_SCHEMAP_A_PROPS_CORRECT_3,
19514: NULL, WXS_BASIC_CAST attr,
19515: "Value constraints are not allowed if the type definition "
19516: "is or is derived from xs:ID",
19517: NULL, NULL);
19518: return(pctxt->err);
19519: }
19520: /*
19521: * SPEC a-props-correct (2)
19522: * "if there is a {value constraint}, the canonical lexical
19523: * representation of its value must be �valid� with respect
19524: * to the {type definition} as defined in String Valid (�3.14.4)."
19525: * TODO: Don't care about the *cononical* stuff here, this requirement
19526: * will be removed in WXS 1.1 anyway.
19527: */
19528: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19529: attr->node, WXS_ATTR_TYPEDEF(attr),
19530: attr->defValue, &(attr->defVal),
19531: 1, 1, 0);
19532: if (ret != 0) {
19533: if (ret < 0) {
19534: PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19535: "calling xmlSchemaVCheckCVCSimpleType()");
19536: return(-1);
19537: }
19538: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19539: XML_SCHEMAP_A_PROPS_CORRECT_2,
19540: NULL, WXS_BASIC_CAST attr,
19541: "The value of the value constraint is not valid",
19542: NULL, NULL);
19543: return(pctxt->err);
19544: }
19545: }
19546:
19547: return(0);
19548: }
19549:
19550: static xmlSchemaElementPtr
19551: xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19552: xmlSchemaElementPtr ancestor)
19553: {
19554: xmlSchemaElementPtr ret;
19555:
19556: if (WXS_SUBST_HEAD(ancestor) == NULL)
19557: return (NULL);
19558: if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19559: return (ancestor);
19560:
19561: if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19562: return (NULL);
19563: WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19564: ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19565: WXS_SUBST_HEAD(ancestor));
19566: WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19567:
19568: return (ret);
19569: }
19570:
19571: /**
19572: * xmlSchemaCheckElemPropsCorrect:
19573: * @ctxt: a schema parser context
19574: * @decl: the element declaration
19575: * @name: the name of the attribute
19576: *
19577: * Schema Component Constraint:
19578: * Element Declaration Properties Correct (e-props-correct)
19579: *
19580: * STATUS:
19581: * missing: (6)
19582: */
19583: static int
19584: xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19585: xmlSchemaElementPtr elemDecl)
19586: {
19587: int ret = 0;
19588: xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19589: /*
19590: * SPEC (1) "The values of the properties of an element declaration
19591: * must be as described in the property tableau in The Element
19592: * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19593: * Sub-components (�5.3)."
19594: */
19595: if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19596: xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19597:
19598: xmlSchemaCheckElementDeclComponent(head, pctxt);
19599: /*
19600: * SPEC (3) "If there is a non-�absent� {substitution group
19601: * affiliation}, then {scope} must be global."
19602: */
19603: if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19604: xmlSchemaPCustomErr(pctxt,
19605: XML_SCHEMAP_E_PROPS_CORRECT_3,
19606: WXS_BASIC_CAST elemDecl, NULL,
19607: "Only global element declarations can have a "
19608: "substitution group affiliation", NULL);
19609: ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19610: }
19611: /*
19612: * TODO: SPEC (6) "Circular substitution groups are disallowed.
19613: * That is, it must not be possible to return to an element declaration
19614: * by repeatedly following the {substitution group affiliation}
19615: * property."
19616: */
19617: if (head == elemDecl)
19618: circ = head;
19619: else if (WXS_SUBST_HEAD(head) != NULL)
19620: circ = xmlSchemaCheckSubstGroupCircular(head, head);
19621: else
19622: circ = NULL;
19623: if (circ != NULL) {
19624: xmlChar *strA = NULL, *strB = NULL;
19625:
19626: xmlSchemaPCustomErrExt(pctxt,
19627: XML_SCHEMAP_E_PROPS_CORRECT_6,
19628: WXS_BASIC_CAST circ, NULL,
19629: "The element declaration '%s' defines a circular "
19630: "substitution group to element declaration '%s'",
19631: xmlSchemaGetComponentQName(&strA, circ),
19632: xmlSchemaGetComponentQName(&strB, head),
19633: NULL);
19634: FREE_AND_NULL(strA)
19635: FREE_AND_NULL(strB)
19636: ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19637: }
19638: /*
19639: * SPEC (4) "If there is a {substitution group affiliation},
19640: * the {type definition}
19641: * of the element declaration must be validly derived from the {type
19642: * definition} of the {substitution group affiliation}, given the value
19643: * of the {substitution group exclusions} of the {substitution group
19644: * affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19645: * (if the {type definition} is complex) or as defined in
19646: * Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19647: * simple)."
19648: *
19649: * NOTE: {substitution group exclusions} means the values of the
19650: * attribute "final".
19651: */
19652:
19653: if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19654: int set = 0;
19655:
19656: if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19657: set |= SUBSET_EXTENSION;
19658: if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19659: set |= SUBSET_RESTRICTION;
19660:
19661: if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19662: WXS_ELEM_TYPEDEF(head), set) != 0) {
19663: xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19664:
19665: ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19666: xmlSchemaPCustomErrExt(pctxt,
19667: XML_SCHEMAP_E_PROPS_CORRECT_4,
19668: WXS_BASIC_CAST elemDecl, NULL,
19669: "The type definition '%s' was "
19670: "either rejected by the substitution group "
19671: "affiliation '%s', or not validly derived from its type "
19672: "definition '%s'",
19673: xmlSchemaGetComponentQName(&strA, typeDef),
19674: xmlSchemaGetComponentQName(&strB, head),
19675: xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19676: FREE_AND_NULL(strA)
19677: FREE_AND_NULL(strB)
19678: FREE_AND_NULL(strC)
19679: }
19680: }
19681: }
19682: /*
19683: * SPEC (5) "If the {type definition} or {type definition}'s
19684: * {content type}
19685: * is or is derived from ID then there must not be a {value constraint}.
19686: * Note: The use of ID as a type definition for elements goes beyond
19687: * XML 1.0, and should be avoided if backwards compatibility is desired"
19688: */
19689: if ((elemDecl->value != NULL) &&
19690: ((WXS_IS_SIMPLE(typeDef) &&
19691: xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19692: (WXS_IS_COMPLEX(typeDef) &&
19693: WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19694: xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19695: XML_SCHEMAS_ID)))) {
19696:
19697: ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19698: xmlSchemaPCustomErr(pctxt,
19699: XML_SCHEMAP_E_PROPS_CORRECT_5,
19700: WXS_BASIC_CAST elemDecl, NULL,
19701: "The type definition (or type definition's content type) is or "
19702: "is derived from ID; value constraints are not allowed in "
19703: "conjunction with such a type definition", NULL);
19704: } else if (elemDecl->value != NULL) {
19705: int vcret;
19706: xmlNodePtr node = NULL;
19707:
19708: /*
19709: * SPEC (2) "If there is a {value constraint}, the canonical lexical
19710: * representation of its value must be �valid� with respect to the
19711: * {type definition} as defined in Element Default Valid (Immediate)
19712: * (�3.3.6)."
19713: */
19714: if (typeDef == NULL) {
19715: xmlSchemaPErr(pctxt, elemDecl->node,
19716: XML_SCHEMAP_INTERNAL,
19717: "Internal error: xmlSchemaCheckElemPropsCorrect, "
19718: "type is missing... skipping validation of "
19719: "the value constraint", NULL, NULL);
19720: return (-1);
19721: }
19722: if (elemDecl->node != NULL) {
19723: if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19724: node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19725: BAD_CAST "fixed");
19726: else
19727: node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19728: BAD_CAST "default");
19729: }
19730: vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19731: typeDef, elemDecl->value, &(elemDecl->defVal));
19732: if (vcret != 0) {
19733: if (vcret < 0) {
19734: PERROR_INT("xmlSchemaElemCheckValConstr",
19735: "failed to validate the value constraint of an "
19736: "element declaration");
19737: return (-1);
19738: }
19739: return (vcret);
19740: }
19741: }
19742:
19743: return (ret);
19744: }
19745:
19746: /**
19747: * xmlSchemaCheckElemSubstGroup:
19748: * @ctxt: a schema parser context
19749: * @decl: the element declaration
19750: * @name: the name of the attribute
19751: *
19752: * Schema Component Constraint:
19753: * Substitution Group (cos-equiv-class)
19754: *
19755: * In Libxml2 the subst. groups will be precomputed, in terms of that
19756: * a list will be built for each subst. group head, holding all direct
19757: * referents to this head.
19758: * NOTE that this function needs:
19759: * 1. circular subst. groups to be checked beforehand
19760: * 2. the declaration's type to be derived from the head's type
19761: *
19762: * STATUS:
19763: *
19764: */
19765: static void
19766: xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19767: xmlSchemaElementPtr elemDecl)
19768: {
19769: if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19770: /* SPEC (1) "Its {abstract} is false." */
19771: (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19772: return;
19773: {
19774: xmlSchemaElementPtr head;
19775: xmlSchemaTypePtr headType, type;
19776: int set, methSet;
19777: /*
19778: * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19779: * {disallowed substitutions} as the blocking constraint, as defined in
19780: * Substitution Group OK (Transitive) (�3.3.6)."
19781: */
19782: for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19783: head = WXS_SUBST_HEAD(head)) {
19784: set = 0;
19785: methSet = 0;
19786: /*
19787: * The blocking constraints.
19788: */
19789: if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19790: continue;
19791: headType = head->subtypes;
19792: type = elemDecl->subtypes;
19793: if (headType == type)
19794: goto add_member;
19795: if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19796: set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19797: if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19798: set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19799: /*
19800: * SPEC: Substitution Group OK (Transitive) (2.3)
19801: * "The set of all {derivation method}s involved in the
19802: * derivation of D's {type definition} from C's {type definition}
19803: * does not intersect with the union of the blocking constraint,
19804: * C's {prohibited substitutions} (if C is complex, otherwise the
19805: * empty set) and the {prohibited substitutions} (respectively the
19806: * empty set) of any intermediate {type definition}s in the
19807: * derivation of D's {type definition} from C's {type definition}."
19808: */
19809: /*
19810: * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19811: * subst.head axis, the methSet does not need to be computed for
19812: * the full depth over and over.
19813: */
19814: /*
19815: * The set of all {derivation method}s involved in the derivation
19816: */
19817: while ((type != NULL) && (type != headType)) {
19818: if ((WXS_IS_EXTENSION(type)) &&
19819: ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19820: methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19821:
19822: if (WXS_IS_RESTRICTION(type) &&
19823: ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19824: methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19825:
19826: type = type->baseType;
19827: }
19828: /*
19829: * The {prohibited substitutions} of all intermediate types +
19830: * the head's type.
19831: */
19832: type = elemDecl->subtypes->baseType;
19833: while (type != NULL) {
19834: if (WXS_IS_COMPLEX(type)) {
19835: if ((type->flags &
19836: XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19837: ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19838: set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19839: if ((type->flags &
19840: XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19841: ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19842: set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19843: } else
19844: break;
19845: if (type == headType)
19846: break;
19847: type = type->baseType;
19848: }
19849: if ((set != 0) &&
19850: (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19851: (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19852: ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19853: (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19854: continue;
19855: }
19856: add_member:
19857: xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19858: if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19859: head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19860: }
19861: }
19862: }
19863:
19864: #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19865: /**
19866: * xmlSchemaCheckElementDeclComponent
19867: * @pctxt: the schema parser context
19868: * @ctxtComponent: the context component (an element declaration)
19869: * @ctxtParticle: the first particle of the context component
19870: * @searchParticle: the element declaration particle to be analysed
19871: *
19872: * Schema Component Constraint: Element Declarations Consistent
19873: */
19874: static int
19875: xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19876: xmlSchemaBasicItemPtr ctxtComponent,
19877: xmlSchemaParticlePtr ctxtParticle,
19878: xmlSchemaParticlePtr searchParticle,
19879: xmlSchemaParticlePtr curParticle,
19880: int search)
19881: {
19882: return(0);
19883:
19884: int ret = 0;
19885: xmlSchemaParticlePtr cur = curParticle;
19886: if (curParticle == NULL) {
19887: return(0);
19888: }
19889: if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19890: /*
19891: * Just return in this case. A missing "term" of the particle
19892: * might arise due to an invalid "term" component.
19893: */
19894: return(0);
19895: }
19896: while (cur != NULL) {
19897: switch (WXS_PARTICLE_TERM(cur)->type) {
19898: case XML_SCHEMA_TYPE_ANY:
19899: break;
19900: case XML_SCHEMA_TYPE_ELEMENT:
19901: if (search == 0) {
19902: ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19903: ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19904: if (ret != 0)
19905: return(ret);
19906: } else {
19907: xmlSchemaElementPtr elem =
19908: WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19909: /*
19910: * SPEC Element Declarations Consistent:
19911: * "If the {particles} contains, either directly,
19912: * indirectly (that is, within the {particles} of a
19913: * contained model group, recursively) or �implicitly�
19914: * two or more element declaration particles with
19915: * the same {name} and {target namespace}, then
19916: * all their type definitions must be the same
19917: * top-level definition [...]"
19918: */
19919: if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19920: WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19921: xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19922: WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19923: {
19924: xmlChar *strA = NULL, *strB = NULL;
19925:
19926: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19927: /* TODO: error code */
19928: XML_SCHEMAP_COS_NONAMBIG,
19929: WXS_ITEM_NODE(cur), NULL,
19930: "In the content model of %s, there are multiple "
19931: "element declarations for '%s' with different "
19932: "type definitions",
19933: xmlSchemaGetComponentDesignation(&strA,
19934: ctxtComponent),
19935: xmlSchemaFormatQName(&strB,
19936: WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19937: WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19938: FREE_AND_NULL(strA);
19939: FREE_AND_NULL(strB);
19940: return(XML_SCHEMAP_COS_NONAMBIG);
19941: }
19942: }
19943: break;
19944: case XML_SCHEMA_TYPE_SEQUENCE: {
19945: break;
19946: }
19947: case XML_SCHEMA_TYPE_CHOICE:{
19948: /*
19949: xmlSchemaTreeItemPtr sub;
19950:
19951: sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr)
19952: while (sub != NULL) {
19953: ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19954: ctxtParticle, ctxtElem);
19955: if (ret != 0)
19956: return(ret);
19957: sub = sub->next;
19958: }
19959: */
19960: break;
19961: }
19962: case XML_SCHEMA_TYPE_ALL:
19963: break;
19964: case XML_SCHEMA_TYPE_GROUP:
19965: break;
19966: default:
19967: xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19968: "xmlSchemaCheckElementDeclConsistent",
19969: "found unexpected term of type '%s' in content model",
19970: WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19971: return(-1);
19972: }
19973: cur = (xmlSchemaParticlePtr) cur->next;
19974: }
19975:
19976: exit:
19977: return(ret);
19978: }
19979: #endif
19980:
19981: /**
19982: * xmlSchemaCheckElementDeclComponent
19983: * @item: an schema element declaration/particle
19984: * @ctxt: a schema parser context
19985: * @name: the name of the attribute
19986: *
19987: * Validates the value constraints of an element declaration.
19988: * Adds substitution group members.
19989: */
19990: static void
19991: xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19992: xmlSchemaParserCtxtPtr ctxt)
19993: {
19994: if (elemDecl == NULL)
19995: return;
19996: if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19997: return;
19998: elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19999: if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20000: /*
20001: * Adds substitution group members.
20002: */
20003: xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20004: }
20005: }
20006:
20007: /**
20008: * xmlSchemaResolveModelGroupParticleReferences:
20009: * @particle: a particle component
20010: * @ctxt: a parser context
20011: *
20012: * Resolves references of a model group's {particles} to
20013: * model group definitions and to element declarations.
20014: */
20015: static void
20016: xmlSchemaResolveModelGroupParticleReferences(
20017: xmlSchemaParserCtxtPtr ctxt,
20018: xmlSchemaModelGroupPtr mg)
20019: {
20020: xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20021: xmlSchemaQNameRefPtr ref;
20022: xmlSchemaBasicItemPtr refItem;
20023:
20024: /*
20025: * URGENT TODO: Test this.
20026: */
20027: while (particle != NULL) {
20028: if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20029: ((WXS_PARTICLE_TERM(particle))->type !=
20030: XML_SCHEMA_EXTRA_QNAMEREF))
20031: {
20032: goto next_particle;
20033: }
20034: ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20035: /*
20036: * Resolve the reference.
20037: * NULL the {term} by default.
20038: */
20039: particle->children = NULL;
20040:
20041: refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20042: ref->itemType, ref->name, ref->targetNamespace);
20043: if (refItem == NULL) {
20044: xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20045: NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20046: ref->targetNamespace, ref->itemType, NULL);
20047: /* TODO: remove the particle. */
20048: goto next_particle;
20049: }
20050: if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20051: if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20052: /* TODO: remove the particle. */
20053: goto next_particle;
20054: /*
20055: * NOTE that we will assign the model group definition
20056: * itself to the "term" of the particle. This will ease
20057: * the check for circular model group definitions. After
20058: * that the "term" will be assigned the model group of the
20059: * model group definition.
20060: */
20061: if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20062: XML_SCHEMA_TYPE_ALL) {
20063: /*
20064: * SPEC cos-all-limited (1)
20065: * SPEC cos-all-limited (1.2)
20066: * "It appears only as the value of one or both of the
20067: * following properties:"
20068: * (1.1) "the {model group} property of a model group
20069: * definition."
20070: * (1.2) "the {term} property of a particle [... of] the "
20071: * {content type} of a complex type definition."
20072: */
20073: xmlSchemaCustomErr(ACTXT_CAST ctxt,
20074: /* TODO: error code */
20075: XML_SCHEMAP_COS_ALL_LIMITED,
20076: WXS_ITEM_NODE(particle), NULL,
20077: "A model group definition is referenced, but "
20078: "it contains an 'all' model group, which "
20079: "cannot be contained by model groups",
20080: NULL, NULL);
20081: /* TODO: remove the particle. */
20082: goto next_particle;
20083: }
20084: particle->children = (xmlSchemaTreeItemPtr) refItem;
20085: } else {
20086: /*
20087: * TODO: Are referenced element declarations the only
20088: * other components we expect here?
20089: */
20090: particle->children = (xmlSchemaTreeItemPtr) refItem;
20091: }
20092: next_particle:
20093: particle = WXS_PTC_CAST particle->next;
20094: }
20095: }
20096:
20097: static int
20098: xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20099: xmlSchemaValPtr y)
20100: {
20101: xmlSchemaTypePtr tx, ty, ptx, pty;
20102: int ret;
20103:
20104: while (x != NULL) {
20105: /* Same types. */
20106: tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20107: ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20108: ptx = xmlSchemaGetPrimitiveType(tx);
20109: pty = xmlSchemaGetPrimitiveType(ty);
20110: /*
20111: * (1) if a datatype T' is �derived� by �restriction� from an
20112: * atomic datatype T then the �value space� of T' is a subset of
20113: * the �value space� of T. */
20114: /*
20115: * (2) if datatypes T' and T'' are �derived� by �restriction�
20116: * from a common atomic ancestor T then the �value space�s of T'
20117: * and T'' may overlap.
20118: */
20119: if (ptx != pty)
20120: return(0);
20121: /*
20122: * We assume computed values to be normalized, so do a fast
20123: * string comparison for string based types.
20124: */
20125: if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20126: WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20127: if (! xmlStrEqual(
20128: xmlSchemaValueGetAsString(x),
20129: xmlSchemaValueGetAsString(y)))
20130: return (0);
20131: } else {
20132: ret = xmlSchemaCompareValuesWhtsp(
20133: x, XML_SCHEMA_WHITESPACE_PRESERVE,
20134: y, XML_SCHEMA_WHITESPACE_PRESERVE);
20135: if (ret == -2)
20136: return(-1);
20137: if (ret != 0)
20138: return(0);
20139: }
20140: /*
20141: * Lists.
20142: */
20143: x = xmlSchemaValueGetNext(x);
20144: if (x != NULL) {
20145: y = xmlSchemaValueGetNext(y);
20146: if (y == NULL)
20147: return (0);
20148: } else if (xmlSchemaValueGetNext(y) != NULL)
20149: return (0);
20150: else
20151: return (1);
20152: }
20153: return (0);
20154: }
20155:
20156: /**
20157: * xmlSchemaResolveAttrUseReferences:
20158: * @item: an attribute use
20159: * @ctxt: a parser context
20160: *
20161: * Resolves the referenced attribute declaration.
20162: */
20163: static int
20164: xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20165: xmlSchemaParserCtxtPtr ctxt)
20166: {
20167: if ((ctxt == NULL) || (ause == NULL))
20168: return(-1);
20169: if ((ause->attrDecl == NULL) ||
20170: (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20171: return(0);
20172:
20173: {
20174: xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20175:
20176: /*
20177: * TODO: Evaluate, what errors could occur if the declaration is not
20178: * found.
20179: */
20180: ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20181: ref->name, ref->targetNamespace);
20182: if (ause->attrDecl == NULL) {
20183: xmlSchemaPResCompAttrErr(ctxt,
1.1.1.3 ! misho 20184: XML_SCHEMAP_SRC_RESOLVE,
1.1 misho 20185: WXS_BASIC_CAST ause, ause->node,
20186: "ref", ref->name, ref->targetNamespace,
20187: XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20188: return(ctxt->err);;
20189: }
20190: }
20191: return(0);
20192: }
20193:
20194: /**
20195: * xmlSchemaCheckAttrUsePropsCorrect:
20196: * @ctxt: a parser context
20197: * @use: an attribute use
20198: *
20199: * Schema Component Constraint:
20200: * Attribute Use Correct (au-props-correct)
20201: *
20202: */
20203: static int
20204: xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20205: xmlSchemaAttributeUsePtr use)
20206: {
20207: if ((ctxt == NULL) || (use == NULL))
20208: return(-1);
20209: if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20210: ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20211: return(0);
20212:
20213: /*
20214: * SPEC au-props-correct (1)
20215: * "The values of the properties of an attribute use must be as
20216: * described in the property tableau in The Attribute Use Schema
20217: * Component (�3.5.1), modulo the impact of Missing
20218: * Sub-components (�5.3)."
20219: */
20220:
20221: if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20222: ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20223: ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20224: {
20225: xmlSchemaPCustomErr(ctxt,
20226: XML_SCHEMAP_AU_PROPS_CORRECT_2,
20227: WXS_BASIC_CAST use, NULL,
20228: "The attribute declaration has a 'fixed' value constraint "
20229: ", thus the attribute use must also have a 'fixed' value "
20230: "constraint",
20231: NULL);
20232: return(ctxt->err);
20233: }
20234: /*
20235: * Compute and check the value constraint's value.
20236: */
20237: if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20238: int ret;
20239: /*
20240: * TODO: The spec seems to be missing a check of the
20241: * value constraint of the attribute use. We will do it here.
20242: */
20243: /*
20244: * SPEC a-props-correct (3)
20245: */
20246: if (xmlSchemaIsDerivedFromBuiltInType(
20247: WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20248: {
20249: xmlSchemaCustomErr(ACTXT_CAST ctxt,
20250: XML_SCHEMAP_AU_PROPS_CORRECT,
20251: NULL, WXS_BASIC_CAST use,
20252: "Value constraints are not allowed if the type definition "
20253: "is or is derived from xs:ID",
20254: NULL, NULL);
20255: return(ctxt->err);
20256: }
20257:
20258: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20259: use->node, WXS_ATTRUSE_TYPEDEF(use),
20260: use->defValue, &(use->defVal),
20261: 1, 1, 0);
20262: if (ret != 0) {
20263: if (ret < 0) {
20264: PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20265: "calling xmlSchemaVCheckCVCSimpleType()");
20266: return(-1);
20267: }
20268: xmlSchemaCustomErr(ACTXT_CAST ctxt,
20269: XML_SCHEMAP_AU_PROPS_CORRECT,
20270: NULL, WXS_BASIC_CAST use,
20271: "The value of the value constraint is not valid",
20272: NULL, NULL);
20273: return(ctxt->err);
20274: }
20275: }
20276: /*
20277: * SPEC au-props-correct (2)
20278: * "If the {attribute declaration} has a fixed
20279: * {value constraint}, then if the attribute use itself has a
20280: * {value constraint}, it must also be fixed and its value must match
20281: * that of the {attribute declaration}'s {value constraint}."
20282: */
20283: if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20284: (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20285: {
20286: if (! xmlSchemaAreValuesEqual(use->defVal,
20287: (WXS_ATTRUSE_DECL(use))->defVal))
20288: {
20289: xmlSchemaPCustomErr(ctxt,
20290: XML_SCHEMAP_AU_PROPS_CORRECT_2,
20291: WXS_BASIC_CAST use, NULL,
20292: "The 'fixed' value constraint of the attribute use "
20293: "must match the attribute declaration's value "
20294: "constraint '%s'",
20295: (WXS_ATTRUSE_DECL(use))->defValue);
20296: }
20297: return(ctxt->err);
20298: }
20299: return(0);
20300: }
20301:
20302:
20303:
20304:
20305: /**
20306: * xmlSchemaResolveAttrTypeReferences:
20307: * @item: an attribute declaration
20308: * @ctxt: a parser context
20309: *
20310: * Resolves the referenced type definition component.
20311: */
20312: static int
20313: xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20314: xmlSchemaParserCtxtPtr ctxt)
20315: {
20316: /*
20317: * The simple type definition corresponding to the <simpleType> element
20318: * information item in the [children], if present, otherwise the simple
20319: * type definition �resolved� to by the �actual value� of the type
20320: * [attribute], if present, otherwise the �simple ur-type definition�.
20321: */
20322: if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20323: return(0);
20324: item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20325: if (item->subtypes != NULL)
20326: return(0);
20327: if (item->typeName != NULL) {
20328: xmlSchemaTypePtr type;
20329:
20330: type = xmlSchemaGetType(ctxt->schema, item->typeName,
20331: item->typeNs);
20332: if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20333: xmlSchemaPResCompAttrErr(ctxt,
20334: XML_SCHEMAP_SRC_RESOLVE,
20335: WXS_BASIC_CAST item, item->node,
20336: "type", item->typeName, item->typeNs,
20337: XML_SCHEMA_TYPE_SIMPLE, NULL);
20338: return(ctxt->err);
20339: } else
20340: item->subtypes = type;
20341:
20342: } else {
20343: /*
20344: * The type defaults to the xs:anySimpleType.
20345: */
20346: item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20347: }
20348: return(0);
20349: }
20350:
20351: /**
20352: * xmlSchemaResolveIDCKeyReferences:
20353: * @idc: the identity-constraint definition
20354: * @ctxt: the schema parser context
20355: * @name: the attribute name
20356: *
20357: * Resolve keyRef references to key/unique IDCs.
20358: * Schema Component Constraint:
20359: * Identity-constraint Definition Properties Correct (c-props-correct)
20360: */
20361: static int
20362: xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20363: xmlSchemaParserCtxtPtr pctxt)
20364: {
20365: if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20366: return(0);
20367: if (idc->ref->name != NULL) {
20368: idc->ref->item = (xmlSchemaBasicItemPtr)
20369: xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20370: idc->ref->targetNamespace);
20371: if (idc->ref->item == NULL) {
20372: /*
20373: * TODO: It is actually not an error to fail to resolve
20374: * at this stage. BUT we need to be that strict!
20375: */
20376: xmlSchemaPResCompAttrErr(pctxt,
20377: XML_SCHEMAP_SRC_RESOLVE,
20378: WXS_BASIC_CAST idc, idc->node,
20379: "refer", idc->ref->name,
20380: idc->ref->targetNamespace,
20381: XML_SCHEMA_TYPE_IDC_KEY, NULL);
20382: return(pctxt->err);
20383: } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20384: /*
20385: * SPEC c-props-correct (1)
20386: */
20387: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20388: XML_SCHEMAP_C_PROPS_CORRECT,
20389: NULL, WXS_BASIC_CAST idc,
20390: "The keyref references a keyref",
20391: NULL, NULL);
20392: idc->ref->item = NULL;
20393: return(pctxt->err);
20394: } else {
20395: if (idc->nbFields !=
20396: ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20397: xmlChar *str = NULL;
20398: xmlSchemaIDCPtr refer;
20399:
20400: refer = (xmlSchemaIDCPtr) idc->ref->item;
20401: /*
20402: * SPEC c-props-correct(2)
20403: * "If the {identity-constraint category} is keyref,
20404: * the cardinality of the {fields} must equal that of
20405: * the {fields} of the {referenced key}.
20406: */
20407: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20408: XML_SCHEMAP_C_PROPS_CORRECT,
20409: NULL, WXS_BASIC_CAST idc,
20410: "The cardinality of the keyref differs from the "
20411: "cardinality of the referenced key/unique '%s'",
20412: xmlSchemaFormatQName(&str, refer->targetNamespace,
20413: refer->name),
20414: NULL);
20415: FREE_AND_NULL(str)
20416: return(pctxt->err);
20417: }
20418: }
20419: }
20420: return(0);
20421: }
20422:
20423: static int
20424: xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20425: xmlSchemaParserCtxtPtr pctxt)
20426: {
20427: if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20428: prohib->targetNamespace) == NULL) {
20429:
20430: xmlSchemaPResCompAttrErr(pctxt,
20431: XML_SCHEMAP_SRC_RESOLVE,
20432: NULL, prohib->node,
20433: "ref", prohib->name, prohib->targetNamespace,
20434: XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20435: return(XML_SCHEMAP_SRC_RESOLVE);
20436: }
20437: return(0);
20438: }
20439:
20440: #define WXS_REDEFINED_TYPE(c) \
20441: (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20442:
20443: #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20444: (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20445:
20446: #define WXS_REDEFINED_ATTR_GROUP(c) \
20447: (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20448:
20449: static int
20450: xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20451: {
20452: int err = 0;
20453: xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20454: xmlSchemaBasicItemPtr prev, item;
20455: int wasRedefined;
20456:
20457: if (redef == NULL)
20458: return(0);
20459:
20460: do {
20461: item = redef->item;
20462: /*
20463: * First try to locate the redefined component in the
20464: * schema graph starting with the redefined schema.
20465: * NOTE: According to this schema bug entry:
20466: * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20467: * it's not clear if the referenced component needs to originate
20468: * from the <redefine>d schema _document_ or the schema; the latter
20469: * would include all imported and included sub-schemas of the
20470: * <redefine>d schema. Currenlty we latter approach is used.
20471: * SUPPLEMENT: It seems that the WG moves towards the latter
20472: * approach, so we are doing it right.
20473: *
20474: */
20475: prev = xmlSchemaFindRedefCompInGraph(
20476: redef->targetBucket, item->type,
20477: redef->refName, redef->refTargetNs);
20478: if (prev == NULL) {
20479: xmlChar *str = NULL;
20480: xmlNodePtr node;
20481:
20482: /*
20483: * SPEC src-redefine:
20484: * (6.2.1) "The �actual value� of its own name attribute plus
20485: * target namespace must successfully �resolve� to a model
20486: * group definition in I."
20487: * (7.2.1) "The �actual value� of its own name attribute plus
20488: * target namespace must successfully �resolve� to an attribute
20489: * group definition in I."
20490:
20491: *
20492: * Note that, if we are redefining with the use of references
20493: * to components, the spec assumes the src-resolve to be used;
20494: * but this won't assure that we search only *inside* the
20495: * redefined schema.
20496: */
20497: if (redef->reference)
20498: node = WXS_ITEM_NODE(redef->reference);
20499: else
20500: node = WXS_ITEM_NODE(item);
20501: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20502: /*
20503: * TODO: error code.
20504: * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20505: * reference kind.
20506: */
20507: XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20508: "The %s '%s' to be redefined could not be found in "
20509: "the redefined schema",
20510: WXS_ITEM_TYPE_NAME(item),
20511: xmlSchemaFormatQName(&str, redef->refTargetNs,
20512: redef->refName));
20513: FREE_AND_NULL(str);
20514: err = pctxt->err;
20515: redef = redef->next;
20516: continue;
20517: }
20518: /*
20519: * TODO: Obtaining and setting the redefinition state is really
20520: * clumsy.
20521: */
20522: wasRedefined = 0;
20523: switch (item->type) {
20524: case XML_SCHEMA_TYPE_COMPLEX:
20525: case XML_SCHEMA_TYPE_SIMPLE:
20526: if ((WXS_TYPE_CAST prev)->flags &
20527: XML_SCHEMAS_TYPE_REDEFINED)
20528: {
20529: wasRedefined = 1;
20530: break;
20531: }
20532: /* Mark it as redefined. */
20533: (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20534: /*
20535: * Assign the redefined type to the
20536: * base type of the redefining type.
20537: * TODO: How
20538: */
20539: ((xmlSchemaTypePtr) item)->baseType =
20540: (xmlSchemaTypePtr) prev;
20541: break;
20542: case XML_SCHEMA_TYPE_GROUP:
20543: if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20544: XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20545: {
20546: wasRedefined = 1;
20547: break;
20548: }
20549: /* Mark it as redefined. */
20550: (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20551: XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20552: if (redef->reference != NULL) {
20553: /*
20554: * Overwrite the QName-reference with the
20555: * referenced model group def.
20556: */
20557: (WXS_PTC_CAST redef->reference)->children =
20558: WXS_TREE_CAST prev;
20559: }
20560: redef->target = prev;
20561: break;
20562: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20563: if ((WXS_ATTR_GROUP_CAST prev)->flags &
20564: XML_SCHEMAS_ATTRGROUP_REDEFINED)
20565: {
20566: wasRedefined = 1;
20567: break;
20568: }
20569: (WXS_ATTR_GROUP_CAST prev)->flags |=
20570: XML_SCHEMAS_ATTRGROUP_REDEFINED;
20571: if (redef->reference != NULL) {
20572: /*
20573: * Assign the redefined attribute group to the
20574: * QName-reference component.
20575: * This is the easy case, since we will just
20576: * expand the redefined group.
20577: */
20578: (WXS_QNAME_CAST redef->reference)->item = prev;
20579: redef->target = NULL;
20580: } else {
20581: /*
20582: * This is the complicated case: we need
20583: * to apply src-redefine (7.2.2) at a later
20584: * stage, i.e. when attribute group references
20585: * have beed expanded and simple types have
20586: * beed fixed.
20587: */
20588: redef->target = prev;
20589: }
20590: break;
20591: default:
20592: PERROR_INT("xmlSchemaResolveRedefReferences",
20593: "Unexpected redefined component type");
20594: return(-1);
20595: }
20596: if (wasRedefined) {
20597: xmlChar *str = NULL;
20598: xmlNodePtr node;
20599:
20600: if (redef->reference)
20601: node = WXS_ITEM_NODE(redef->reference);
20602: else
20603: node = WXS_ITEM_NODE(redef->item);
20604:
20605: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20606: /* TODO: error code. */
20607: XML_SCHEMAP_SRC_REDEFINE,
20608: node, NULL,
20609: "The referenced %s was already redefined. Multiple "
20610: "redefinition of the same component is not supported",
20611: xmlSchemaGetComponentDesignation(&str, prev),
20612: NULL);
20613: FREE_AND_NULL(str)
20614: err = pctxt->err;
20615: redef = redef->next;
20616: continue;
20617: }
20618: redef = redef->next;
20619: } while (redef != NULL);
20620:
20621: return(err);
20622: }
20623:
20624: static int
20625: xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20626: {
20627: int err = 0;
20628: xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20629: xmlSchemaBasicItemPtr item;
20630:
20631: if (redef == NULL)
20632: return(0);
20633:
20634: do {
20635: if (redef->target == NULL) {
20636: redef = redef->next;
20637: continue;
20638: }
20639: item = redef->item;
20640:
20641: switch (item->type) {
20642: case XML_SCHEMA_TYPE_SIMPLE:
20643: case XML_SCHEMA_TYPE_COMPLEX:
20644: /*
20645: * Since the spec wants the {name} of the redefined
20646: * type to be 'absent', we'll NULL it.
20647: */
20648: (WXS_TYPE_CAST redef->target)->name = NULL;
20649:
20650: /*
20651: * TODO: Seems like there's nothing more to do. The normal
20652: * inheritance mechanism is used. But not 100% sure.
20653: */
20654: break;
20655: case XML_SCHEMA_TYPE_GROUP:
20656: /*
20657: * URGENT TODO:
20658: * SPEC src-redefine:
20659: * (6.2.2) "The {model group} of the model group definition
20660: * which corresponds to it per XML Representation of Model
20661: * Group Definition Schema Components (�3.7.2) must be a
20662: * �valid restriction� of the {model group} of that model
20663: * group definition in I, as defined in Particle Valid
20664: * (Restriction) (�3.9.6)."
20665: */
20666: break;
20667: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20668: /*
20669: * SPEC src-redefine:
20670: * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20671: * the attribute group definition which corresponds to it
20672: * per XML Representation of Attribute Group Definition Schema
20673: * Components (�3.6.2) must be �valid restrictions� of the
20674: * {attribute uses} and {attribute wildcard} of that attribute
20675: * group definition in I, as defined in clause 2, clause 3 and
20676: * clause 4 of Derivation Valid (Restriction, Complex)
20677: * (�3.4.6) (where references to the base type definition are
20678: * understood as references to the attribute group definition
20679: * in I)."
20680: */
20681: err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20682: XML_SCHEMA_ACTION_REDEFINE,
20683: item, redef->target,
20684: (WXS_ATTR_GROUP_CAST item)->attrUses,
20685: (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20686: (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20687: (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20688: if (err == -1)
20689: return(-1);
20690: break;
20691: default:
20692: break;
20693: }
20694: redef = redef->next;
20695: } while (redef != NULL);
20696: return(0);
20697: }
20698:
20699:
20700: static int
20701: xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20702: xmlSchemaBucketPtr bucket)
20703: {
20704: xmlSchemaBasicItemPtr item;
20705: int err;
20706: xmlHashTablePtr *table;
20707: const xmlChar *name;
20708: int i;
20709:
20710: #define WXS_GET_GLOBAL_HASH(c, slot) { \
20711: if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20712: table = &(WXS_IMPBUCKET((c))->schema->slot); \
20713: else \
20714: table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20715:
20716: /*
20717: * Add global components to the schema's hash tables.
20718: * This is the place where duplicate components will be
20719: * detected.
20720: * TODO: I think normally we should support imports of the
20721: * same namespace from multiple locations. We don't do currently,
20722: * but if we do then according to:
20723: * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20724: * we would need, if imported directly, to import redefined
20725: * components as well to be able to catch clashing components.
20726: * (I hope I'll still know what this means after some months :-()
20727: */
20728: if (bucket == NULL)
20729: return(-1);
20730: if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20731: return(0);
20732: bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20733:
20734: for (i = 0; i < bucket->globals->nbItems; i++) {
20735: item = bucket->globals->items[i];
20736: table = NULL;
20737: switch (item->type) {
20738: case XML_SCHEMA_TYPE_COMPLEX:
20739: case XML_SCHEMA_TYPE_SIMPLE:
20740: if (WXS_REDEFINED_TYPE(item))
20741: continue;
20742: name = (WXS_TYPE_CAST item)->name;
20743: WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20744: break;
20745: case XML_SCHEMA_TYPE_ELEMENT:
20746: name = (WXS_ELEM_CAST item)->name;
20747: WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20748: break;
20749: case XML_SCHEMA_TYPE_ATTRIBUTE:
20750: name = (WXS_ATTR_CAST item)->name;
20751: WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20752: break;
20753: case XML_SCHEMA_TYPE_GROUP:
20754: if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20755: continue;
20756: name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20757: WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20758: break;
20759: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20760: if (WXS_REDEFINED_ATTR_GROUP(item))
20761: continue;
20762: name = (WXS_ATTR_GROUP_CAST item)->name;
20763: WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20764: break;
20765: case XML_SCHEMA_TYPE_IDC_KEY:
20766: case XML_SCHEMA_TYPE_IDC_UNIQUE:
20767: case XML_SCHEMA_TYPE_IDC_KEYREF:
20768: name = (WXS_IDC_CAST item)->name;
20769: WXS_GET_GLOBAL_HASH(bucket, idcDef)
20770: break;
20771: case XML_SCHEMA_TYPE_NOTATION:
20772: name = ((xmlSchemaNotationPtr) item)->name;
20773: WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20774: break;
20775: default:
20776: PERROR_INT("xmlSchemaAddComponents",
20777: "Unexpected global component type");
20778: continue;
20779: }
20780: if (*table == NULL) {
20781: *table = xmlHashCreateDict(10, pctxt->dict);
20782: if (*table == NULL) {
20783: PERROR_INT("xmlSchemaAddComponents",
20784: "failed to create a component hash table");
20785: return(-1);
20786: }
20787: }
20788: err = xmlHashAddEntry(*table, name, item);
20789: if (err != 0) {
20790: xmlChar *str = NULL;
20791:
20792: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20793: XML_SCHEMAP_REDEFINED_TYPE,
20794: WXS_ITEM_NODE(item),
20795: WXS_BASIC_CAST item,
20796: "A global %s '%s' does already exist",
20797: WXS_ITEM_TYPE_NAME(item),
20798: xmlSchemaGetComponentQName(&str, item));
20799: FREE_AND_NULL(str);
20800: }
20801: }
20802: /*
20803: * Process imported/included schemas.
20804: */
20805: if (bucket->relations != NULL) {
20806: xmlSchemaSchemaRelationPtr rel = bucket->relations;
20807: do {
20808: if ((rel->bucket != NULL) &&
20809: ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20810: if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20811: return(-1);
20812: }
20813: rel = rel->next;
20814: } while (rel != NULL);
20815: }
20816: return(0);
20817: }
20818:
20819: static int
20820: xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20821: xmlSchemaBucketPtr rootBucket)
20822: {
20823: xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20824: xmlSchemaTreeItemPtr item, *items;
20825: int nbItems, i, ret = 0;
20826: xmlSchemaBucketPtr oldbucket = con->bucket;
20827: xmlSchemaElementPtr elemDecl;
20828:
20829: #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20830:
20831: if ((con->pending == NULL) ||
20832: (con->pending->nbItems == 0))
20833: return(0);
20834:
20835: /*
20836: * Since xmlSchemaFixupComplexType() will create new particles
20837: * (local components), and those particle components need a bucket
20838: * on the constructor, we'll assure here that the constructor has
20839: * a bucket.
20840: * TODO: Think about storing locals _only_ on the main bucket.
20841: */
20842: if (con->bucket == NULL)
20843: con->bucket = rootBucket;
20844:
20845: /* TODO:
20846: * SPEC (src-redefine):
20847: * (6.2) "If it has no such self-reference, then all of the
20848: * following must be true:"
20849:
20850: * (6.2.2) The {model group} of the model group definition which
20851: * corresponds to it per XML Representation of Model Group
20852: * Definition Schema Components (�3.7.2) must be a �valid
20853: * restriction� of the {model group} of that model group definition
20854: * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20855: */
20856: xmlSchemaCheckSRCRedefineFirst(pctxt);
20857:
20858: /*
20859: * Add global components to the schemata's hash tables.
20860: */
20861: xmlSchemaAddComponents(pctxt, rootBucket);
20862:
20863: pctxt->ctxtType = NULL;
20864: items = (xmlSchemaTreeItemPtr *) con->pending->items;
20865: nbItems = con->pending->nbItems;
20866: /*
20867: * Now that we have parsed *all* the schema document(s) and converted
20868: * them to schema components, we can resolve references, apply component
20869: * constraints, create the FSA from the content model, etc.
20870: */
20871: /*
20872: * Resolve references of..
20873: *
20874: * 1. element declarations:
20875: * - the type definition
20876: * - the substitution group affiliation
20877: * 2. simple/complex types:
20878: * - the base type definition
20879: * - the memberTypes of union types
20880: * - the itemType of list types
20881: * 3. attributes declarations and attribute uses:
20882: * - the type definition
20883: * - if an attribute use, then the attribute declaration
20884: * 4. attribute group references:
20885: * - the attribute group definition
20886: * 5. particles:
20887: * - the term of the particle (e.g. a model group)
20888: * 6. IDC key-references:
20889: * - the referenced IDC 'key' or 'unique' definition
20890: * 7. Attribute prohibitions which had a "ref" attribute.
20891: */
20892: for (i = 0; i < nbItems; i++) {
20893: item = items[i];
20894: switch (item->type) {
20895: case XML_SCHEMA_TYPE_ELEMENT:
20896: xmlSchemaResolveElementReferences(
20897: (xmlSchemaElementPtr) item, pctxt);
20898: FIXHFAILURE;
20899: break;
20900: case XML_SCHEMA_TYPE_COMPLEX:
20901: case XML_SCHEMA_TYPE_SIMPLE:
20902: xmlSchemaResolveTypeReferences(
20903: (xmlSchemaTypePtr) item, pctxt);
20904: FIXHFAILURE;
20905: break;
20906: case XML_SCHEMA_TYPE_ATTRIBUTE:
20907: xmlSchemaResolveAttrTypeReferences(
20908: (xmlSchemaAttributePtr) item, pctxt);
20909: FIXHFAILURE;
20910: break;
20911: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20912: xmlSchemaResolveAttrUseReferences(
20913: (xmlSchemaAttributeUsePtr) item, pctxt);
20914: FIXHFAILURE;
20915: break;
20916: case XML_SCHEMA_EXTRA_QNAMEREF:
20917: if ((WXS_QNAME_CAST item)->itemType ==
20918: XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20919: {
20920: xmlSchemaResolveAttrGroupReferences(
20921: WXS_QNAME_CAST item, pctxt);
20922: }
20923: FIXHFAILURE;
20924: break;
20925: case XML_SCHEMA_TYPE_SEQUENCE:
20926: case XML_SCHEMA_TYPE_CHOICE:
20927: case XML_SCHEMA_TYPE_ALL:
20928: xmlSchemaResolveModelGroupParticleReferences(pctxt,
20929: WXS_MODEL_GROUP_CAST item);
20930: FIXHFAILURE;
20931: break;
20932: case XML_SCHEMA_TYPE_IDC_KEY:
20933: case XML_SCHEMA_TYPE_IDC_UNIQUE:
20934: case XML_SCHEMA_TYPE_IDC_KEYREF:
20935: xmlSchemaResolveIDCKeyReferences(
20936: (xmlSchemaIDCPtr) item, pctxt);
20937: FIXHFAILURE;
20938: break;
20939: case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20940: /*
20941: * Handle attribue prohibition which had a
20942: * "ref" attribute.
20943: */
20944: xmlSchemaResolveAttrUseProhibReferences(
20945: WXS_ATTR_PROHIB_CAST item, pctxt);
20946: FIXHFAILURE;
20947: break;
20948: default:
20949: break;
20950: }
20951: }
20952: if (pctxt->nberrors != 0)
20953: goto exit_error;
20954:
20955: /*
20956: * Now that all references are resolved we
20957: * can check for circularity of...
20958: * 1. the base axis of type definitions
20959: * 2. nested model group definitions
20960: * 3. nested attribute group definitions
20961: * TODO: check for circual substitution groups.
20962: */
20963: for (i = 0; i < nbItems; i++) {
20964: item = items[i];
20965: /*
20966: * Let's better stop on the first error here.
20967: */
20968: switch (item->type) {
20969: case XML_SCHEMA_TYPE_COMPLEX:
20970: case XML_SCHEMA_TYPE_SIMPLE:
20971: xmlSchemaCheckTypeDefCircular(
20972: (xmlSchemaTypePtr) item, pctxt);
20973: FIXHFAILURE;
20974: if (pctxt->nberrors != 0)
20975: goto exit_error;
20976: break;
20977: case XML_SCHEMA_TYPE_GROUP:
20978: xmlSchemaCheckGroupDefCircular(
20979: (xmlSchemaModelGroupDefPtr) item, pctxt);
20980: FIXHFAILURE;
20981: if (pctxt->nberrors != 0)
20982: goto exit_error;
20983: break;
20984: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20985: xmlSchemaCheckAttrGroupCircular(
20986: (xmlSchemaAttributeGroupPtr) item, pctxt);
20987: FIXHFAILURE;
20988: if (pctxt->nberrors != 0)
20989: goto exit_error;
20990: break;
20991: default:
20992: break;
20993: }
20994: }
20995: if (pctxt->nberrors != 0)
20996: goto exit_error;
20997: /*
20998: * Model group definition references:
20999: * Such a reference is reflected by a particle at the component
21000: * level. Until now the 'term' of such particles pointed
21001: * to the model group definition; this was done, in order to
21002: * ease circularity checks. Now we need to set the 'term' of
21003: * such particles to the model group of the model group definition.
21004: */
21005: for (i = 0; i < nbItems; i++) {
21006: item = items[i];
21007: switch (item->type) {
21008: case XML_SCHEMA_TYPE_SEQUENCE:
21009: case XML_SCHEMA_TYPE_CHOICE:
21010: xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21011: WXS_MODEL_GROUP_CAST item);
21012: break;
21013: default:
21014: break;
21015: }
21016: }
21017: if (pctxt->nberrors != 0)
21018: goto exit_error;
21019: /*
21020: * Expand attribute group references of attribute group definitions.
21021: */
21022: for (i = 0; i < nbItems; i++) {
21023: item = items[i];
21024: switch (item->type) {
21025: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21026: if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21027: WXS_ATTR_GROUP_HAS_REFS(item))
21028: {
21029: xmlSchemaAttributeGroupExpandRefs(pctxt,
21030: WXS_ATTR_GROUP_CAST item);
21031: FIXHFAILURE;
21032: }
21033: break;
21034: default:
21035: break;
21036: }
21037: }
21038: if (pctxt->nberrors != 0)
21039: goto exit_error;
21040: /*
21041: * First compute the variety of simple types. This is needed as
21042: * a seperate step, since otherwise we won't be able to detect
21043: * circular union types in all cases.
21044: */
21045: for (i = 0; i < nbItems; i++) {
21046: item = items[i];
21047: switch (item->type) {
21048: case XML_SCHEMA_TYPE_SIMPLE:
21049: if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21050: xmlSchemaFixupSimpleTypeStageOne(pctxt,
21051: (xmlSchemaTypePtr) item);
21052: FIXHFAILURE;
21053: }
21054: break;
21055: default:
21056: break;
21057: }
21058: }
21059: if (pctxt->nberrors != 0)
21060: goto exit_error;
21061: /*
21062: * Detect circular union types. Note that this needs the variety to
21063: * be already computed.
21064: */
21065: for (i = 0; i < nbItems; i++) {
21066: item = items[i];
21067: switch (item->type) {
21068: case XML_SCHEMA_TYPE_SIMPLE:
21069: if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21070: xmlSchemaCheckUnionTypeDefCircular(pctxt,
21071: (xmlSchemaTypePtr) item);
21072: FIXHFAILURE;
21073: }
21074: break;
21075: default:
21076: break;
21077: }
21078: }
21079: if (pctxt->nberrors != 0)
21080: goto exit_error;
21081:
21082: /*
21083: * Do the complete type fixup for simple types.
21084: */
21085: for (i = 0; i < nbItems; i++) {
21086: item = items[i];
21087: switch (item->type) {
21088: case XML_SCHEMA_TYPE_SIMPLE:
21089: if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21090: xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21091: FIXHFAILURE;
21092: }
21093: break;
21094: default:
21095: break;
21096: }
21097: }
21098: if (pctxt->nberrors != 0)
21099: goto exit_error;
21100: /*
21101: * At this point we need build and check all simple types.
21102: */
21103: /*
21104: * Apply contraints for attribute declarations.
21105: */
21106: for (i = 0; i < nbItems; i++) {
21107: item = items[i];
21108: switch (item->type) {
21109: case XML_SCHEMA_TYPE_ATTRIBUTE:
21110: xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21111: FIXHFAILURE;
21112: break;
21113: default:
21114: break;
21115: }
21116: }
21117: if (pctxt->nberrors != 0)
21118: goto exit_error;
21119: /*
21120: * Apply constraints for attribute uses.
21121: */
21122: for (i = 0; i < nbItems; i++) {
21123: item = items[i];
21124: switch (item->type) {
21125: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21126: if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21127: xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21128: WXS_ATTR_USE_CAST item);
21129: FIXHFAILURE;
21130: }
21131: break;
21132: default:
21133: break;
21134: }
21135: }
21136: if (pctxt->nberrors != 0)
21137: goto exit_error;
21138:
21139: /*
21140: * Apply constraints for attribute group definitions.
21141: */
21142: for (i = 0; i < nbItems; i++) {
21143: item = items[i];
21144: switch (item->type) {
21145: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21146: if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21147: ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21148: {
21149: xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21150: FIXHFAILURE;
21151: }
21152: break;
21153: default:
21154: break;
21155: }
21156: }
21157: if (pctxt->nberrors != 0)
21158: goto exit_error;
21159:
21160: /*
21161: * Apply constraints for redefinitions.
21162: */
21163: if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21164: xmlSchemaCheckSRCRedefineSecond(pctxt);
21165: if (pctxt->nberrors != 0)
21166: goto exit_error;
21167:
21168: /*
21169: * Complex types are builded and checked.
21170: */
21171: for (i = 0; i < nbItems; i++) {
21172: item = con->pending->items[i];
21173: switch (item->type) {
21174: case XML_SCHEMA_TYPE_COMPLEX:
21175: if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21176: xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21177: FIXHFAILURE;
21178: }
21179: break;
21180: default:
21181: break;
21182: }
21183: }
21184: if (pctxt->nberrors != 0)
21185: goto exit_error;
21186:
21187: /*
21188: * The list could have changed, since xmlSchemaFixupComplexType()
21189: * will create particles and model groups in some cases.
21190: */
21191: items = (xmlSchemaTreeItemPtr *) con->pending->items;
21192: nbItems = con->pending->nbItems;
21193:
21194: /*
21195: * Apply some constraints for element declarations.
21196: */
21197: for (i = 0; i < nbItems; i++) {
21198: item = items[i];
21199: switch (item->type) {
21200: case XML_SCHEMA_TYPE_ELEMENT:
21201: elemDecl = (xmlSchemaElementPtr) item;
21202:
21203: if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21204: {
21205: xmlSchemaCheckElementDeclComponent(
21206: (xmlSchemaElementPtr) elemDecl, pctxt);
21207: FIXHFAILURE;
21208: }
21209:
21210: #ifdef WXS_ELEM_DECL_CONS_ENABLED
21211: /*
21212: * Schema Component Constraint: Element Declarations Consistent
21213: * Apply this constraint to local types of element declarations.
21214: */
21215: if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21216: (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21217: (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21218: {
21219: xmlSchemaCheckElementDeclConsistent(pctxt,
21220: WXS_BASIC_CAST elemDecl,
21221: WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21222: NULL, NULL, 0);
21223: }
21224: #endif
21225: break;
21226: default:
21227: break;
21228: }
21229: }
21230: if (pctxt->nberrors != 0)
21231: goto exit_error;
21232:
21233: /*
21234: * Finally we can build the automaton from the content model of
21235: * complex types.
21236: */
21237:
21238: for (i = 0; i < nbItems; i++) {
21239: item = items[i];
21240: switch (item->type) {
21241: case XML_SCHEMA_TYPE_COMPLEX:
21242: xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21243: /* FIXHFAILURE; */
21244: break;
21245: default:
21246: break;
21247: }
21248: }
21249: if (pctxt->nberrors != 0)
21250: goto exit_error;
21251: /*
21252: * URGENT TODO: cos-element-consistent
21253: */
21254: goto exit;
21255:
21256: exit_error:
21257: ret = pctxt->err;
21258: goto exit;
21259:
21260: exit_failure:
21261: ret = -1;
21262:
21263: exit:
21264: /*
21265: * Reset the constructor. This is needed for XSI acquisition, since
21266: * those items will be processed over and over again for every XSI
21267: * if not cleared here.
21268: */
21269: con->bucket = oldbucket;
21270: con->pending->nbItems = 0;
21271: if (con->substGroups != NULL) {
21272: xmlHashFree(con->substGroups,
21273: (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21274: con->substGroups = NULL;
21275: }
21276: if (con->redefs != NULL) {
21277: xmlSchemaRedefListFree(con->redefs);
21278: con->redefs = NULL;
21279: }
21280: return(ret);
21281: }
21282: /**
21283: * xmlSchemaParse:
21284: * @ctxt: a schema validation context
21285: *
21286: * parse a schema definition resource and build an internal
21287: * XML Shema struture which can be used to validate instances.
21288: *
21289: * Returns the internal XML Schema structure built from the resource or
21290: * NULL in case of error
21291: */
21292: xmlSchemaPtr
21293: xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21294: {
21295: xmlSchemaPtr mainSchema = NULL;
21296: xmlSchemaBucketPtr bucket = NULL;
21297: int res;
21298:
21299: /*
21300: * This one is used if the schema to be parsed was specified via
21301: * the API; i.e. not automatically by the validated instance document.
21302: */
21303:
21304: xmlSchemaInitTypes();
21305:
21306: if (ctxt == NULL)
21307: return (NULL);
21308:
21309: /* TODO: Init the context. Is this all we need?*/
21310: ctxt->nberrors = 0;
21311: ctxt->err = 0;
21312: ctxt->counter = 0;
21313:
21314: /* Create the *main* schema. */
21315: mainSchema = xmlSchemaNewSchema(ctxt);
21316: if (mainSchema == NULL)
21317: goto exit_failure;
21318: /*
21319: * Create the schema constructor.
21320: */
21321: if (ctxt->constructor == NULL) {
21322: ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21323: if (ctxt->constructor == NULL)
21324: return(NULL);
21325: /* Take ownership of the constructor to be able to free it. */
21326: ctxt->ownsConstructor = 1;
21327: }
21328: ctxt->constructor->mainSchema = mainSchema;
21329: /*
21330: * Locate and add the schema document.
21331: */
21332: res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21333: ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21334: NULL, NULL, &bucket);
21335: if (res == -1)
21336: goto exit_failure;
21337: if (res != 0)
21338: goto exit;
21339:
21340: if (bucket == NULL) {
21341: /* TODO: Error code, actually we failed to *locate* the schema. */
21342: if (ctxt->URL)
21343: xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21344: NULL, NULL,
21345: "Failed to locate the main schema resource at '%s'",
21346: ctxt->URL, NULL);
21347: else
21348: xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21349: NULL, NULL,
21350: "Failed to locate the main schema resource",
21351: NULL, NULL);
21352: goto exit;
21353: }
21354: /* Then do the parsing for good. */
21355: if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21356: goto exit_failure;
21357: if (ctxt->nberrors != 0)
21358: goto exit;
21359:
21360: mainSchema->doc = bucket->doc;
21361: mainSchema->preserve = ctxt->preserve;
21362:
21363: ctxt->schema = mainSchema;
21364:
21365: if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21366: goto exit_failure;
21367:
21368: /*
21369: * TODO: This is not nice, since we cannot distinguish from the
21370: * result if there was an internal error or not.
21371: */
21372: exit:
21373: if (ctxt->nberrors != 0) {
21374: if (mainSchema) {
21375: xmlSchemaFree(mainSchema);
21376: mainSchema = NULL;
21377: }
21378: if (ctxt->constructor) {
21379: xmlSchemaConstructionCtxtFree(ctxt->constructor);
21380: ctxt->constructor = NULL;
21381: ctxt->ownsConstructor = 0;
21382: }
21383: }
21384: ctxt->schema = NULL;
21385: return(mainSchema);
21386: exit_failure:
21387: /*
21388: * Quite verbose, but should catch internal errors, which were
21389: * not communitated.
21390: */
21391: if (mainSchema) {
21392: xmlSchemaFree(mainSchema);
21393: mainSchema = NULL;
21394: }
21395: if (ctxt->constructor) {
21396: xmlSchemaConstructionCtxtFree(ctxt->constructor);
21397: ctxt->constructor = NULL;
21398: ctxt->ownsConstructor = 0;
21399: }
21400: PERROR_INT2("xmlSchemaParse",
21401: "An internal error occured");
21402: ctxt->schema = NULL;
21403: return(NULL);
21404: }
21405:
21406: /**
21407: * xmlSchemaSetParserErrors:
21408: * @ctxt: a schema validation context
21409: * @err: the error callback
21410: * @warn: the warning callback
21411: * @ctx: contextual data for the callbacks
21412: *
21413: * Set the callback functions used to handle errors for a validation context
21414: */
21415: void
21416: xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21417: xmlSchemaValidityErrorFunc err,
21418: xmlSchemaValidityWarningFunc warn, void *ctx)
21419: {
21420: if (ctxt == NULL)
21421: return;
21422: ctxt->error = err;
21423: ctxt->warning = warn;
21424: ctxt->errCtxt = ctx;
21425: if (ctxt->vctxt != NULL)
21426: xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21427: }
21428:
21429: /**
21430: * xmlSchemaSetParserStructuredErrors:
21431: * @ctxt: a schema parser context
21432: * @serror: the structured error function
21433: * @ctx: the functions context
21434: *
21435: * Set the structured error callback
21436: */
21437: void
21438: xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21439: xmlStructuredErrorFunc serror,
21440: void *ctx)
21441: {
21442: if (ctxt == NULL)
21443: return;
21444: ctxt->serror = serror;
21445: ctxt->errCtxt = ctx;
21446: if (ctxt->vctxt != NULL)
21447: xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21448: }
21449:
21450: /**
21451: * xmlSchemaGetParserErrors:
21452: * @ctxt: a XMl-Schema parser context
21453: * @err: the error callback result
21454: * @warn: the warning callback result
21455: * @ctx: contextual data for the callbacks result
21456: *
21457: * Get the callback information used to handle errors for a parser context
21458: *
21459: * Returns -1 in case of failure, 0 otherwise
21460: */
21461: int
21462: xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21463: xmlSchemaValidityErrorFunc * err,
21464: xmlSchemaValidityWarningFunc * warn, void **ctx)
21465: {
21466: if (ctxt == NULL)
21467: return(-1);
21468: if (err != NULL)
21469: *err = ctxt->error;
21470: if (warn != NULL)
21471: *warn = ctxt->warning;
21472: if (ctx != NULL)
21473: *ctx = ctxt->errCtxt;
21474: return(0);
21475: }
21476:
21477: /**
21478: * xmlSchemaFacetTypeToString:
21479: * @type: the facet type
21480: *
21481: * Convert the xmlSchemaTypeType to a char string.
21482: *
21483: * Returns the char string representation of the facet type if the
21484: * type is a facet and an "Internal Error" string otherwise.
21485: */
21486: static const xmlChar *
21487: xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21488: {
21489: switch (type) {
21490: case XML_SCHEMA_FACET_PATTERN:
21491: return (BAD_CAST "pattern");
21492: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21493: return (BAD_CAST "maxExclusive");
21494: case XML_SCHEMA_FACET_MAXINCLUSIVE:
21495: return (BAD_CAST "maxInclusive");
21496: case XML_SCHEMA_FACET_MINEXCLUSIVE:
21497: return (BAD_CAST "minExclusive");
21498: case XML_SCHEMA_FACET_MININCLUSIVE:
21499: return (BAD_CAST "minInclusive");
21500: case XML_SCHEMA_FACET_WHITESPACE:
21501: return (BAD_CAST "whiteSpace");
21502: case XML_SCHEMA_FACET_ENUMERATION:
21503: return (BAD_CAST "enumeration");
21504: case XML_SCHEMA_FACET_LENGTH:
21505: return (BAD_CAST "length");
21506: case XML_SCHEMA_FACET_MAXLENGTH:
21507: return (BAD_CAST "maxLength");
21508: case XML_SCHEMA_FACET_MINLENGTH:
21509: return (BAD_CAST "minLength");
21510: case XML_SCHEMA_FACET_TOTALDIGITS:
21511: return (BAD_CAST "totalDigits");
21512: case XML_SCHEMA_FACET_FRACTIONDIGITS:
21513: return (BAD_CAST "fractionDigits");
21514: default:
21515: break;
21516: }
21517: return (BAD_CAST "Internal Error");
21518: }
21519:
21520: static xmlSchemaWhitespaceValueType
21521: xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21522: {
21523: /*
21524: * The normalization type can be changed only for types which are derived
21525: * from xsd:string.
21526: */
21527: if (type->type == XML_SCHEMA_TYPE_BASIC) {
21528: /*
21529: * Note that we assume a whitespace of preserve for anySimpleType.
21530: */
21531: if ((type->builtInType == XML_SCHEMAS_STRING) ||
21532: (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21533: return(XML_SCHEMA_WHITESPACE_PRESERVE);
21534: else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21535: return(XML_SCHEMA_WHITESPACE_REPLACE);
21536: else {
21537: /*
21538: * For all �atomic� datatypes other than string (and types �derived�
21539: * by �restriction� from it) the value of whiteSpace is fixed to
21540: * collapse
21541: * Note that this includes built-in list datatypes.
21542: */
21543: return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21544: }
21545: } else if (WXS_IS_LIST(type)) {
21546: /*
21547: * For list types the facet "whiteSpace" is fixed to "collapse".
21548: */
21549: return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21550: } else if (WXS_IS_UNION(type)) {
21551: return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21552: } else if (WXS_IS_ATOMIC(type)) {
21553: if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21554: return (XML_SCHEMA_WHITESPACE_PRESERVE);
21555: else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21556: return (XML_SCHEMA_WHITESPACE_REPLACE);
21557: else
21558: return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21559: }
21560: return (-1);
21561: }
21562:
21563: /************************************************************************
1.1.1.3 ! misho 21564: * *
! 21565: * Simple type validation *
! 21566: * *
1.1 misho 21567: ************************************************************************/
21568:
21569:
21570: /************************************************************************
1.1.1.3 ! misho 21571: * *
! 21572: * DOM Validation code *
! 21573: * *
1.1 misho 21574: ************************************************************************/
21575:
21576: /**
21577: * xmlSchemaAssembleByLocation:
21578: * @pctxt: a schema parser context
21579: * @vctxt: a schema validation context
21580: * @schema: the existing schema
21581: * @node: the node that fired the assembling
21582: * @nsName: the namespace name of the new schema
21583: * @location: the location of the schema
21584: *
21585: * Expands an existing schema by an additional schema.
21586: *
21587: * Returns 0 if the new schema is correct, a positive error code
21588: * number otherwise and -1 in case of an internal or API error.
21589: */
21590: static int
21591: xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21592: xmlSchemaPtr schema,
21593: xmlNodePtr node,
21594: const xmlChar *nsName,
21595: const xmlChar *location)
21596: {
21597: int ret = 0;
21598: xmlSchemaParserCtxtPtr pctxt;
21599: xmlSchemaBucketPtr bucket = NULL;
21600:
21601: if ((vctxt == NULL) || (schema == NULL))
21602: return (-1);
21603:
21604: if (vctxt->pctxt == NULL) {
21605: VERROR_INT("xmlSchemaAssembleByLocation",
21606: "no parser context available");
21607: return(-1);
21608: }
21609: pctxt = vctxt->pctxt;
21610: if (pctxt->constructor == NULL) {
21611: PERROR_INT("xmlSchemaAssembleByLocation",
21612: "no constructor");
21613: return(-1);
21614: }
21615: /*
21616: * Acquire the schema document.
21617: */
21618: location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21619: location, node);
21620: /*
21621: * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21622: * the process will automatically change this to
21623: * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21624: */
21625: ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21626: location, NULL, NULL, 0, node, NULL, nsName,
21627: &bucket);
21628: if (ret != 0)
21629: return(ret);
21630: if (bucket == NULL) {
21631: /*
21632: * Generate a warning that the document could not be located.
21633: */
21634: xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21635: node, NULL,
21636: "The document at location '%s' could not be acquired",
21637: location, NULL, NULL);
21638: return(ret);
21639: }
21640: /*
21641: * The first located schema will be handled as if all other
21642: * schemas imported by XSI were imported by this first schema.
21643: */
21644: if ((bucket != NULL) &&
21645: (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21646: WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21647: /*
21648: * TODO: Is this handled like an import? I.e. is it not an error
21649: * if the schema cannot be located?
21650: */
21651: if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21652: return(0);
21653: /*
21654: * We will reuse the parser context for every schema imported
21655: * directly via XSI. So reset the context.
21656: */
21657: pctxt->nberrors = 0;
21658: pctxt->err = 0;
21659: pctxt->doc = bucket->doc;
21660:
21661: ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21662: if (ret == -1) {
21663: pctxt->doc = NULL;
21664: goto exit_failure;
21665: }
21666: /* Paranoid error channelling. */
21667: if ((ret == 0) && (pctxt->nberrors != 0))
21668: ret = pctxt->err;
21669: if (pctxt->nberrors == 0) {
21670: /*
21671: * Only bother to fixup pending components, if there was
21672: * no error yet.
21673: * For every XSI acquired schema (and its sub-schemata) we will
21674: * fixup the components.
21675: */
21676: xmlSchemaFixupComponents(pctxt, bucket);
21677: ret = pctxt->err;
21678: /*
21679: * Not nice, but we need somehow to channel the schema parser
21680: * error to the validation context.
21681: */
21682: if ((ret != 0) && (vctxt->err == 0))
21683: vctxt->err = ret;
21684: vctxt->nberrors += pctxt->nberrors;
21685: } else {
21686: /* Add to validation error sum. */
21687: vctxt->nberrors += pctxt->nberrors;
21688: }
21689: pctxt->doc = NULL;
21690: return(ret);
21691: exit_failure:
21692: pctxt->doc = NULL;
21693: return (-1);
21694: }
21695:
21696: static xmlSchemaAttrInfoPtr
21697: xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21698: int metaType)
21699: {
21700: if (vctxt->nbAttrInfos == 0)
21701: return (NULL);
21702: {
21703: int i;
21704: xmlSchemaAttrInfoPtr iattr;
21705:
21706: for (i = 0; i < vctxt->nbAttrInfos; i++) {
21707: iattr = vctxt->attrInfos[i];
21708: if (iattr->metaType == metaType)
21709: return (iattr);
21710: }
21711:
21712: }
21713: return (NULL);
21714: }
21715:
21716: /**
21717: * xmlSchemaAssembleByXSI:
21718: * @vctxt: a schema validation context
21719: *
21720: * Expands an existing schema by an additional schema using
21721: * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21722: * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21723: * must be set to 1.
21724: *
21725: * Returns 0 if the new schema is correct, a positive error code
21726: * number otherwise and -1 in case of an internal or API error.
21727: */
21728: static int
21729: xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21730: {
21731: const xmlChar *cur, *end;
21732: const xmlChar *nsname = NULL, *location;
21733: int count = 0;
21734: int ret = 0;
21735: xmlSchemaAttrInfoPtr iattr;
21736:
21737: /*
21738: * Parse the value; we will assume an even number of values
21739: * to be given (this is how Xerces and XSV work).
21740: *
21741: * URGENT TODO: !! This needs to work for both
21742: * @noNamespaceSchemaLocation AND @schemaLocation on the same
21743: * element !!
21744: */
21745: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21746: XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21747: if (iattr == NULL)
21748: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21749: XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21750: if (iattr == NULL)
21751: return (0);
21752: cur = iattr->value;
21753: do {
21754: /*
21755: * TODO: Move the string parsing mechanism away from here.
21756: */
21757: if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21758: /*
21759: * Get the namespace name.
21760: */
21761: while (IS_BLANK_CH(*cur))
21762: cur++;
21763: end = cur;
21764: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21765: end++;
21766: if (end == cur)
21767: break;
21768: count++; /* TODO: Don't use the schema's dict. */
21769: nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21770: cur = end;
21771: }
21772: /*
21773: * Get the URI.
21774: */
21775: while (IS_BLANK_CH(*cur))
21776: cur++;
21777: end = cur;
21778: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21779: end++;
21780: if (end == cur) {
21781: if (iattr->metaType ==
21782: XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21783: {
21784: /*
21785: * If using @schemaLocation then tuples are expected.
21786: * I.e. the namespace name *and* the document's URI.
21787: */
21788: xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21789: iattr->node, NULL,
21790: "The value must consist of tuples: the target namespace "
21791: "name and the document's URI", NULL, NULL, NULL);
21792: }
21793: break;
21794: }
21795: count++; /* TODO: Don't use the schema's dict. */
21796: location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21797: cur = end;
21798: ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21799: iattr->node, nsname, location);
21800: if (ret == -1) {
21801: VERROR_INT("xmlSchemaAssembleByXSI",
21802: "assembling schemata");
21803: return (-1);
21804: }
21805: } while (*cur != 0);
21806: return (ret);
21807: }
21808:
21809: static const xmlChar *
21810: xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21811: const xmlChar *prefix)
21812: {
21813: if (vctxt->sax != NULL) {
21814: int i, j;
21815: xmlSchemaNodeInfoPtr inode;
21816:
21817: for (i = vctxt->depth; i >= 0; i--) {
21818: if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21819: inode = vctxt->elemInfos[i];
21820: for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21821: if (((prefix == NULL) &&
21822: (inode->nsBindings[j] == NULL)) ||
21823: ((prefix != NULL) && xmlStrEqual(prefix,
21824: inode->nsBindings[j]))) {
21825:
21826: /*
21827: * Note that the namespace bindings are already
21828: * in a string dict.
21829: */
21830: return (inode->nsBindings[j+1]);
21831: }
21832: }
21833: }
21834: }
21835: return (NULL);
21836: #ifdef LIBXML_READER_ENABLED
21837: } else if (vctxt->reader != NULL) {
21838: xmlChar *nsName;
21839:
21840: nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21841: if (nsName != NULL) {
21842: const xmlChar *ret;
21843:
21844: ret = xmlDictLookup(vctxt->dict, nsName, -1);
21845: xmlFree(nsName);
21846: return (ret);
21847: } else
21848: return (NULL);
21849: #endif
21850: } else {
21851: xmlNsPtr ns;
21852:
21853: if ((vctxt->inode->node == NULL) ||
21854: (vctxt->inode->node->doc == NULL)) {
21855: VERROR_INT("xmlSchemaLookupNamespace",
21856: "no node or node's doc avaliable");
21857: return (NULL);
21858: }
21859: ns = xmlSearchNs(vctxt->inode->node->doc,
21860: vctxt->inode->node, prefix);
21861: if (ns != NULL)
21862: return (ns->href);
21863: return (NULL);
21864: }
21865: }
21866:
21867: /*
21868: * This one works on the schema of the validation context.
21869: */
21870: static int
21871: xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21872: xmlSchemaPtr schema,
21873: xmlNodePtr node,
21874: const xmlChar *value,
21875: xmlSchemaValPtr *val,
21876: int valNeeded)
21877: {
21878: int ret;
21879:
21880: if (vctxt && (vctxt->schema == NULL)) {
21881: VERROR_INT("xmlSchemaValidateNotation",
21882: "a schema is needed on the validation context");
21883: return (-1);
21884: }
21885: ret = xmlValidateQName(value, 1);
21886: if (ret != 0)
21887: return (ret);
21888: {
21889: xmlChar *localName = NULL;
21890: xmlChar *prefix = NULL;
21891:
21892: localName = xmlSplitQName2(value, &prefix);
21893: if (prefix != NULL) {
21894: const xmlChar *nsName = NULL;
21895:
21896: if (vctxt != NULL)
21897: nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21898: else if (node != NULL) {
21899: xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21900: if (ns != NULL)
21901: nsName = ns->href;
21902: } else {
21903: xmlFree(prefix);
21904: xmlFree(localName);
21905: return (1);
21906: }
21907: if (nsName == NULL) {
21908: xmlFree(prefix);
21909: xmlFree(localName);
21910: return (1);
21911: }
21912: if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21913: if ((valNeeded) && (val != NULL)) {
21914: (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21915: xmlStrdup(nsName));
21916: if (*val == NULL)
21917: ret = -1;
21918: }
21919: } else
21920: ret = 1;
21921: xmlFree(prefix);
21922: xmlFree(localName);
21923: } else {
21924: if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21925: if (valNeeded && (val != NULL)) {
21926: (*val) = xmlSchemaNewNOTATIONValue(
21927: BAD_CAST xmlStrdup(value), NULL);
21928: if (*val == NULL)
21929: ret = -1;
21930: }
21931: } else
21932: return (1);
21933: }
21934: }
21935: return (ret);
21936: }
21937:
21938: static int
21939: xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21940: const xmlChar* lname,
21941: const xmlChar* nsname)
21942: {
21943: int i;
21944:
21945: lname = xmlDictLookup(vctxt->dict, lname, -1);
21946: if (lname == NULL)
21947: return(-1);
21948: if (nsname != NULL) {
21949: nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21950: if (nsname == NULL)
21951: return(-1);
21952: }
21953: for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21954: if ((vctxt->nodeQNames->items [i] == lname) &&
21955: (vctxt->nodeQNames->items[i +1] == nsname))
21956: /* Already there */
21957: return(i);
21958: }
21959: /* Add new entry. */
21960: i = vctxt->nodeQNames->nbItems;
21961: xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21962: xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21963: return(i);
21964: }
21965:
21966: /************************************************************************
1.1.1.3 ! misho 21967: * *
1.1 misho 21968: * Validation of identity-constraints (IDC) *
1.1.1.3 ! misho 21969: * *
1.1 misho 21970: ************************************************************************/
21971:
21972: /**
21973: * xmlSchemaAugmentIDC:
21974: * @idcDef: the IDC definition
21975: *
21976: * Creates an augmented IDC definition item.
21977: *
21978: * Returns the item, or NULL on internal errors.
21979: */
21980: static void
21981: xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21982: xmlSchemaValidCtxtPtr vctxt)
21983: {
21984: xmlSchemaIDCAugPtr aidc;
21985:
21986: aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21987: if (aidc == NULL) {
21988: xmlSchemaVErrMemory(vctxt,
21989: "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21990: NULL);
21991: return;
21992: }
21993: aidc->keyrefDepth = -1;
21994: aidc->def = idcDef;
21995: aidc->next = NULL;
21996: if (vctxt->aidcs == NULL)
21997: vctxt->aidcs = aidc;
21998: else {
21999: aidc->next = vctxt->aidcs;
22000: vctxt->aidcs = aidc;
22001: }
22002: /*
22003: * Save if we have keyrefs at all.
22004: */
22005: if ((vctxt->hasKeyrefs == 0) &&
22006: (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22007: vctxt->hasKeyrefs = 1;
22008: }
22009:
22010: /**
22011: * xmlSchemaAugmentImportedIDC:
22012: * @imported: the imported schema
22013: *
22014: * Creates an augmented IDC definition for the imported schema.
22015: */
22016: static void
22017: xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
22018: if (imported->schema->idcDef != NULL) {
22019: xmlHashScan(imported->schema->idcDef ,
22020: (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
22021: }
22022: }
22023:
22024: /**
22025: * xmlSchemaIDCNewBinding:
22026: * @idcDef: the IDC definition of this binding
22027: *
22028: * Creates a new IDC binding.
22029: *
22030: * Returns the new IDC binding, NULL on internal errors.
22031: */
22032: static xmlSchemaPSVIIDCBindingPtr
22033: xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22034: {
22035: xmlSchemaPSVIIDCBindingPtr ret;
22036:
22037: ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22038: sizeof(xmlSchemaPSVIIDCBinding));
22039: if (ret == NULL) {
22040: xmlSchemaVErrMemory(NULL,
22041: "allocating a PSVI IDC binding item", NULL);
22042: return (NULL);
22043: }
22044: memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22045: ret->definition = idcDef;
22046: return (ret);
22047: }
22048:
22049: /**
22050: * xmlSchemaIDCStoreNodeTableItem:
22051: * @vctxt: the WXS validation context
22052: * @item: the IDC node table item
22053: *
22054: * The validation context is used to store IDC node table items.
22055: * They are stored to avoid copying them if IDC node-tables are merged
22056: * with corresponding parent IDC node-tables (bubbling).
22057: *
22058: * Returns 0 if succeeded, -1 on internal errors.
22059: */
22060: static int
22061: xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22062: xmlSchemaPSVIIDCNodePtr item)
22063: {
22064: /*
22065: * Add to gobal list.
22066: */
22067: if (vctxt->idcNodes == NULL) {
22068: vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22069: xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22070: if (vctxt->idcNodes == NULL) {
22071: xmlSchemaVErrMemory(vctxt,
22072: "allocating the IDC node table item list", NULL);
22073: return (-1);
22074: }
22075: vctxt->sizeIdcNodes = 20;
22076: } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22077: vctxt->sizeIdcNodes *= 2;
22078: vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22079: xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22080: sizeof(xmlSchemaPSVIIDCNodePtr));
22081: if (vctxt->idcNodes == NULL) {
22082: xmlSchemaVErrMemory(vctxt,
22083: "re-allocating the IDC node table item list", NULL);
22084: return (-1);
22085: }
22086: }
22087: vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22088:
22089: return (0);
22090: }
22091:
22092: /**
22093: * xmlSchemaIDCStoreKey:
22094: * @vctxt: the WXS validation context
22095: * @item: the IDC key
22096: *
22097: * The validation context is used to store an IDC key.
22098: *
22099: * Returns 0 if succeeded, -1 on internal errors.
22100: */
22101: static int
22102: xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22103: xmlSchemaPSVIIDCKeyPtr key)
22104: {
22105: /*
22106: * Add to gobal list.
22107: */
22108: if (vctxt->idcKeys == NULL) {
22109: vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22110: xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22111: if (vctxt->idcKeys == NULL) {
22112: xmlSchemaVErrMemory(vctxt,
22113: "allocating the IDC key storage list", NULL);
22114: return (-1);
22115: }
22116: vctxt->sizeIdcKeys = 40;
22117: } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22118: vctxt->sizeIdcKeys *= 2;
22119: vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22120: xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22121: sizeof(xmlSchemaPSVIIDCKeyPtr));
22122: if (vctxt->idcKeys == NULL) {
22123: xmlSchemaVErrMemory(vctxt,
22124: "re-allocating the IDC key storage list", NULL);
22125: return (-1);
22126: }
22127: }
22128: vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22129:
22130: return (0);
22131: }
22132:
22133: /**
22134: * xmlSchemaIDCAppendNodeTableItem:
22135: * @bind: the IDC binding
22136: * @ntItem: the node-table item
22137: *
22138: * Appends the IDC node-table item to the binding.
22139: *
22140: * Returns 0 on success and -1 on internal errors.
22141: */
22142: static int
22143: xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22144: xmlSchemaPSVIIDCNodePtr ntItem)
22145: {
22146: if (bind->nodeTable == NULL) {
22147: bind->sizeNodes = 10;
22148: bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22149: xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22150: if (bind->nodeTable == NULL) {
22151: xmlSchemaVErrMemory(NULL,
22152: "allocating an array of IDC node-table items", NULL);
22153: return(-1);
22154: }
22155: } else if (bind->sizeNodes <= bind->nbNodes) {
22156: bind->sizeNodes *= 2;
22157: bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22158: xmlRealloc(bind->nodeTable, bind->sizeNodes *
22159: sizeof(xmlSchemaPSVIIDCNodePtr));
22160: if (bind->nodeTable == NULL) {
22161: xmlSchemaVErrMemory(NULL,
22162: "re-allocating an array of IDC node-table items", NULL);
22163: return(-1);
22164: }
22165: }
22166: bind->nodeTable[bind->nbNodes++] = ntItem;
22167: return(0);
22168: }
22169:
22170: /**
22171: * xmlSchemaIDCAcquireBinding:
22172: * @vctxt: the WXS validation context
22173: * @matcher: the IDC matcher
22174: *
22175: * Looks up an PSVI IDC binding, for the IDC definition and
22176: * of the given matcher. If none found, a new one is created
22177: * and added to the IDC table.
22178: *
22179: * Returns an IDC binding or NULL on internal errors.
22180: */
22181: static xmlSchemaPSVIIDCBindingPtr
22182: xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22183: xmlSchemaIDCMatcherPtr matcher)
22184: {
22185: xmlSchemaNodeInfoPtr ielem;
22186:
22187: ielem = vctxt->elemInfos[matcher->depth];
22188:
22189: if (ielem->idcTable == NULL) {
22190: ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22191: if (ielem->idcTable == NULL)
22192: return (NULL);
22193: return(ielem->idcTable);
22194: } else {
22195: xmlSchemaPSVIIDCBindingPtr bind = NULL;
22196:
22197: bind = ielem->idcTable;
22198: do {
22199: if (bind->definition == matcher->aidc->def)
22200: return(bind);
22201: if (bind->next == NULL) {
22202: bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22203: if (bind->next == NULL)
22204: return (NULL);
22205: return(bind->next);
22206: }
22207: bind = bind->next;
22208: } while (bind != NULL);
22209: }
22210: return (NULL);
22211: }
22212:
22213: static xmlSchemaItemListPtr
22214: xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22215: xmlSchemaIDCMatcherPtr matcher)
22216: {
22217: if (matcher->targets == NULL)
22218: matcher->targets = xmlSchemaItemListCreate();
22219: return(matcher->targets);
22220: }
22221:
22222: /**
22223: * xmlSchemaIDCFreeKey:
22224: * @key: the IDC key
22225: *
22226: * Frees an IDC key together with its compiled value.
22227: */
22228: static void
22229: xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22230: {
22231: if (key->val != NULL)
22232: xmlSchemaFreeValue(key->val);
22233: xmlFree(key);
22234: }
22235:
22236: /**
22237: * xmlSchemaIDCFreeBinding:
22238: *
22239: * Frees an IDC binding. Note that the node table-items
22240: * are not freed.
22241: */
22242: static void
22243: xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22244: {
22245: if (bind->nodeTable != NULL)
22246: xmlFree(bind->nodeTable);
22247: if (bind->dupls != NULL)
22248: xmlSchemaItemListFree(bind->dupls);
22249: xmlFree(bind);
22250: }
22251:
22252: /**
22253: * xmlSchemaIDCFreeIDCTable:
22254: * @bind: the first IDC binding in the list
22255: *
22256: * Frees an IDC table, i.e. all the IDC bindings in the list.
22257: */
22258: static void
22259: xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22260: {
22261: xmlSchemaPSVIIDCBindingPtr prev;
22262:
22263: while (bind != NULL) {
22264: prev = bind;
22265: bind = bind->next;
22266: xmlSchemaIDCFreeBinding(prev);
22267: }
22268: }
22269:
22270: /**
22271: * xmlSchemaIDCFreeMatcherList:
22272: * @matcher: the first IDC matcher in the list
22273: *
22274: * Frees a list of IDC matchers.
22275: */
22276: static void
22277: xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22278: {
22279: xmlSchemaIDCMatcherPtr next;
22280:
22281: while (matcher != NULL) {
22282: next = matcher->next;
22283: if (matcher->keySeqs != NULL) {
22284: int i;
22285: for (i = 0; i < matcher->sizeKeySeqs; i++)
22286: if (matcher->keySeqs[i] != NULL)
22287: xmlFree(matcher->keySeqs[i]);
22288: xmlFree(matcher->keySeqs);
22289: }
22290: if (matcher->targets != NULL) {
22291: if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22292: int i;
22293: xmlSchemaPSVIIDCNodePtr idcNode;
22294: /*
22295: * Node-table items for keyrefs are not stored globally
22296: * to the validation context, since they are not bubbled.
22297: * We need to free them here.
22298: */
22299: for (i = 0; i < matcher->targets->nbItems; i++) {
22300: idcNode =
22301: (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22302: xmlFree(idcNode->keys);
22303: xmlFree(idcNode);
22304: }
22305: }
22306: xmlSchemaItemListFree(matcher->targets);
22307: }
22308: xmlFree(matcher);
22309: matcher = next;
22310: }
22311: }
22312:
22313: /**
22314: * xmlSchemaIDCReleaseMatcherList:
22315: * @vctxt: the WXS validation context
22316: * @matcher: the first IDC matcher in the list
22317: *
22318: * Caches a list of IDC matchers for reuse.
22319: */
22320: static void
22321: xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22322: xmlSchemaIDCMatcherPtr matcher)
22323: {
22324: xmlSchemaIDCMatcherPtr next;
22325:
22326: while (matcher != NULL) {
22327: next = matcher->next;
22328: if (matcher->keySeqs != NULL) {
22329: int i;
22330: /*
22331: * Don't free the array, but only the content.
22332: */
22333: for (i = 0; i < matcher->sizeKeySeqs; i++)
22334: if (matcher->keySeqs[i] != NULL) {
22335: xmlFree(matcher->keySeqs[i]);
22336: matcher->keySeqs[i] = NULL;
22337: }
22338: }
22339: if (matcher->targets) {
22340: if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22341: int i;
22342: xmlSchemaPSVIIDCNodePtr idcNode;
22343: /*
22344: * Node-table items for keyrefs are not stored globally
22345: * to the validation context, since they are not bubbled.
22346: * We need to free them here.
22347: */
22348: for (i = 0; i < matcher->targets->nbItems; i++) {
22349: idcNode =
22350: (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22351: xmlFree(idcNode->keys);
22352: xmlFree(idcNode);
22353: }
22354: }
22355: xmlSchemaItemListFree(matcher->targets);
22356: matcher->targets = NULL;
22357: }
22358: matcher->next = NULL;
22359: /*
22360: * Cache the matcher.
22361: */
22362: if (vctxt->idcMatcherCache != NULL)
22363: matcher->nextCached = vctxt->idcMatcherCache;
22364: vctxt->idcMatcherCache = matcher;
22365:
22366: matcher = next;
22367: }
22368: }
22369:
22370: /**
22371: * xmlSchemaIDCAddStateObject:
22372: * @vctxt: the WXS validation context
22373: * @matcher: the IDC matcher
22374: * @sel: the XPath information
22375: * @parent: the parent "selector" state object if any
22376: * @type: "selector" or "field"
22377: *
22378: * Creates/reuses and activates state objects for the given
22379: * XPath information; if the XPath expression consists of unions,
22380: * multiple state objects are created for every unioned expression.
22381: *
22382: * Returns 0 on success and -1 on internal errors.
22383: */
22384: static int
22385: xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22386: xmlSchemaIDCMatcherPtr matcher,
22387: xmlSchemaIDCSelectPtr sel,
22388: int type)
22389: {
22390: xmlSchemaIDCStateObjPtr sto;
22391:
22392: /*
22393: * Reuse the state objects from the pool.
22394: */
22395: if (vctxt->xpathStatePool != NULL) {
22396: sto = vctxt->xpathStatePool;
22397: vctxt->xpathStatePool = sto->next;
22398: sto->next = NULL;
22399: } else {
22400: /*
22401: * Create a new state object.
22402: */
22403: sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22404: if (sto == NULL) {
22405: xmlSchemaVErrMemory(NULL,
22406: "allocating an IDC state object", NULL);
22407: return (-1);
22408: }
22409: memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22410: }
22411: /*
22412: * Add to global list.
22413: */
22414: if (vctxt->xpathStates != NULL)
22415: sto->next = vctxt->xpathStates;
22416: vctxt->xpathStates = sto;
22417:
22418: /*
22419: * Free the old xpath validation context.
22420: */
22421: if (sto->xpathCtxt != NULL)
22422: xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22423:
22424: /*
22425: * Create a new XPath (pattern) validation context.
22426: */
22427: sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22428: (xmlPatternPtr) sel->xpathComp);
22429: if (sto->xpathCtxt == NULL) {
22430: VERROR_INT("xmlSchemaIDCAddStateObject",
22431: "failed to create an XPath validation context");
22432: return (-1);
22433: }
22434: sto->type = type;
22435: sto->depth = vctxt->depth;
22436: sto->matcher = matcher;
22437: sto->sel = sel;
22438: sto->nbHistory = 0;
22439:
22440: #ifdef DEBUG_IDC
22441: xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22442: sto->sel->xpath);
22443: #endif
22444: return (0);
22445: }
22446:
22447: /**
22448: * xmlSchemaXPathEvaluate:
22449: * @vctxt: the WXS validation context
22450: * @nodeType: the nodeType of the current node
22451: *
22452: * Evaluates all active XPath state objects.
22453: *
22454: * Returns the number of IC "field" state objects which resolved to
22455: * this node, 0 if none resolved and -1 on internal errors.
22456: */
22457: static int
22458: xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22459: xmlElementType nodeType)
22460: {
22461: xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22462: int res, resolved = 0, depth = vctxt->depth;
22463:
22464: if (vctxt->xpathStates == NULL)
22465: return (0);
22466:
22467: if (nodeType == XML_ATTRIBUTE_NODE)
22468: depth++;
22469: #ifdef DEBUG_IDC
22470: {
22471: xmlChar *str = NULL;
22472: xmlGenericError(xmlGenericErrorContext,
22473: "IDC: EVAL on %s, depth %d, type %d\n",
22474: xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22475: vctxt->inode->localName), depth, nodeType);
22476: FREE_AND_NULL(str)
22477: }
22478: #endif
22479: /*
22480: * Process all active XPath state objects.
22481: */
22482: first = vctxt->xpathStates;
22483: sto = first;
22484: while (sto != head) {
22485: #ifdef DEBUG_IDC
22486: if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22487: xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22488: sto->matcher->aidc->def->name, sto->sel->xpath);
22489: else
22490: xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22491: sto->matcher->aidc->def->name, sto->sel->xpath);
22492: #endif
22493: if (nodeType == XML_ELEMENT_NODE)
22494: res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22495: vctxt->inode->localName, vctxt->inode->nsName);
22496: else
22497: res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22498: vctxt->inode->localName, vctxt->inode->nsName);
22499:
22500: if (res == -1) {
22501: VERROR_INT("xmlSchemaXPathEvaluate",
22502: "calling xmlStreamPush()");
22503: return (-1);
22504: }
22505: if (res == 0)
22506: goto next_sto;
22507: /*
22508: * Full match.
22509: */
22510: #ifdef DEBUG_IDC
22511: xmlGenericError(xmlGenericErrorContext, "IDC: "
22512: "MATCH\n");
22513: #endif
22514: /*
22515: * Register a match in the state object history.
22516: */
22517: if (sto->history == NULL) {
22518: sto->history = (int *) xmlMalloc(5 * sizeof(int));
22519: if (sto->history == NULL) {
22520: xmlSchemaVErrMemory(NULL,
22521: "allocating the state object history", NULL);
22522: return(-1);
22523: }
22524: sto->sizeHistory = 5;
22525: } else if (sto->sizeHistory <= sto->nbHistory) {
22526: sto->sizeHistory *= 2;
22527: sto->history = (int *) xmlRealloc(sto->history,
22528: sto->sizeHistory * sizeof(int));
22529: if (sto->history == NULL) {
22530: xmlSchemaVErrMemory(NULL,
22531: "re-allocating the state object history", NULL);
22532: return(-1);
22533: }
22534: }
22535: sto->history[sto->nbHistory++] = depth;
22536:
22537: #ifdef DEBUG_IDC
22538: xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22539: vctxt->depth);
22540: #endif
22541:
22542: if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22543: xmlSchemaIDCSelectPtr sel;
22544: /*
22545: * Activate state objects for the IDC fields of
22546: * the IDC selector.
22547: */
22548: #ifdef DEBUG_IDC
22549: xmlGenericError(xmlGenericErrorContext, "IDC: "
22550: "activating field states\n");
22551: #endif
22552: sel = sto->matcher->aidc->def->fields;
22553: while (sel != NULL) {
22554: if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22555: sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22556: return (-1);
22557: sel = sel->next;
22558: }
22559: } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22560: /*
22561: * An IDC key node was found by the IDC field.
22562: */
22563: #ifdef DEBUG_IDC
22564: xmlGenericError(xmlGenericErrorContext,
22565: "IDC: key found\n");
22566: #endif
22567: /*
22568: * Notify that the character value of this node is
22569: * needed.
22570: */
22571: if (resolved == 0) {
22572: if ((vctxt->inode->flags &
22573: XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22574: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22575: }
22576: resolved++;
22577: }
22578: next_sto:
22579: if (sto->next == NULL) {
22580: /*
22581: * Evaluate field state objects created on this node as well.
22582: */
22583: head = first;
22584: sto = vctxt->xpathStates;
22585: } else
22586: sto = sto->next;
22587: }
22588: return (resolved);
22589: }
22590:
22591: static const xmlChar *
22592: xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22593: xmlChar **buf,
22594: xmlSchemaPSVIIDCKeyPtr *seq,
22595: int count)
22596: {
22597: int i, res;
22598: xmlChar *value = NULL;
22599:
22600: *buf = xmlStrdup(BAD_CAST "[");
22601: for (i = 0; i < count; i++) {
22602: *buf = xmlStrcat(*buf, BAD_CAST "'");
22603: res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22604: xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22605: &value);
22606: if (res == 0)
22607: *buf = xmlStrcat(*buf, BAD_CAST value);
22608: else {
22609: VERROR_INT("xmlSchemaFormatIDCKeySequence",
22610: "failed to compute a canonical value");
22611: *buf = xmlStrcat(*buf, BAD_CAST "???");
22612: }
22613: if (i < count -1)
22614: *buf = xmlStrcat(*buf, BAD_CAST "', ");
22615: else
22616: *buf = xmlStrcat(*buf, BAD_CAST "'");
22617: if (value != NULL) {
22618: xmlFree(value);
22619: value = NULL;
22620: }
22621: }
22622: *buf = xmlStrcat(*buf, BAD_CAST "]");
22623:
22624: return (BAD_CAST *buf);
22625: }
22626:
22627: /**
22628: * xmlSchemaXPathPop:
22629: * @vctxt: the WXS validation context
22630: *
22631: * Pops all XPath states.
22632: *
22633: * Returns 0 on success and -1 on internal errors.
22634: */
22635: static int
22636: xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22637: {
22638: xmlSchemaIDCStateObjPtr sto;
22639: int res;
22640:
22641: if (vctxt->xpathStates == NULL)
22642: return(0);
22643: sto = vctxt->xpathStates;
22644: do {
22645: res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22646: if (res == -1)
22647: return (-1);
22648: sto = sto->next;
22649: } while (sto != NULL);
22650: return(0);
22651: }
22652:
22653: /**
22654: * xmlSchemaXPathProcessHistory:
22655: * @vctxt: the WXS validation context
22656: * @type: the simple/complex type of the current node if any at all
22657: * @val: the precompiled value
22658: *
22659: * Processes and pops the history items of the IDC state objects.
22660: * IDC key-sequences are validated/created on IDC bindings.
22661: *
22662: * Returns 0 on success and -1 on internal errors.
22663: */
22664: static int
22665: xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22666: int depth)
22667: {
22668: xmlSchemaIDCStateObjPtr sto, nextsto;
22669: int res, matchDepth;
22670: xmlSchemaPSVIIDCKeyPtr key = NULL;
22671: xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22672:
22673: if (vctxt->xpathStates == NULL)
22674: return (0);
22675: sto = vctxt->xpathStates;
22676:
22677: #ifdef DEBUG_IDC
22678: {
22679: xmlChar *str = NULL;
22680: xmlGenericError(xmlGenericErrorContext,
22681: "IDC: BACK on %s, depth %d\n",
22682: xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22683: vctxt->inode->localName), vctxt->depth);
22684: FREE_AND_NULL(str)
22685: }
22686: #endif
22687: /*
22688: * Evaluate the state objects.
22689: */
22690: while (sto != NULL) {
22691: res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22692: if (res == -1) {
22693: VERROR_INT("xmlSchemaXPathProcessHistory",
22694: "calling xmlStreamPop()");
22695: return (-1);
22696: }
22697: #ifdef DEBUG_IDC
22698: xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22699: sto->sel->xpath);
22700: #endif
22701: if (sto->nbHistory == 0)
22702: goto deregister_check;
22703:
22704: matchDepth = sto->history[sto->nbHistory -1];
22705:
22706: /*
22707: * Only matches at the current depth are of interest.
22708: */
22709: if (matchDepth != depth) {
22710: sto = sto->next;
22711: continue;
22712: }
22713: if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22714: /*
22715: * NOTE: According to
22716: * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22717: * ... the simple-content of complex types is also allowed.
22718: */
22719:
22720: if (WXS_IS_COMPLEX(type)) {
22721: if (WXS_HAS_SIMPLE_CONTENT(type)) {
22722: /*
22723: * Sanity check for complex types with simple content.
22724: */
22725: simpleType = type->contentTypeDef;
22726: if (simpleType == NULL) {
22727: VERROR_INT("xmlSchemaXPathProcessHistory",
22728: "field resolves to a CT with simple content "
22729: "but the CT is missing the ST definition");
22730: return (-1);
22731: }
22732: } else
22733: simpleType = NULL;
22734: } else
22735: simpleType = type;
22736: if (simpleType == NULL) {
22737: xmlChar *str = NULL;
22738:
22739: /*
22740: * Not qualified if the field resolves to a node of non
22741: * simple type.
22742: */
22743: xmlSchemaCustomErr(ACTXT_CAST vctxt,
22744: XML_SCHEMAV_CVC_IDC, NULL,
22745: WXS_BASIC_CAST sto->matcher->aidc->def,
22746: "The XPath '%s' of a field of %s does evaluate to a node of "
22747: "non-simple type",
22748: sto->sel->xpath,
22749: xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22750: FREE_AND_NULL(str);
22751: sto->nbHistory--;
22752: goto deregister_check;
22753: }
22754:
22755: if ((key == NULL) && (vctxt->inode->val == NULL)) {
22756: /*
22757: * Failed to provide the normalized value; maybe
22758: * the value was invalid.
22759: */
22760: VERROR(XML_SCHEMAV_CVC_IDC,
22761: WXS_BASIC_CAST sto->matcher->aidc->def,
22762: "Warning: No precomputed value available, the value "
22763: "was either invalid or something strange happend");
22764: sto->nbHistory--;
22765: goto deregister_check;
22766: } else {
22767: xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22768: xmlSchemaPSVIIDCKeyPtr *keySeq;
22769: int pos, idx;
22770:
22771: /*
22772: * The key will be anchored on the matcher's list of
22773: * key-sequences. The position in this list is determined
22774: * by the target node's depth relative to the matcher's
22775: * depth of creation (i.e. the depth of the scope element).
22776: *
22777: * Element Depth Pos List-entries
22778: * <scope> 0 NULL
22779: * <bar> 1 NULL
22780: * <target/> 2 2 target
22781: * <bar>
22782: * </scope>
22783: *
22784: * The size of the list is only dependant on the depth of
22785: * the tree.
22786: * An entry will be NULLed in selector_leave, i.e. when
22787: * we hit the target's
22788: */
22789: pos = sto->depth - matcher->depth;
22790: idx = sto->sel->index;
22791:
22792: /*
22793: * Create/grow the array of key-sequences.
22794: */
22795: if (matcher->keySeqs == NULL) {
22796: if (pos > 9)
22797: matcher->sizeKeySeqs = pos * 2;
22798: else
22799: matcher->sizeKeySeqs = 10;
22800: matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22801: xmlMalloc(matcher->sizeKeySeqs *
22802: sizeof(xmlSchemaPSVIIDCKeyPtr *));
22803: if (matcher->keySeqs == NULL) {
22804: xmlSchemaVErrMemory(NULL,
22805: "allocating an array of key-sequences",
22806: NULL);
22807: return(-1);
22808: }
22809: memset(matcher->keySeqs, 0,
22810: matcher->sizeKeySeqs *
22811: sizeof(xmlSchemaPSVIIDCKeyPtr *));
22812: } else if (pos >= matcher->sizeKeySeqs) {
22813: int i = matcher->sizeKeySeqs;
22814:
22815: matcher->sizeKeySeqs *= 2;
22816: matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22817: xmlRealloc(matcher->keySeqs,
22818: matcher->sizeKeySeqs *
22819: sizeof(xmlSchemaPSVIIDCKeyPtr *));
22820: if (matcher->keySeqs == NULL) {
22821: xmlSchemaVErrMemory(NULL,
22822: "reallocating an array of key-sequences",
22823: NULL);
22824: return (-1);
22825: }
22826: /*
22827: * The array needs to be NULLed.
22828: * TODO: Use memset?
22829: */
22830: for (; i < matcher->sizeKeySeqs; i++)
22831: matcher->keySeqs[i] = NULL;
22832: }
22833:
22834: /*
22835: * Get/create the key-sequence.
22836: */
22837: keySeq = matcher->keySeqs[pos];
22838: if (keySeq == NULL) {
22839: goto create_sequence;
22840: } else if (keySeq[idx] != NULL) {
22841: xmlChar *str = NULL;
22842: /*
22843: * cvc-identity-constraint:
22844: * 3 For each node in the �target node set� all
22845: * of the {fields}, with that node as the context
22846: * node, evaluate to either an empty node-set or
22847: * a node-set with exactly one member, which must
22848: * have a simple type.
22849: *
22850: * The key was already set; report an error.
22851: */
22852: xmlSchemaCustomErr(ACTXT_CAST vctxt,
22853: XML_SCHEMAV_CVC_IDC, NULL,
22854: WXS_BASIC_CAST matcher->aidc->def,
22855: "The XPath '%s' of a field of %s evaluates to a "
22856: "node-set with more than one member",
22857: sto->sel->xpath,
22858: xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22859: FREE_AND_NULL(str);
22860: sto->nbHistory--;
22861: goto deregister_check;
22862: } else
22863: goto create_key;
22864:
22865: create_sequence:
22866: /*
22867: * Create a key-sequence.
22868: */
22869: keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22870: matcher->aidc->def->nbFields *
22871: sizeof(xmlSchemaPSVIIDCKeyPtr));
22872: if (keySeq == NULL) {
22873: xmlSchemaVErrMemory(NULL,
22874: "allocating an IDC key-sequence", NULL);
22875: return(-1);
22876: }
22877: memset(keySeq, 0, matcher->aidc->def->nbFields *
22878: sizeof(xmlSchemaPSVIIDCKeyPtr));
22879: matcher->keySeqs[pos] = keySeq;
22880: create_key:
22881: /*
22882: * Create a key once per node only.
22883: */
22884: if (key == NULL) {
22885: key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22886: sizeof(xmlSchemaPSVIIDCKey));
22887: if (key == NULL) {
22888: xmlSchemaVErrMemory(NULL,
22889: "allocating a IDC key", NULL);
22890: xmlFree(keySeq);
22891: matcher->keySeqs[pos] = NULL;
22892: return(-1);
22893: }
22894: /*
22895: * Consume the compiled value.
22896: */
22897: key->type = simpleType;
22898: key->val = vctxt->inode->val;
22899: vctxt->inode->val = NULL;
22900: /*
22901: * Store the key in a global list.
22902: */
22903: if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22904: xmlSchemaIDCFreeKey(key);
22905: return (-1);
22906: }
22907: }
22908: keySeq[idx] = key;
22909: }
22910: } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22911:
22912: xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22913: /* xmlSchemaPSVIIDCBindingPtr bind; */
22914: xmlSchemaPSVIIDCNodePtr ntItem;
22915: xmlSchemaIDCMatcherPtr matcher;
22916: xmlSchemaIDCPtr idc;
22917: xmlSchemaItemListPtr targets;
22918: int pos, i, j, nbKeys;
22919: /*
22920: * Here we have the following scenario:
22921: * An IDC 'selector' state object resolved to a target node,
22922: * during the time this target node was in the
22923: * ancestor-or-self axis, the 'field' state object(s) looked
22924: * out for matching nodes to create a key-sequence for this
22925: * target node. Now we are back to this target node and need
22926: * to put the key-sequence, together with the target node
22927: * itself, into the node-table of the corresponding IDC
22928: * binding.
22929: */
22930: matcher = sto->matcher;
22931: idc = matcher->aidc->def;
22932: nbKeys = idc->nbFields;
22933: pos = depth - matcher->depth;
22934: /*
22935: * Check if the matcher has any key-sequences at all, plus
22936: * if it has a key-sequence for the current target node.
22937: */
22938: if ((matcher->keySeqs == NULL) ||
22939: (matcher->sizeKeySeqs <= pos)) {
22940: if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22941: goto selector_key_error;
22942: else
22943: goto selector_leave;
22944: }
22945:
22946: keySeq = &(matcher->keySeqs[pos]);
22947: if (*keySeq == NULL) {
22948: if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22949: goto selector_key_error;
22950: else
22951: goto selector_leave;
22952: }
22953:
22954: for (i = 0; i < nbKeys; i++) {
22955: if ((*keySeq)[i] == NULL) {
22956: /*
22957: * Not qualified, if not all fields did resolve.
22958: */
22959: if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22960: /*
22961: * All fields of a "key" IDC must resolve.
22962: */
22963: goto selector_key_error;
22964: }
22965: goto selector_leave;
22966: }
22967: }
22968: /*
22969: * All fields did resolve.
22970: */
22971:
22972: /*
22973: * 4.1 If the {identity-constraint category} is unique(/key),
22974: * then no two members of the �qualified node set� have
22975: * �key-sequences� whose members are pairwise equal, as
22976: * defined by Equal in [XML Schemas: Datatypes].
22977: *
22978: * Get the IDC binding from the matcher and check for
22979: * duplicate key-sequences.
22980: */
22981: #if 0
22982: bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22983: #endif
22984: targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22985: if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22986: (targets->nbItems != 0)) {
22987: xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22988:
22989: i = 0;
22990: res = 0;
22991: /*
22992: * Compare the key-sequences, key by key.
22993: */
22994: do {
22995: bkeySeq =
22996: ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22997: for (j = 0; j < nbKeys; j++) {
22998: ckey = (*keySeq)[j];
22999: bkey = bkeySeq[j];
23000: res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23001: if (res == -1) {
23002: return (-1);
23003: } else if (res == 0) {
23004: /*
23005: * One of the keys differs, so the key-sequence
23006: * won't be equal; get out.
23007: */
23008: break;
23009: }
23010: }
23011: if (res == 1) {
23012: /*
23013: * Duplicate key-sequence found.
23014: */
23015: break;
23016: }
23017: i++;
23018: } while (i < targets->nbItems);
23019: if (i != targets->nbItems) {
23020: xmlChar *str = NULL, *strB = NULL;
23021: /*
23022: * TODO: Try to report the key-sequence.
23023: */
23024: xmlSchemaCustomErr(ACTXT_CAST vctxt,
23025: XML_SCHEMAV_CVC_IDC, NULL,
23026: WXS_BASIC_CAST idc,
23027: "Duplicate key-sequence %s in %s",
23028: xmlSchemaFormatIDCKeySequence(vctxt, &str,
23029: (*keySeq), nbKeys),
23030: xmlSchemaGetIDCDesignation(&strB, idc));
23031: FREE_AND_NULL(str);
23032: FREE_AND_NULL(strB);
23033: goto selector_leave;
23034: }
23035: }
23036: /*
23037: * Add a node-table item to the IDC binding.
23038: */
23039: ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23040: sizeof(xmlSchemaPSVIIDCNode));
23041: if (ntItem == NULL) {
23042: xmlSchemaVErrMemory(NULL,
23043: "allocating an IDC node-table item", NULL);
23044: xmlFree(*keySeq);
23045: *keySeq = NULL;
23046: return(-1);
23047: }
23048: memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23049:
23050: /*
23051: * Store the node-table item in a global list.
23052: */
23053: if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23054: if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23055: xmlFree(ntItem);
23056: xmlFree(*keySeq);
23057: *keySeq = NULL;
23058: return (-1);
23059: }
23060: ntItem->nodeQNameID = -1;
23061: } else {
23062: /*
23063: * Save a cached QName for this node on the IDC node, to be
23064: * able to report it, even if the node is not saved.
23065: */
23066: ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23067: vctxt->inode->localName, vctxt->inode->nsName);
23068: if (ntItem->nodeQNameID == -1) {
23069: xmlFree(ntItem);
23070: xmlFree(*keySeq);
23071: *keySeq = NULL;
23072: return (-1);
23073: }
23074: }
23075: /*
23076: * Init the node-table item: Save the node, position and
23077: * consume the key-sequence.
23078: */
23079: ntItem->node = vctxt->node;
23080: ntItem->nodeLine = vctxt->inode->nodeLine;
23081: ntItem->keys = *keySeq;
23082: *keySeq = NULL;
23083: #if 0
23084: if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23085: #endif
23086: if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23087: if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23088: /*
23089: * Free the item, since keyref items won't be
23090: * put on a global list.
23091: */
23092: xmlFree(ntItem->keys);
23093: xmlFree(ntItem);
23094: }
23095: return (-1);
23096: }
23097:
23098: goto selector_leave;
23099: selector_key_error:
23100: {
23101: xmlChar *str = NULL;
23102: /*
23103: * 4.2.1 (KEY) The �target node set� and the
23104: * �qualified node set� are equal, that is, every
23105: * member of the �target node set� is also a member
23106: * of the �qualified node set� and vice versa.
23107: */
23108: xmlSchemaCustomErr(ACTXT_CAST vctxt,
23109: XML_SCHEMAV_CVC_IDC, NULL,
23110: WXS_BASIC_CAST idc,
23111: "Not all fields of %s evaluate to a node",
23112: xmlSchemaGetIDCDesignation(&str, idc), NULL);
23113: FREE_AND_NULL(str);
23114: }
23115: selector_leave:
23116: /*
23117: * Free the key-sequence if not added to the IDC table.
23118: */
23119: if ((keySeq != NULL) && (*keySeq != NULL)) {
23120: xmlFree(*keySeq);
23121: *keySeq = NULL;
23122: }
23123: } /* if selector */
23124:
23125: sto->nbHistory--;
23126:
23127: deregister_check:
23128: /*
23129: * Deregister state objects if they reach the depth of creation.
23130: */
23131: if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23132: #ifdef DEBUG_IDC
23133: xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
23134: sto->sel->xpath);
23135: #endif
23136: if (vctxt->xpathStates != sto) {
23137: VERROR_INT("xmlSchemaXPathProcessHistory",
23138: "The state object to be removed is not the first "
23139: "in the list");
23140: }
23141: nextsto = sto->next;
23142: /*
23143: * Unlink from the list of active XPath state objects.
23144: */
23145: vctxt->xpathStates = sto->next;
23146: sto->next = vctxt->xpathStatePool;
23147: /*
23148: * Link it to the pool of reusable state objects.
23149: */
23150: vctxt->xpathStatePool = sto;
23151: sto = nextsto;
23152: } else
23153: sto = sto->next;
23154: } /* while (sto != NULL) */
23155: return (0);
23156: }
23157:
23158: /**
23159: * xmlSchemaIDCRegisterMatchers:
23160: * @vctxt: the WXS validation context
23161: * @elemDecl: the element declaration
23162: *
23163: * Creates helper objects to evaluate IDC selectors/fields
23164: * successively.
23165: *
23166: * Returns 0 if OK and -1 on internal errors.
23167: */
23168: static int
23169: xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23170: xmlSchemaElementPtr elemDecl)
23171: {
23172: xmlSchemaIDCMatcherPtr matcher, last = NULL;
23173: xmlSchemaIDCPtr idc, refIdc;
23174: xmlSchemaIDCAugPtr aidc;
23175:
23176: idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23177: if (idc == NULL)
23178: return (0);
23179:
23180: #ifdef DEBUG_IDC
23181: {
23182: xmlChar *str = NULL;
23183: xmlGenericError(xmlGenericErrorContext,
23184: "IDC: REGISTER on %s, depth %d\n",
23185: (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23186: vctxt->inode->localName), vctxt->depth);
23187: FREE_AND_NULL(str)
23188: }
23189: #endif
23190: if (vctxt->inode->idcMatchers != NULL) {
23191: VERROR_INT("xmlSchemaIDCRegisterMatchers",
23192: "The chain of IDC matchers is expected to be empty");
23193: return (-1);
23194: }
23195: do {
23196: if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23197: /*
23198: * Since IDCs bubbles are expensive we need to know the
23199: * depth at which the bubbles should stop; this will be
23200: * the depth of the top-most keyref IDC. If no keyref
23201: * references a key/unique IDC, the keyrefDepth will
23202: * be -1, indicating that no bubbles are needed.
23203: */
23204: refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23205: if (refIdc != NULL) {
23206: /*
23207: * Remember that we have keyrefs on this node.
23208: */
23209: vctxt->inode->hasKeyrefs = 1;
23210: /*
23211: * Lookup the referenced augmented IDC info.
23212: */
23213: aidc = vctxt->aidcs;
23214: while (aidc != NULL) {
23215: if (aidc->def == refIdc)
23216: break;
23217: aidc = aidc->next;
23218: }
23219: if (aidc == NULL) {
23220: VERROR_INT("xmlSchemaIDCRegisterMatchers",
23221: "Could not find an augmented IDC item for an IDC "
23222: "definition");
23223: return (-1);
23224: }
23225: if ((aidc->keyrefDepth == -1) ||
23226: (vctxt->depth < aidc->keyrefDepth))
23227: aidc->keyrefDepth = vctxt->depth;
23228: }
23229: }
23230: /*
23231: * Lookup the augmented IDC item for the IDC definition.
23232: */
23233: aidc = vctxt->aidcs;
23234: while (aidc != NULL) {
23235: if (aidc->def == idc)
23236: break;
23237: aidc = aidc->next;
23238: }
23239: if (aidc == NULL) {
23240: VERROR_INT("xmlSchemaIDCRegisterMatchers",
23241: "Could not find an augmented IDC item for an IDC definition");
23242: return (-1);
23243: }
23244: /*
23245: * Create an IDC matcher for every IDC definition.
23246: */
23247: if (vctxt->idcMatcherCache != NULL) {
23248: /*
23249: * Reuse a cached matcher.
23250: */
23251: matcher = vctxt->idcMatcherCache;
23252: vctxt->idcMatcherCache = matcher->nextCached;
23253: matcher->nextCached = NULL;
23254: } else {
23255: matcher = (xmlSchemaIDCMatcherPtr)
23256: xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23257: if (matcher == NULL) {
23258: xmlSchemaVErrMemory(vctxt,
23259: "allocating an IDC matcher", NULL);
23260: return (-1);
23261: }
23262: memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23263: }
23264: if (last == NULL)
23265: vctxt->inode->idcMatchers = matcher;
23266: else
23267: last->next = matcher;
23268: last = matcher;
23269:
23270: matcher->type = IDC_MATCHER;
23271: matcher->depth = vctxt->depth;
23272: matcher->aidc = aidc;
23273: matcher->idcType = aidc->def->type;
23274: #ifdef DEBUG_IDC
23275: xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
23276: #endif
23277: /*
23278: * Init the automaton state object.
23279: */
23280: if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23281: idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23282: return (-1);
23283:
23284: idc = idc->next;
23285: } while (idc != NULL);
23286: return (0);
23287: }
23288:
23289: static int
23290: xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23291: xmlSchemaNodeInfoPtr ielem)
23292: {
23293: xmlSchemaPSVIIDCBindingPtr bind;
23294: int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23295: xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23296: xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23297:
23298: xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23299: /* vctxt->createIDCNodeTables */
23300: while (matcher != NULL) {
23301: /*
23302: * Skip keyref IDCs and empty IDC target-lists.
23303: */
23304: if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23305: WXS_ILIST_IS_EMPTY(matcher->targets))
23306: {
23307: matcher = matcher->next;
23308: continue;
23309: }
23310: /*
23311: * If we _want_ the IDC node-table to be created in any case
23312: * then do so. Otherwise create them only if keyrefs need them.
23313: */
23314: if ((! vctxt->createIDCNodeTables) &&
23315: ((matcher->aidc->keyrefDepth == -1) ||
23316: (matcher->aidc->keyrefDepth > vctxt->depth)))
23317: {
23318: matcher = matcher->next;
23319: continue;
23320: }
23321: /*
23322: * Get/create the IDC binding on this element for the IDC definition.
23323: */
23324: bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23325:
23326: if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23327: dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23328: nbDupls = bind->dupls->nbItems;
23329: } else {
23330: dupls = NULL;
23331: nbDupls = 0;
23332: }
23333: if (bind->nodeTable != NULL) {
23334: nbNodeTable = bind->nbNodes;
23335: } else {
23336: nbNodeTable = 0;
23337: }
23338:
23339: if ((nbNodeTable == 0) && (nbDupls == 0)) {
23340: /*
23341: * Transfer all IDC target-nodes to the IDC node-table.
23342: */
23343: bind->nodeTable =
23344: (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23345: bind->sizeNodes = matcher->targets->sizeItems;
23346: bind->nbNodes = matcher->targets->nbItems;
23347:
23348: matcher->targets->items = NULL;
23349: matcher->targets->sizeItems = 0;
23350: matcher->targets->nbItems = 0;
23351: } else {
23352: /*
23353: * Compare the key-sequences and add to the IDC node-table.
23354: */
23355: nbTargets = matcher->targets->nbItems;
23356: targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23357: nbFields = matcher->aidc->def->nbFields;
23358: i = 0;
23359: do {
23360: keys = targets[i]->keys;
23361: if (nbDupls) {
23362: /*
23363: * Search in already found duplicates first.
23364: */
23365: j = 0;
23366: do {
23367: if (nbFields == 1) {
23368: res = xmlSchemaAreValuesEqual(keys[0]->val,
23369: dupls[j]->keys[0]->val);
23370: if (res == -1)
23371: goto internal_error;
23372: if (res == 1) {
23373: /*
23374: * Equal key-sequence.
23375: */
23376: goto next_target;
23377: }
23378: } else {
23379: res = 0;
23380: ntkeys = dupls[j]->keys;
23381: for (k = 0; k < nbFields; k++) {
23382: res = xmlSchemaAreValuesEqual(keys[k]->val,
23383: ntkeys[k]->val);
23384: if (res == -1)
23385: goto internal_error;
23386: if (res == 0) {
23387: /*
23388: * One of the keys differs.
23389: */
23390: break;
23391: }
23392: }
23393: if (res == 1) {
23394: /*
23395: * Equal key-sequence found.
23396: */
23397: goto next_target;
23398: }
23399: }
23400: j++;
23401: } while (j < nbDupls);
23402: }
23403: if (nbNodeTable) {
23404: j = 0;
23405: do {
23406: if (nbFields == 1) {
23407: res = xmlSchemaAreValuesEqual(keys[0]->val,
23408: bind->nodeTable[j]->keys[0]->val);
23409: if (res == -1)
23410: goto internal_error;
23411: if (res == 0) {
23412: /*
23413: * The key-sequence differs.
23414: */
23415: goto next_node_table_entry;
23416: }
23417: } else {
23418: res = 0;
23419: ntkeys = bind->nodeTable[j]->keys;
23420: for (k = 0; k < nbFields; k++) {
23421: res = xmlSchemaAreValuesEqual(keys[k]->val,
23422: ntkeys[k]->val);
23423: if (res == -1)
23424: goto internal_error;
23425: if (res == 0) {
23426: /*
23427: * One of the keys differs.
23428: */
23429: goto next_node_table_entry;
23430: }
23431: }
23432: }
23433: /*
23434: * Add the duplicate to the list of duplicates.
23435: */
23436: if (bind->dupls == NULL) {
23437: bind->dupls = xmlSchemaItemListCreate();
23438: if (bind->dupls == NULL)
23439: goto internal_error;
23440: }
23441: if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23442: goto internal_error;
23443: /*
23444: * Remove the duplicate entry from the IDC node-table.
23445: */
23446: bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23447: bind->nbNodes--;
23448:
23449: goto next_target;
23450:
23451: next_node_table_entry:
23452: j++;
23453: } while (j < nbNodeTable);
23454: }
23455: /*
23456: * If everything is fine, then add the IDC target-node to
23457: * the IDC node-table.
23458: */
23459: if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23460: goto internal_error;
23461:
23462: next_target:
23463: i++;
23464: } while (i < nbTargets);
23465: }
23466: matcher = matcher->next;
23467: }
23468: return(0);
23469:
23470: internal_error:
23471: return(-1);
23472: }
23473:
23474: /**
23475: * xmlSchemaBubbleIDCNodeTables:
23476: * @depth: the current tree depth
23477: *
23478: * Merges IDC bindings of an element at @depth into the corresponding IDC
23479: * bindings of its parent element. If a duplicate note-table entry is found,
23480: * both, the parent node-table entry and child entry are discarded from the
23481: * node-table of the parent.
23482: *
23483: * Returns 0 if OK and -1 on internal errors.
23484: */
23485: static int
23486: xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23487: {
23488: xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23489: xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23490: xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23491: xmlSchemaIDCAugPtr aidc;
23492: int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23493:
23494: bind = vctxt->inode->idcTable;
23495: if (bind == NULL) {
23496: /* Fine, no table, no bubbles. */
23497: return (0);
23498: }
23499:
23500: parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23501: /*
23502: * Walk all bindings; create new or add to existing bindings.
23503: * Remove duplicate key-sequences.
23504: */
23505: while (bind != NULL) {
23506:
23507: if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23508: goto next_binding;
23509: /*
23510: * Check if the key/unique IDC table needs to be bubbled.
23511: */
23512: if (! vctxt->createIDCNodeTables) {
23513: aidc = vctxt->aidcs;
23514: do {
23515: if (aidc->def == bind->definition) {
23516: if ((aidc->keyrefDepth == -1) ||
23517: (aidc->keyrefDepth >= vctxt->depth)) {
23518: goto next_binding;
23519: }
23520: break;
23521: }
23522: aidc = aidc->next;
23523: } while (aidc != NULL);
23524: }
23525:
23526: if (parTable != NULL)
23527: parBind = *parTable;
23528: /*
23529: * Search a matching parent binding for the
23530: * IDC definition.
23531: */
23532: while (parBind != NULL) {
23533: if (parBind->definition == bind->definition)
23534: break;
23535: parBind = parBind->next;
23536: }
23537:
23538: if (parBind != NULL) {
23539: /*
23540: * Compare every node-table entry of the child node,
23541: * i.e. the key-sequence within, ...
23542: */
23543: oldNum = parBind->nbNodes; /* Skip newly added items. */
23544:
23545: if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23546: oldDupls = parBind->dupls->nbItems;
23547: dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23548: } else {
23549: dupls = NULL;
23550: oldDupls = 0;
23551: }
23552:
23553: parNodes = parBind->nodeTable;
23554: nbFields = bind->definition->nbFields;
23555:
23556: for (i = 0; i < bind->nbNodes; i++) {
23557: node = bind->nodeTable[i];
23558: if (node == NULL)
23559: continue;
23560: /*
23561: * ...with every key-sequence of the parent node, already
23562: * evaluated to be a duplicate key-sequence.
23563: */
23564: if (oldDupls) {
23565: j = 0;
23566: while (j < oldDupls) {
23567: if (nbFields == 1) {
23568: ret = xmlSchemaAreValuesEqual(
23569: node->keys[0]->val,
23570: dupls[j]->keys[0]->val);
23571: if (ret == -1)
23572: goto internal_error;
23573: if (ret == 0) {
23574: j++;
23575: continue;
23576: }
23577: } else {
23578: parNode = dupls[j];
23579: for (k = 0; k < nbFields; k++) {
23580: ret = xmlSchemaAreValuesEqual(
23581: node->keys[k]->val,
23582: parNode->keys[k]->val);
23583: if (ret == -1)
23584: goto internal_error;
23585: if (ret == 0)
23586: break;
23587: }
23588: }
23589: if (ret == 1)
23590: /* Duplicate found. */
23591: break;
23592: j++;
23593: }
23594: if (j != oldDupls) {
23595: /* Duplicate found. Skip this entry. */
23596: continue;
23597: }
23598: }
23599: /*
23600: * ... and with every key-sequence of the parent node.
23601: */
23602: if (oldNum) {
23603: j = 0;
23604: while (j < oldNum) {
23605: parNode = parNodes[j];
23606: if (nbFields == 1) {
23607: ret = xmlSchemaAreValuesEqual(
23608: node->keys[0]->val,
23609: parNode->keys[0]->val);
23610: if (ret == -1)
23611: goto internal_error;
23612: if (ret == 0) {
23613: j++;
23614: continue;
23615: }
23616: } else {
23617: for (k = 0; k < nbFields; k++) {
23618: ret = xmlSchemaAreValuesEqual(
23619: node->keys[k]->val,
23620: parNode->keys[k]->val);
23621: if (ret == -1)
23622: goto internal_error;
23623: if (ret == 0)
23624: break;
23625: }
23626: }
23627: if (ret == 1)
23628: /* Duplicate found. */
23629: break;
23630: j++;
23631: }
23632: if (j != oldNum) {
23633: /*
23634: * Handle duplicates. Move the duplicate in
23635: * the parent's node-table to the list of
23636: * duplicates.
23637: */
23638: oldNum--;
23639: parBind->nbNodes--;
23640: /*
23641: * Move last old item to pos of duplicate.
23642: */
23643: parNodes[j] = parNodes[oldNum];
23644:
23645: if (parBind->nbNodes != oldNum) {
23646: /*
23647: * If new items exist, move last new item to
23648: * last of old items.
23649: */
23650: parNodes[oldNum] =
23651: parNodes[parBind->nbNodes];
23652: }
23653: if (parBind->dupls == NULL) {
23654: parBind->dupls = xmlSchemaItemListCreate();
23655: if (parBind->dupls == NULL)
23656: goto internal_error;
23657: }
23658: xmlSchemaItemListAdd(parBind->dupls, parNode);
23659: } else {
23660: /*
23661: * Add the node-table entry (node and key-sequence) of
23662: * the child node to the node table of the parent node.
23663: */
23664: if (parBind->nodeTable == NULL) {
23665: parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23666: xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23667: if (parBind->nodeTable == NULL) {
23668: xmlSchemaVErrMemory(NULL,
23669: "allocating IDC list of node-table items", NULL);
23670: goto internal_error;
23671: }
23672: parBind->sizeNodes = 1;
23673: } else if (parBind->nbNodes >= parBind->sizeNodes) {
23674: parBind->sizeNodes *= 2;
23675: parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23676: xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23677: sizeof(xmlSchemaPSVIIDCNodePtr));
23678: if (parBind->nodeTable == NULL) {
23679: xmlSchemaVErrMemory(NULL,
23680: "re-allocating IDC list of node-table items", NULL);
23681: goto internal_error;
23682: }
23683: }
23684: parNodes = parBind->nodeTable;
23685: /*
23686: * Append the new node-table entry to the 'new node-table
23687: * entries' section.
23688: */
23689: parNodes[parBind->nbNodes++] = node;
23690: }
23691:
23692: }
23693:
23694: }
23695: } else {
23696: /*
23697: * No binding for the IDC was found: create a new one and
23698: * copy all node-tables.
23699: */
23700: parBind = xmlSchemaIDCNewBinding(bind->definition);
23701: if (parBind == NULL)
23702: goto internal_error;
23703:
23704: /*
23705: * TODO: Hmm, how to optimize the initial number of
23706: * allocated entries?
23707: */
23708: if (bind->nbNodes != 0) {
23709: /*
23710: * Add all IDC node-table entries.
23711: */
23712: if (! vctxt->psviExposeIDCNodeTables) {
23713: /*
23714: * Just move the entries.
23715: * NOTE: this is quite save here, since
23716: * all the keyref lookups have already been
23717: * performed.
23718: */
23719: parBind->nodeTable = bind->nodeTable;
23720: bind->nodeTable = NULL;
23721: parBind->sizeNodes = bind->sizeNodes;
23722: bind->sizeNodes = 0;
23723: parBind->nbNodes = bind->nbNodes;
23724: bind->nbNodes = 0;
23725: } else {
23726: /*
23727: * Copy the entries.
23728: */
23729: parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23730: xmlMalloc(bind->nbNodes *
23731: sizeof(xmlSchemaPSVIIDCNodePtr));
23732: if (parBind->nodeTable == NULL) {
23733: xmlSchemaVErrMemory(NULL,
23734: "allocating an array of IDC node-table "
23735: "items", NULL);
23736: xmlSchemaIDCFreeBinding(parBind);
23737: goto internal_error;
23738: }
23739: parBind->sizeNodes = bind->nbNodes;
23740: parBind->nbNodes = bind->nbNodes;
23741: memcpy(parBind->nodeTable, bind->nodeTable,
23742: bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23743: }
23744: }
23745: if (bind->dupls) {
23746: /*
23747: * Move the duplicates.
23748: */
23749: if (parBind->dupls != NULL)
23750: xmlSchemaItemListFree(parBind->dupls);
23751: parBind->dupls = bind->dupls;
23752: bind->dupls = NULL;
23753: }
23754: if (parTable != NULL) {
23755: if (*parTable == NULL)
23756: *parTable = parBind;
23757: else {
23758: parBind->next = *parTable;
23759: *parTable = parBind;
23760: }
23761: }
23762: }
23763:
23764: next_binding:
23765: bind = bind->next;
23766: }
23767: return (0);
23768:
23769: internal_error:
23770: return(-1);
23771: }
23772:
23773: /**
23774: * xmlSchemaCheckCVCIDCKeyRef:
23775: * @vctxt: the WXS validation context
23776: * @elemDecl: the element declaration
23777: *
23778: * Check the cvc-idc-keyref constraints.
23779: */
23780: static int
23781: xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23782: {
23783: xmlSchemaIDCMatcherPtr matcher;
23784: xmlSchemaPSVIIDCBindingPtr bind;
23785:
23786: matcher = vctxt->inode->idcMatchers;
23787: /*
23788: * Find a keyref.
23789: */
23790: while (matcher != NULL) {
23791: if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23792: matcher->targets &&
23793: matcher->targets->nbItems)
23794: {
23795: int i, j, k, res, nbFields, hasDupls;
23796: xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23797: xmlSchemaPSVIIDCNodePtr refNode = NULL;
23798:
23799: nbFields = matcher->aidc->def->nbFields;
23800:
23801: /*
23802: * Find the IDC node-table for the referenced IDC key/unique.
23803: */
23804: bind = vctxt->inode->idcTable;
23805: while (bind != NULL) {
23806: if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23807: bind->definition)
23808: break;
23809: bind = bind->next;
23810: }
23811: hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23812: /*
23813: * Search for a matching key-sequences.
23814: */
23815: for (i = 0; i < matcher->targets->nbItems; i++) {
23816: res = 0;
23817: refNode = matcher->targets->items[i];
23818: if (bind != NULL) {
23819: refKeys = refNode->keys;
23820: for (j = 0; j < bind->nbNodes; j++) {
23821: keys = bind->nodeTable[j]->keys;
23822: for (k = 0; k < nbFields; k++) {
23823: res = xmlSchemaAreValuesEqual(keys[k]->val,
23824: refKeys[k]->val);
23825: if (res == 0)
23826: break;
23827: else if (res == -1) {
23828: return (-1);
23829: }
23830: }
23831: if (res == 1) {
23832: /*
23833: * Match found.
23834: */
23835: break;
23836: }
23837: }
23838: if ((res == 0) && hasDupls) {
23839: /*
23840: * Search in duplicates
23841: */
23842: for (j = 0; j < bind->dupls->nbItems; j++) {
23843: keys = ((xmlSchemaPSVIIDCNodePtr)
23844: bind->dupls->items[j])->keys;
23845: for (k = 0; k < nbFields; k++) {
23846: res = xmlSchemaAreValuesEqual(keys[k]->val,
23847: refKeys[k]->val);
23848: if (res == 0)
23849: break;
23850: else if (res == -1) {
23851: return (-1);
23852: }
23853: }
23854: if (res == 1) {
23855: /*
23856: * Match in duplicates found.
23857: */
23858: xmlChar *str = NULL, *strB = NULL;
23859: xmlSchemaKeyrefErr(vctxt,
23860: XML_SCHEMAV_CVC_IDC, refNode,
23861: (xmlSchemaTypePtr) matcher->aidc->def,
23862: "More than one match found for "
23863: "key-sequence %s of keyref '%s'",
23864: xmlSchemaFormatIDCKeySequence(vctxt, &str,
23865: refNode->keys, nbFields),
23866: xmlSchemaGetComponentQName(&strB,
23867: matcher->aidc->def));
23868: FREE_AND_NULL(str);
23869: FREE_AND_NULL(strB);
23870: break;
23871: }
23872: }
23873: }
23874: }
23875:
23876: if (res == 0) {
23877: xmlChar *str = NULL, *strB = NULL;
23878: xmlSchemaKeyrefErr(vctxt,
23879: XML_SCHEMAV_CVC_IDC, refNode,
23880: (xmlSchemaTypePtr) matcher->aidc->def,
23881: "No match found for key-sequence %s of keyref '%s'",
23882: xmlSchemaFormatIDCKeySequence(vctxt, &str,
23883: refNode->keys, nbFields),
23884: xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23885: FREE_AND_NULL(str);
23886: FREE_AND_NULL(strB);
23887: }
23888: }
23889: }
23890: matcher = matcher->next;
23891: }
23892: /* TODO: Return an error if any error encountered. */
23893: return (0);
23894: }
23895:
23896: /************************************************************************
1.1.1.3 ! misho 23897: * *
! 23898: * XML Reader validation code *
! 23899: * *
1.1 misho 23900: ************************************************************************/
23901:
23902: static xmlSchemaAttrInfoPtr
23903: xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23904: {
23905: xmlSchemaAttrInfoPtr iattr;
23906: /*
23907: * Grow/create list of attribute infos.
23908: */
23909: if (vctxt->attrInfos == NULL) {
23910: vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23911: xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23912: vctxt->sizeAttrInfos = 1;
23913: if (vctxt->attrInfos == NULL) {
23914: xmlSchemaVErrMemory(vctxt,
23915: "allocating attribute info list", NULL);
23916: return (NULL);
23917: }
23918: } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23919: vctxt->sizeAttrInfos++;
23920: vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23921: xmlRealloc(vctxt->attrInfos,
23922: vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23923: if (vctxt->attrInfos == NULL) {
23924: xmlSchemaVErrMemory(vctxt,
23925: "re-allocating attribute info list", NULL);
23926: return (NULL);
23927: }
23928: } else {
23929: iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23930: if (iattr->localName != NULL) {
23931: VERROR_INT("xmlSchemaGetFreshAttrInfo",
23932: "attr info not cleared");
23933: return (NULL);
23934: }
23935: iattr->nodeType = XML_ATTRIBUTE_NODE;
23936: return (iattr);
23937: }
23938: /*
23939: * Create an attribute info.
23940: */
23941: iattr = (xmlSchemaAttrInfoPtr)
23942: xmlMalloc(sizeof(xmlSchemaAttrInfo));
23943: if (iattr == NULL) {
23944: xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23945: return (NULL);
23946: }
23947: memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23948: iattr->nodeType = XML_ATTRIBUTE_NODE;
23949: vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23950:
23951: return (iattr);
23952: }
23953:
23954: static int
23955: xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23956: xmlNodePtr attrNode,
23957: int nodeLine,
23958: const xmlChar *localName,
23959: const xmlChar *nsName,
23960: int ownedNames,
23961: xmlChar *value,
23962: int ownedValue)
23963: {
23964: xmlSchemaAttrInfoPtr attr;
23965:
23966: attr = xmlSchemaGetFreshAttrInfo(vctxt);
23967: if (attr == NULL) {
23968: VERROR_INT("xmlSchemaPushAttribute",
23969: "calling xmlSchemaGetFreshAttrInfo()");
23970: return (-1);
23971: }
23972: attr->node = attrNode;
23973: attr->nodeLine = nodeLine;
23974: attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23975: attr->localName = localName;
23976: attr->nsName = nsName;
23977: if (ownedNames)
23978: attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23979: /*
23980: * Evaluate if it's an XSI attribute.
23981: */
23982: if (nsName != NULL) {
23983: if (xmlStrEqual(localName, BAD_CAST "nil")) {
23984: if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23985: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23986: }
23987: } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23988: if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23989: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23990: }
23991: } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23992: if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23993: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23994: }
23995: } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23996: if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23997: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23998: }
23999: } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24000: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24001: }
24002: }
24003: attr->value = value;
24004: if (ownedValue)
24005: attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24006: if (attr->metaType != 0)
24007: attr->state = XML_SCHEMAS_ATTR_META;
24008: return (0);
24009: }
24010:
24011: /**
24012: * xmlSchemaClearElemInfo:
24013: * @vctxt: the WXS validation context
24014: * @ielem: the element information item
24015: */
24016: static void
24017: xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24018: xmlSchemaNodeInfoPtr ielem)
24019: {
24020: ielem->hasKeyrefs = 0;
24021: ielem->appliedXPath = 0;
24022: if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24023: FREE_AND_NULL(ielem->localName);
24024: FREE_AND_NULL(ielem->nsName);
24025: } else {
24026: ielem->localName = NULL;
24027: ielem->nsName = NULL;
24028: }
24029: if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24030: FREE_AND_NULL(ielem->value);
24031: } else {
24032: ielem->value = NULL;
24033: }
24034: if (ielem->val != NULL) {
24035: /*
24036: * PSVI TODO: Be careful not to free it when the value is
24037: * exposed via PSVI.
24038: */
24039: xmlSchemaFreeValue(ielem->val);
24040: ielem->val = NULL;
24041: }
24042: if (ielem->idcMatchers != NULL) {
24043: /*
24044: * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24045: * Does it work?
24046: */
24047: xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24048: #if 0
24049: xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24050: #endif
24051: ielem->idcMatchers = NULL;
24052: }
24053: if (ielem->idcTable != NULL) {
24054: /*
24055: * OPTIMIZE TODO: Use a pool of IDC tables??.
24056: */
24057: xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24058: ielem->idcTable = NULL;
24059: }
24060: if (ielem->regexCtxt != NULL) {
24061: xmlRegFreeExecCtxt(ielem->regexCtxt);
24062: ielem->regexCtxt = NULL;
24063: }
24064: if (ielem->nsBindings != NULL) {
24065: xmlFree((xmlChar **)ielem->nsBindings);
24066: ielem->nsBindings = NULL;
24067: ielem->nbNsBindings = 0;
24068: ielem->sizeNsBindings = 0;
24069: }
24070: }
24071:
24072: /**
24073: * xmlSchemaGetFreshElemInfo:
24074: * @vctxt: the schema validation context
24075: *
24076: * Creates/reuses and initializes the element info item for
24077: * the currect tree depth.
24078: *
24079: * Returns the element info item or NULL on API or internal errors.
24080: */
24081: static xmlSchemaNodeInfoPtr
24082: xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24083: {
24084: xmlSchemaNodeInfoPtr info = NULL;
24085:
24086: if (vctxt->depth > vctxt->sizeElemInfos) {
24087: VERROR_INT("xmlSchemaGetFreshElemInfo",
24088: "inconsistent depth encountered");
24089: return (NULL);
24090: }
24091: if (vctxt->elemInfos == NULL) {
24092: vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24093: xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24094: if (vctxt->elemInfos == NULL) {
24095: xmlSchemaVErrMemory(vctxt,
24096: "allocating the element info array", NULL);
24097: return (NULL);
24098: }
24099: memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24100: vctxt->sizeElemInfos = 10;
24101: } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24102: int i = vctxt->sizeElemInfos;
24103:
24104: vctxt->sizeElemInfos *= 2;
24105: vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24106: xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24107: sizeof(xmlSchemaNodeInfoPtr));
24108: if (vctxt->elemInfos == NULL) {
24109: xmlSchemaVErrMemory(vctxt,
24110: "re-allocating the element info array", NULL);
24111: return (NULL);
24112: }
24113: /*
24114: * We need the new memory to be NULLed.
24115: * TODO: Use memset instead?
24116: */
24117: for (; i < vctxt->sizeElemInfos; i++)
24118: vctxt->elemInfos[i] = NULL;
24119: } else
24120: info = vctxt->elemInfos[vctxt->depth];
24121:
24122: if (info == NULL) {
24123: info = (xmlSchemaNodeInfoPtr)
24124: xmlMalloc(sizeof(xmlSchemaNodeInfo));
24125: if (info == NULL) {
24126: xmlSchemaVErrMemory(vctxt,
24127: "allocating an element info", NULL);
24128: return (NULL);
24129: }
24130: vctxt->elemInfos[vctxt->depth] = info;
24131: } else {
24132: if (info->localName != NULL) {
24133: VERROR_INT("xmlSchemaGetFreshElemInfo",
24134: "elem info has not been cleared");
24135: return (NULL);
24136: }
24137: }
24138: memset(info, 0, sizeof(xmlSchemaNodeInfo));
24139: info->nodeType = XML_ELEMENT_NODE;
24140: info->depth = vctxt->depth;
24141:
24142: return (info);
24143: }
24144:
24145: #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24146: #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24147: #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24148:
24149: static int
24150: xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24151: xmlNodePtr node,
24152: xmlSchemaTypePtr type,
24153: xmlSchemaValType valType,
24154: const xmlChar * value,
24155: xmlSchemaValPtr val,
24156: unsigned long length,
24157: int fireErrors)
24158: {
24159: int ret, error = 0;
24160:
24161: xmlSchemaTypePtr tmpType;
24162: xmlSchemaFacetLinkPtr facetLink;
24163: xmlSchemaFacetPtr facet;
24164: unsigned long len = 0;
24165: xmlSchemaWhitespaceValueType ws;
24166:
24167: /*
24168: * In Libxml2, derived built-in types have currently no explicit facets.
24169: */
24170: if (type->type == XML_SCHEMA_TYPE_BASIC)
24171: return (0);
24172:
24173: /*
24174: * NOTE: Do not jump away, if the facetSet of the given type is
24175: * empty: until now, "pattern" and "enumeration" facets of the
24176: * *base types* need to be checked as well.
24177: */
24178: if (type->facetSet == NULL)
24179: goto pattern_and_enum;
24180:
24181: if (! WXS_IS_ATOMIC(type)) {
24182: if (WXS_IS_LIST(type))
24183: goto WXS_IS_LIST;
24184: else
24185: goto pattern_and_enum;
24186: }
24187: /*
24188: * Whitespace handling is only of importance for string-based
24189: * types.
24190: */
24191: tmpType = xmlSchemaGetPrimitiveType(type);
24192: if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24193: WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24194: ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24195: } else
24196: ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24197: /*
24198: * If the value was not computed (for string or
24199: * anySimpleType based types), then use the provided
24200: * type.
24201: */
24202: if (val == NULL)
24203: valType = valType;
24204: else
24205: valType = xmlSchemaGetValType(val);
24206:
24207: ret = 0;
24208: for (facetLink = type->facetSet; facetLink != NULL;
24209: facetLink = facetLink->next) {
24210: /*
24211: * Skip the pattern "whiteSpace": it is used to
24212: * format the character content beforehand.
24213: */
24214: switch (facetLink->facet->type) {
24215: case XML_SCHEMA_FACET_WHITESPACE:
24216: case XML_SCHEMA_FACET_PATTERN:
24217: case XML_SCHEMA_FACET_ENUMERATION:
24218: continue;
24219: case XML_SCHEMA_FACET_LENGTH:
24220: case XML_SCHEMA_FACET_MINLENGTH:
24221: case XML_SCHEMA_FACET_MAXLENGTH:
24222: ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24223: valType, value, val, &len, ws);
24224: break;
24225: default:
24226: ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24227: valType, value, val, ws);
24228: break;
24229: }
24230: if (ret < 0) {
24231: AERROR_INT("xmlSchemaValidateFacets",
24232: "validating against a atomic type facet");
24233: return (-1);
24234: } else if (ret > 0) {
24235: if (fireErrors)
24236: xmlSchemaFacetErr(actxt, ret, node,
24237: value, len, type, facetLink->facet, NULL, NULL, NULL);
24238: else
24239: return (ret);
24240: if (error == 0)
24241: error = ret;
24242: }
24243: ret = 0;
24244: }
24245:
24246: WXS_IS_LIST:
24247: if (! WXS_IS_LIST(type))
24248: goto pattern_and_enum;
24249: /*
24250: * "length", "minLength" and "maxLength" of list types.
24251: */
24252: ret = 0;
24253: for (facetLink = type->facetSet; facetLink != NULL;
24254: facetLink = facetLink->next) {
24255:
24256: switch (facetLink->facet->type) {
24257: case XML_SCHEMA_FACET_LENGTH:
24258: case XML_SCHEMA_FACET_MINLENGTH:
24259: case XML_SCHEMA_FACET_MAXLENGTH:
24260: ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24261: value, length, NULL);
24262: break;
24263: default:
24264: continue;
24265: }
24266: if (ret < 0) {
24267: AERROR_INT("xmlSchemaValidateFacets",
24268: "validating against a list type facet");
24269: return (-1);
24270: } else if (ret > 0) {
24271: if (fireErrors)
24272: xmlSchemaFacetErr(actxt, ret, node,
24273: value, length, type, facetLink->facet, NULL, NULL, NULL);
24274: else
24275: return (ret);
24276: if (error == 0)
24277: error = ret;
24278: }
24279: ret = 0;
24280: }
24281:
24282: pattern_and_enum:
24283: if (error >= 0) {
24284: int found = 0;
24285: /*
24286: * Process enumerations. Facet values are in the value space
24287: * of the defining type's base type. This seems to be a bug in the
24288: * XML Schema 1.0 spec. Use the whitespace type of the base type.
24289: * Only the first set of enumerations in the ancestor-or-self axis
24290: * is used for validation.
24291: */
24292: ret = 0;
24293: tmpType = type;
24294: do {
24295: for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24296: if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24297: continue;
24298: found = 1;
24299: ret = xmlSchemaAreValuesEqual(facet->val, val);
24300: if (ret == 1)
24301: break;
24302: else if (ret < 0) {
24303: AERROR_INT("xmlSchemaValidateFacets",
24304: "validating against an enumeration facet");
24305: return (-1);
24306: }
24307: }
24308: if (ret != 0)
24309: break;
24310: /*
24311: * Break on the first set of enumerations. Any additional
24312: * enumerations which might be existent on the ancestors
24313: * of the current type are restricted by this set; thus
24314: * *must* *not* be taken into account.
24315: */
24316: if (found)
24317: break;
24318: tmpType = tmpType->baseType;
24319: } while ((tmpType != NULL) &&
24320: (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24321: if (found && (ret == 0)) {
24322: ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24323: if (fireErrors) {
24324: xmlSchemaFacetErr(actxt, ret, node,
24325: value, 0, type, NULL, NULL, NULL, NULL);
24326: } else
24327: return (ret);
24328: if (error == 0)
24329: error = ret;
24330: }
24331: }
24332:
24333: if (error >= 0) {
24334: int found;
24335: /*
24336: * Process patters. Pattern facets are ORed at type level
24337: * and ANDed if derived. Walk the base type axis.
24338: */
24339: tmpType = type;
24340: facet = NULL;
24341: do {
24342: found = 0;
24343: for (facetLink = tmpType->facetSet; facetLink != NULL;
24344: facetLink = facetLink->next) {
24345: if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24346: continue;
24347: found = 1;
24348: /*
24349: * NOTE that for patterns, @value needs to be the
24350: * normalized vaule.
24351: */
24352: ret = xmlRegexpExec(facetLink->facet->regexp, value);
24353: if (ret == 1)
24354: break;
24355: else if (ret < 0) {
24356: AERROR_INT("xmlSchemaValidateFacets",
24357: "validating against a pattern facet");
24358: return (-1);
24359: } else {
24360: /*
24361: * Save the last non-validating facet.
24362: */
24363: facet = facetLink->facet;
24364: }
24365: }
24366: if (found && (ret != 1)) {
24367: ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24368: if (fireErrors) {
24369: xmlSchemaFacetErr(actxt, ret, node,
24370: value, 0, type, facet, NULL, NULL, NULL);
24371: } else
24372: return (ret);
24373: if (error == 0)
24374: error = ret;
24375: break;
24376: }
24377: tmpType = tmpType->baseType;
24378: } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24379: }
24380:
24381: return (error);
24382: }
24383:
24384: static xmlChar *
24385: xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24386: const xmlChar *value)
24387: {
24388: switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24389: case XML_SCHEMA_WHITESPACE_COLLAPSE:
24390: return (xmlSchemaCollapseString(value));
24391: case XML_SCHEMA_WHITESPACE_REPLACE:
24392: return (xmlSchemaWhiteSpaceReplace(value));
24393: default:
24394: return (NULL);
24395: }
24396: }
24397:
24398: static int
24399: xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24400: const xmlChar *value,
24401: xmlSchemaValPtr *val,
24402: int valNeeded)
24403: {
24404: int ret;
24405: const xmlChar *nsName;
24406: xmlChar *local, *prefix = NULL;
24407:
24408: ret = xmlValidateQName(value, 1);
24409: if (ret != 0) {
24410: if (ret == -1) {
24411: VERROR_INT("xmlSchemaValidateQName",
24412: "calling xmlValidateQName()");
24413: return (-1);
24414: }
24415: return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24416: }
24417: /*
24418: * NOTE: xmlSplitQName2 will always return a duplicated
24419: * strings.
24420: */
24421: local = xmlSplitQName2(value, &prefix);
24422: if (local == NULL)
24423: local = xmlStrdup(value);
24424: /*
24425: * OPTIMIZE TODO: Use flags for:
24426: * - is there any namespace binding?
24427: * - is there a default namespace?
24428: */
24429: nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24430:
24431: if (prefix != NULL) {
24432: xmlFree(prefix);
24433: /*
24434: * A namespace must be found if the prefix is
24435: * NOT NULL.
24436: */
24437: if (nsName == NULL) {
24438: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24439: xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24440: WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24441: "The QName value '%s' has no "
24442: "corresponding namespace declaration in "
24443: "scope", value, NULL);
24444: if (local != NULL)
24445: xmlFree(local);
24446: return (ret);
24447: }
24448: }
24449: if (valNeeded && val) {
24450: if (nsName != NULL)
24451: *val = xmlSchemaNewQNameValue(
24452: BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24453: else
24454: *val = xmlSchemaNewQNameValue(NULL,
24455: BAD_CAST local);
24456: } else
24457: xmlFree(local);
24458: return (0);
24459: }
24460:
24461: /*
24462: * cvc-simple-type
24463: */
24464: static int
24465: xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24466: xmlNodePtr node,
24467: xmlSchemaTypePtr type,
24468: const xmlChar *value,
24469: xmlSchemaValPtr *retVal,
24470: int fireErrors,
24471: int normalize,
24472: int isNormalized)
24473: {
24474: int ret = 0, valNeeded = (retVal) ? 1 : 0;
24475: xmlSchemaValPtr val = NULL;
24476: /* xmlSchemaWhitespaceValueType ws; */
24477: xmlChar *normValue = NULL;
24478:
24479: #define NORMALIZE(atype) \
24480: if ((! isNormalized) && \
24481: (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24482: normValue = xmlSchemaNormalizeValue(atype, value); \
24483: if (normValue != NULL) \
24484: value = normValue; \
24485: isNormalized = 1; \
24486: }
24487:
24488: if ((retVal != NULL) && (*retVal != NULL)) {
24489: xmlSchemaFreeValue(*retVal);
24490: *retVal = NULL;
24491: }
24492: /*
24493: * 3.14.4 Simple Type Definition Validation Rules
24494: * Validation Rule: String Valid
24495: */
24496: /*
24497: * 1 It is schema-valid with respect to that definition as defined
24498: * by Datatype Valid in [XML Schemas: Datatypes].
24499: */
24500: /*
24501: * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24502: * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24503: * the string must be a �declared entity name�.
24504: */
24505: /*
24506: * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24507: * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24508: * then every whitespace-delimited substring of the string must be a �declared
24509: * entity name�.
24510: */
24511: /*
24512: * 2.3 otherwise no further condition applies.
24513: */
24514: if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24515: valNeeded = 1;
24516: if (value == NULL)
24517: value = BAD_CAST "";
24518: if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24519: xmlSchemaTypePtr biType; /* The built-in type. */
24520: /*
24521: * SPEC (1.2.1) "if {variety} is �atomic� then the string must �match�
24522: * a literal in the �lexical space� of {base type definition}"
24523: */
24524: /*
24525: * Whitespace-normalize.
24526: */
24527: NORMALIZE(type);
24528: if (type->type != XML_SCHEMA_TYPE_BASIC) {
24529: /*
24530: * Get the built-in type.
24531: */
24532: biType = type->baseType;
24533: while ((biType != NULL) &&
24534: (biType->type != XML_SCHEMA_TYPE_BASIC))
24535: biType = biType->baseType;
24536:
24537: if (biType == NULL) {
24538: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24539: "could not get the built-in type");
24540: goto internal_error;
24541: }
24542: } else
24543: biType = type;
24544: /*
24545: * NOTATIONs need to be processed here, since they need
24546: * to lookup in the hashtable of NOTATION declarations of the schema.
24547: */
24548: if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24549: switch (biType->builtInType) {
24550: case XML_SCHEMAS_NOTATION:
24551: ret = xmlSchemaValidateNotation(
24552: (xmlSchemaValidCtxtPtr) actxt,
24553: ((xmlSchemaValidCtxtPtr) actxt)->schema,
24554: NULL, value, &val, valNeeded);
24555: break;
24556: case XML_SCHEMAS_QNAME:
24557: ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24558: value, &val, valNeeded);
24559: break;
24560: default:
24561: /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24562: if (valNeeded)
24563: ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24564: value, &val, node);
24565: else
24566: ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24567: value, NULL, node);
24568: break;
24569: }
24570: } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24571: switch (biType->builtInType) {
24572: case XML_SCHEMAS_NOTATION:
24573: ret = xmlSchemaValidateNotation(NULL,
24574: ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24575: value, &val, valNeeded);
24576: break;
24577: default:
24578: /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24579: if (valNeeded)
24580: ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24581: value, &val, node);
24582: else
24583: ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24584: value, NULL, node);
24585: break;
24586: }
24587: } else {
24588: /*
24589: * Validation via a public API is not implemented yet.
24590: */
24591: TODO
24592: goto internal_error;
24593: }
24594: if (ret != 0) {
24595: if (ret < 0) {
24596: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24597: "validating against a built-in type");
24598: goto internal_error;
24599: }
24600: if (WXS_IS_LIST(type))
24601: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24602: else
24603: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24604: }
24605: if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24606: /*
24607: * Check facets.
24608: */
24609: ret = xmlSchemaValidateFacets(actxt, node, type,
24610: (xmlSchemaValType) biType->builtInType, value, val,
24611: 0, fireErrors);
24612: if (ret != 0) {
24613: if (ret < 0) {
24614: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24615: "validating facets of atomic simple type");
24616: goto internal_error;
24617: }
24618: if (WXS_IS_LIST(type))
24619: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24620: else
24621: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24622: }
24623: }
24624: if (fireErrors && (ret > 0))
24625: xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24626: } else if (WXS_IS_LIST(type)) {
24627:
24628: xmlSchemaTypePtr itemType;
24629: const xmlChar *cur, *end;
24630: xmlChar *tmpValue = NULL;
24631: unsigned long len = 0;
24632: xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24633: /* 1.2.2 if {variety} is �list� then the string must be a sequence
24634: * of white space separated tokens, each of which �match�es a literal
24635: * in the �lexical space� of {item type definition}
24636: */
24637: /*
24638: * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24639: * the list type has an enum or pattern facet.
24640: */
24641: NORMALIZE(type);
24642: /*
24643: * VAL TODO: Optimize validation of empty values.
24644: * VAL TODO: We do not have computed values for lists.
24645: */
24646: itemType = WXS_LIST_ITEMTYPE(type);
24647: cur = value;
24648: do {
24649: while (IS_BLANK_CH(*cur))
24650: cur++;
24651: end = cur;
24652: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24653: end++;
24654: if (end == cur)
24655: break;
24656: tmpValue = xmlStrndup(cur, end - cur);
24657: len++;
24658:
24659: if (valNeeded)
24660: ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24661: tmpValue, &curVal, fireErrors, 0, 1);
24662: else
24663: ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24664: tmpValue, NULL, fireErrors, 0, 1);
24665: FREE_AND_NULL(tmpValue);
24666: if (curVal != NULL) {
24667: /*
24668: * Add to list of computed values.
24669: */
24670: if (val == NULL)
24671: val = curVal;
24672: else
24673: xmlSchemaValueAppend(prevVal, curVal);
24674: prevVal = curVal;
24675: curVal = NULL;
24676: }
24677: if (ret != 0) {
24678: if (ret < 0) {
24679: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24680: "validating an item of list simple type");
24681: goto internal_error;
24682: }
24683: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24684: break;
24685: }
24686: cur = end;
24687: } while (*cur != 0);
24688: FREE_AND_NULL(tmpValue);
24689: if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24690: /*
24691: * Apply facets (pattern, enumeration).
24692: */
24693: ret = xmlSchemaValidateFacets(actxt, node, type,
24694: XML_SCHEMAS_UNKNOWN, value, val,
24695: len, fireErrors);
24696: if (ret != 0) {
24697: if (ret < 0) {
24698: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24699: "validating facets of list simple type");
24700: goto internal_error;
24701: }
24702: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24703: }
24704: }
24705: if (fireErrors && (ret > 0)) {
24706: /*
24707: * Report the normalized value.
24708: */
24709: normalize = 1;
24710: NORMALIZE(type);
24711: xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24712: }
24713: } else if (WXS_IS_UNION(type)) {
24714: xmlSchemaTypeLinkPtr memberLink;
24715: /*
24716: * TODO: For all datatypes �derived� by �union� whiteSpace does
24717: * not apply directly; however, the normalization behavior of �union�
24718: * types is controlled by the value of whiteSpace on that one of the
24719: * �memberTypes� against which the �union� is successfully validated.
24720: *
24721: * This means that the value is normalized by the first validating
24722: * member type, then the facets of the union type are applied. This
24723: * needs changing of the value!
24724: */
24725:
24726: /*
24727: * 1.2.3 if {variety} is �union� then the string must �match� a
24728: * literal in the �lexical space� of at least one member of
24729: * {member type definitions}
24730: */
24731: memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24732: if (memberLink == NULL) {
24733: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24734: "union simple type has no member types");
24735: goto internal_error;
24736: }
24737: /*
24738: * Always normalize union type values, since we currently
24739: * cannot store the whitespace information with the value
24740: * itself; otherwise a later value-comparison would be
24741: * not possible.
24742: */
24743: while (memberLink != NULL) {
24744: if (valNeeded)
24745: ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24746: memberLink->type, value, &val, 0, 1, 0);
24747: else
24748: ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24749: memberLink->type, value, NULL, 0, 1, 0);
24750: if (ret <= 0)
24751: break;
24752: memberLink = memberLink->next;
24753: }
24754: if (ret != 0) {
24755: if (ret < 0) {
24756: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24757: "validating members of union simple type");
24758: goto internal_error;
24759: }
24760: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24761: }
24762: /*
24763: * Apply facets (pattern, enumeration).
24764: */
24765: if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24766: /*
24767: * The normalization behavior of �union� types is controlled by
24768: * the value of whiteSpace on that one of the �memberTypes�
24769: * against which the �union� is successfully validated.
24770: */
24771: NORMALIZE(memberLink->type);
24772: ret = xmlSchemaValidateFacets(actxt, node, type,
24773: XML_SCHEMAS_UNKNOWN, value, val,
24774: 0, fireErrors);
24775: if (ret != 0) {
24776: if (ret < 0) {
24777: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24778: "validating facets of union simple type");
24779: goto internal_error;
24780: }
24781: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24782: }
24783: }
24784: if (fireErrors && (ret > 0))
24785: xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24786: }
24787:
24788: if (normValue != NULL)
24789: xmlFree(normValue);
24790: if (ret == 0) {
24791: if (retVal != NULL)
24792: *retVal = val;
24793: else if (val != NULL)
24794: xmlSchemaFreeValue(val);
24795: } else if (val != NULL)
24796: xmlSchemaFreeValue(val);
24797: return (ret);
24798: internal_error:
24799: if (normValue != NULL)
24800: xmlFree(normValue);
24801: if (val != NULL)
24802: xmlSchemaFreeValue(val);
24803: return (-1);
24804: }
24805:
24806: static int
24807: xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24808: const xmlChar *value,
24809: const xmlChar **nsName,
24810: const xmlChar **localName)
24811: {
24812: int ret = 0;
24813:
24814: if ((nsName == NULL) || (localName == NULL))
24815: return (-1);
24816: *nsName = NULL;
24817: *localName = NULL;
24818:
24819: ret = xmlValidateQName(value, 1);
24820: if (ret == -1)
24821: return (-1);
24822: if (ret > 0) {
24823: xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24824: XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24825: value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24826: return (1);
24827: }
24828: {
24829: xmlChar *local = NULL;
24830: xmlChar *prefix;
24831:
24832: /*
24833: * NOTE: xmlSplitQName2 will return a duplicated
24834: * string.
24835: */
24836: local = xmlSplitQName2(value, &prefix);
24837: if (local == NULL)
24838: *localName = xmlDictLookup(vctxt->dict, value, -1);
24839: else {
24840: *localName = xmlDictLookup(vctxt->dict, local, -1);
24841: xmlFree(local);
24842: }
24843:
24844: *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24845:
24846: if (prefix != NULL) {
24847: xmlFree(prefix);
24848: /*
24849: * A namespace must be found if the prefix is NOT NULL.
24850: */
24851: if (*nsName == NULL) {
24852: xmlSchemaCustomErr(ACTXT_CAST vctxt,
24853: XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24854: WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24855: "The QName value '%s' has no "
24856: "corresponding namespace declaration in scope",
24857: value, NULL);
24858: return (2);
24859: }
24860: }
24861: }
24862: return (0);
24863: }
24864:
24865: static int
24866: xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24867: xmlSchemaAttrInfoPtr iattr,
24868: xmlSchemaTypePtr *localType,
24869: xmlSchemaElementPtr elemDecl)
24870: {
24871: int ret = 0;
24872: /*
24873: * cvc-elt (3.3.4) : (4)
24874: * AND
24875: * Schema-Validity Assessment (Element) (cvc-assess-elt)
24876: * (1.2.1.2.1) - (1.2.1.2.4)
24877: * Handle 'xsi:type'.
24878: */
24879: if (localType == NULL)
24880: return (-1);
24881: *localType = NULL;
24882: if (iattr == NULL)
24883: return (0);
24884: else {
24885: const xmlChar *nsName = NULL, *local = NULL;
24886: /*
24887: * TODO: We should report a *warning* that the type was overriden
24888: * by the instance.
24889: */
24890: ACTIVATE_ATTRIBUTE(iattr);
24891: /*
24892: * (cvc-elt) (3.3.4) : (4.1)
24893: * (cvc-assess-elt) (1.2.1.2.2)
24894: */
24895: ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24896: &nsName, &local);
24897: if (ret != 0) {
24898: if (ret < 0) {
24899: VERROR_INT("xmlSchemaValidateElementByDeclaration",
24900: "calling xmlSchemaQNameExpand() to validate the "
24901: "attribute 'xsi:type'");
24902: goto internal_error;
24903: }
24904: goto exit;
24905: }
24906: /*
24907: * (cvc-elt) (3.3.4) : (4.2)
24908: * (cvc-assess-elt) (1.2.1.2.3)
24909: */
24910: *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24911: if (*localType == NULL) {
24912: xmlChar *str = NULL;
24913:
24914: xmlSchemaCustomErr(ACTXT_CAST vctxt,
24915: XML_SCHEMAV_CVC_ELT_4_2, NULL,
24916: WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24917: "The QName value '%s' of the xsi:type attribute does not "
24918: "resolve to a type definition",
24919: xmlSchemaFormatQName(&str, nsName, local), NULL);
24920: FREE_AND_NULL(str);
24921: ret = vctxt->err;
24922: goto exit;
24923: }
24924: if (elemDecl != NULL) {
24925: int set = 0;
24926:
24927: /*
24928: * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24929: * "The �local type definition� must be validly
24930: * derived from the {type definition} given the union of
24931: * the {disallowed substitutions} and the {type definition}'s
24932: * {prohibited substitutions}, as defined in
24933: * Type Derivation OK (Complex) (�3.4.6)
24934: * (if it is a complex type definition),
24935: * or given {disallowed substitutions} as defined in Type
24936: * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24937: * definition)."
24938: *
24939: * {disallowed substitutions}: the "block" on the element decl.
24940: * {prohibited substitutions}: the "block" on the type def.
24941: */
24942: /*
24943: * OPTIMIZE TODO: We could map types already evaluated
24944: * to be validly derived from other types to avoid checking
24945: * this over and over for the same types.
24946: */
24947: if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24948: (elemDecl->subtypes->flags &
24949: XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24950: set |= SUBSET_EXTENSION;
24951:
24952: if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24953: (elemDecl->subtypes->flags &
24954: XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24955: set |= SUBSET_RESTRICTION;
24956:
24957: /*
24958: * REMOVED and CHANGED since this produced a parser context
24959: * which adds to the string dict of the schema. So this would
24960: * change the schema and we don't want this. We don't need
24961: * the parser context anymore.
24962: *
24963: * if ((vctxt->pctxt == NULL) &&
24964: * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24965: * return (-1);
24966: */
24967:
24968: if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24969: elemDecl->subtypes, set) != 0) {
24970: xmlChar *str = NULL;
24971:
24972: xmlSchemaCustomErr(ACTXT_CAST vctxt,
24973: XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24974: "The type definition '%s', specified by xsi:type, is "
24975: "blocked or not validly derived from the type definition "
24976: "of the element declaration",
24977: xmlSchemaFormatQName(&str,
24978: (*localType)->targetNamespace,
24979: (*localType)->name),
24980: NULL);
24981: FREE_AND_NULL(str);
24982: ret = vctxt->err;
24983: *localType = NULL;
24984: }
24985: }
24986: }
24987: exit:
24988: ACTIVATE_ELEM;
24989: return (ret);
24990: internal_error:
24991: ACTIVATE_ELEM;
24992: return (-1);
24993: }
24994:
24995: static int
24996: xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24997: {
24998: xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24999: xmlSchemaTypePtr actualType;
25000:
25001: /*
25002: * cvc-elt (3.3.4) : 1
25003: */
25004: if (elemDecl == NULL) {
25005: VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25006: "No matching declaration available");
25007: return (vctxt->err);
25008: }
25009: actualType = WXS_ELEM_TYPEDEF(elemDecl);
25010: /*
25011: * cvc-elt (3.3.4) : 2
25012: */
25013: if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25014: VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25015: "The element declaration is abstract");
25016: return (vctxt->err);
25017: }
25018: if (actualType == NULL) {
1.1.1.3 ! misho 25019: VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
! 25020: "The type definition is absent");
! 25021: return (XML_SCHEMAV_CVC_TYPE_1);
1.1 misho 25022: }
25023: if (vctxt->nbAttrInfos != 0) {
25024: int ret;
25025: xmlSchemaAttrInfoPtr iattr;
25026: /*
25027: * cvc-elt (3.3.4) : 3
25028: * Handle 'xsi:nil'.
25029: */
25030: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25031: XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25032: if (iattr) {
25033: ACTIVATE_ATTRIBUTE(iattr);
25034: /*
25035: * Validate the value.
25036: */
25037: ret = xmlSchemaVCheckCVCSimpleType(
25038: ACTXT_CAST vctxt, NULL,
25039: xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25040: iattr->value, &(iattr->val), 1, 0, 0);
25041: ACTIVATE_ELEM;
25042: if (ret < 0) {
25043: VERROR_INT("xmlSchemaValidateElemDecl",
25044: "calling xmlSchemaVCheckCVCSimpleType() to "
25045: "validate the attribute 'xsi:nil'");
25046: return (-1);
25047: }
25048: if (ret == 0) {
25049: if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25050: /*
25051: * cvc-elt (3.3.4) : 3.1
25052: */
25053: VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25054: "The element is not 'nillable'");
25055: /* Does not return an error on purpose. */
25056: } else {
25057: if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25058: /*
25059: * cvc-elt (3.3.4) : 3.2.2
25060: */
25061: if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25062: (elemDecl->value != NULL)) {
25063: VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25064: "The element cannot be 'nilled' because "
25065: "there is a fixed value constraint defined "
25066: "for it");
25067: /* Does not return an error on purpose. */
25068: } else
25069: vctxt->inode->flags |=
25070: XML_SCHEMA_ELEM_INFO_NILLED;
25071: }
25072: }
25073: }
25074: }
25075: /*
25076: * cvc-elt (3.3.4) : 4
25077: * Handle 'xsi:type'.
25078: */
25079: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25080: XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25081: if (iattr) {
25082: xmlSchemaTypePtr localType = NULL;
25083:
25084: ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25085: elemDecl);
25086: if (ret != 0) {
25087: if (ret == -1) {
25088: VERROR_INT("xmlSchemaValidateElemDecl",
25089: "calling xmlSchemaProcessXSIType() to "
25090: "process the attribute 'xsi:type'");
25091: return (-1);
25092: }
25093: /* Does not return an error on purpose. */
25094: }
25095: if (localType != NULL) {
25096: vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25097: actualType = localType;
25098: }
25099: }
25100: }
25101: /*
25102: * IDC: Register identity-constraint XPath matchers.
25103: */
25104: if ((elemDecl->idcs != NULL) &&
25105: (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25106: return (-1);
25107: /*
25108: * No actual type definition.
25109: */
25110: if (actualType == NULL) {
1.1.1.3 ! misho 25111: VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
! 25112: "The type definition is absent");
! 25113: return (XML_SCHEMAV_CVC_TYPE_1);
1.1 misho 25114: }
25115: /*
25116: * Remember the actual type definition.
25117: */
25118: vctxt->inode->typeDef = actualType;
25119:
25120: return (0);
25121: }
25122:
25123: static int
25124: xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25125: {
25126: xmlSchemaAttrInfoPtr iattr;
25127: int ret = 0, i;
25128:
25129: /*
25130: * SPEC cvc-type (3.1.1)
25131: * "The attributes of must be empty, excepting those whose namespace
25132: * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25133: * whose local name is one of type, nil, schemaLocation or
25134: * noNamespaceSchemaLocation."
25135: */
25136: if (vctxt->nbAttrInfos == 0)
25137: return (0);
25138: for (i = 0; i < vctxt->nbAttrInfos; i++) {
25139: iattr = vctxt->attrInfos[i];
25140: if (! iattr->metaType) {
25141: ACTIVATE_ATTRIBUTE(iattr)
25142: xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25143: XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25144: ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25145: }
25146: }
25147: ACTIVATE_ELEM
25148: return (ret);
25149: }
25150:
25151: /*
25152: * Cleanup currently used attribute infos.
25153: */
25154: static void
25155: xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25156: {
25157: int i;
25158: xmlSchemaAttrInfoPtr attr;
25159:
25160: if (vctxt->nbAttrInfos == 0)
25161: return;
25162: for (i = 0; i < vctxt->nbAttrInfos; i++) {
25163: attr = vctxt->attrInfos[i];
25164: if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25165: if (attr->localName != NULL)
25166: xmlFree((xmlChar *) attr->localName);
25167: if (attr->nsName != NULL)
25168: xmlFree((xmlChar *) attr->nsName);
25169: }
25170: if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25171: if (attr->value != NULL)
25172: xmlFree((xmlChar *) attr->value);
25173: }
25174: if (attr->val != NULL) {
25175: xmlSchemaFreeValue(attr->val);
25176: attr->val = NULL;
25177: }
25178: memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25179: }
25180: vctxt->nbAttrInfos = 0;
25181: }
25182:
25183: /*
25184: * 3.4.4 Complex Type Definition Validation Rules
25185: * Element Locally Valid (Complex Type) (cvc-complex-type)
25186: * 3.2.4 Attribute Declaration Validation Rules
25187: * Validation Rule: Attribute Locally Valid (cvc-attribute)
25188: * Attribute Locally Valid (Use) (cvc-au)
25189: *
25190: * Only "assessed" attribute information items will be visible to
25191: * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25192: */
25193: static int
25194: xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25195: {
25196: xmlSchemaTypePtr type = vctxt->inode->typeDef;
25197: xmlSchemaItemListPtr attrUseList;
25198: xmlSchemaAttributeUsePtr attrUse = NULL;
25199: xmlSchemaAttributePtr attrDecl = NULL;
25200: xmlSchemaAttrInfoPtr iattr, tmpiattr;
25201: int i, j, found, nbAttrs, nbUses;
25202: int xpathRes = 0, res, wildIDs = 0, fixed;
25203: xmlNodePtr defAttrOwnerElem = NULL;
25204:
25205: /*
25206: * SPEC (cvc-attribute)
25207: * (1) "The declaration must not be �absent� (see Missing
25208: * Sub-components (�5.3) for how this can fail to be
25209: * the case)."
25210: * (2) "Its {type definition} must not be absent."
25211: *
25212: * NOTE (1) + (2): This is not handled here, since we currently do not
25213: * allow validation against schemas which have missing sub-components.
25214: *
25215: * SPEC (cvc-complex-type)
25216: * (3) "For each attribute information item in the element information
25217: * item's [attributes] excepting those whose [namespace name] is
25218: * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25219: * [local name] is one of type, nil, schemaLocation or
25220: * noNamespaceSchemaLocation, the appropriate case among the following
25221: * must be true:
25222: *
25223: */
25224: attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25225: /*
25226: * @nbAttrs is the number of attributes present in the instance.
25227: */
25228: nbAttrs = vctxt->nbAttrInfos;
25229: if (attrUseList != NULL)
25230: nbUses = attrUseList->nbItems;
25231: else
25232: nbUses = 0;
25233: for (i = 0; i < nbUses; i++) {
25234: found = 0;
25235: attrUse = attrUseList->items[i];
25236: attrDecl = WXS_ATTRUSE_DECL(attrUse);
25237: for (j = 0; j < nbAttrs; j++) {
25238: iattr = vctxt->attrInfos[j];
25239: /*
25240: * SPEC (cvc-complex-type) (3)
25241: * Skip meta attributes.
25242: */
25243: if (iattr->metaType)
25244: continue;
25245: if (iattr->localName[0] != attrDecl->name[0])
25246: continue;
25247: if (!xmlStrEqual(iattr->localName, attrDecl->name))
25248: continue;
25249: if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25250: continue;
25251: found = 1;
25252: /*
25253: * SPEC (cvc-complex-type)
25254: * (3.1) "If there is among the {attribute uses} an attribute
25255: * use with an {attribute declaration} whose {name} matches
25256: * the attribute information item's [local name] and whose
25257: * {target namespace} is identical to the attribute information
25258: * item's [namespace name] (where an �absent� {target namespace}
25259: * is taken to be identical to a [namespace name] with no value),
25260: * then the attribute information must be �valid� with respect
25261: * to that attribute use as per Attribute Locally Valid (Use)
25262: * (�3.5.4). In this case the {attribute declaration} of that
25263: * attribute use is the �context-determined declaration� for the
25264: * attribute information item with respect to Schema-Validity
25265: * Assessment (Attribute) (�3.2.4) and
25266: * Assessment Outcome (Attribute) (�3.2.5).
25267: */
25268: iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25269: iattr->use = attrUse;
25270: /*
25271: * Context-determined declaration.
25272: */
25273: iattr->decl = attrDecl;
25274: iattr->typeDef = attrDecl->subtypes;
25275: break;
25276: }
25277:
25278: if (found)
25279: continue;
25280:
25281: if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25282: /*
25283: * Handle non-existent, required attributes.
25284: *
25285: * SPEC (cvc-complex-type)
25286: * (4) "The {attribute declaration} of each attribute use in
25287: * the {attribute uses} whose {required} is true matches one
25288: * of the attribute information items in the element information
25289: * item's [attributes] as per clause 3.1 above."
25290: */
25291: tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25292: if (tmpiattr == NULL) {
25293: VERROR_INT(
25294: "xmlSchemaVAttributesComplex",
25295: "calling xmlSchemaGetFreshAttrInfo()");
25296: return (-1);
25297: }
25298: tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25299: tmpiattr->use = attrUse;
25300: tmpiattr->decl = attrDecl;
25301: } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25302: ((attrUse->defValue != NULL) ||
25303: (attrDecl->defValue != NULL))) {
25304: /*
25305: * Handle non-existent, optional, default/fixed attributes.
25306: */
25307: tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25308: if (tmpiattr == NULL) {
25309: VERROR_INT(
25310: "xmlSchemaVAttributesComplex",
25311: "calling xmlSchemaGetFreshAttrInfo()");
25312: return (-1);
25313: }
25314: tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25315: tmpiattr->use = attrUse;
25316: tmpiattr->decl = attrDecl;
25317: tmpiattr->typeDef = attrDecl->subtypes;
25318: tmpiattr->localName = attrDecl->name;
25319: tmpiattr->nsName = attrDecl->targetNamespace;
25320: }
25321: }
25322:
25323: if (vctxt->nbAttrInfos == 0)
25324: return (0);
25325: /*
25326: * Validate against the wildcard.
25327: */
25328: if (type->attributeWildcard != NULL) {
25329: /*
25330: * SPEC (cvc-complex-type)
25331: * (3.2.1) "There must be an {attribute wildcard}."
25332: */
25333: for (i = 0; i < nbAttrs; i++) {
25334: iattr = vctxt->attrInfos[i];
25335: /*
25336: * SPEC (cvc-complex-type) (3)
25337: * Skip meta attributes.
25338: */
25339: if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25340: continue;
25341: /*
25342: * SPEC (cvc-complex-type)
25343: * (3.2.2) "The attribute information item must be �valid� with
25344: * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
25345: *
25346: * SPEC Item Valid (Wildcard) (cvc-wildcard)
25347: * "... its [namespace name] must be �valid� with respect to
25348: * the wildcard constraint, as defined in Wildcard allows
25349: * Namespace Name (�3.10.4)."
25350: */
25351: if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25352: iattr->nsName) == 0) {
25353: /*
25354: * Handle processContents.
25355: *
25356: * SPEC (cvc-wildcard):
25357: * processContents | context-determined declaration:
25358: * "strict" "mustFind"
25359: * "lax" "none"
25360: * "skip" "skip"
25361: */
25362: if (type->attributeWildcard->processContents ==
25363: XML_SCHEMAS_ANY_SKIP) {
25364: /*
25365: * context-determined declaration = "skip"
25366: *
25367: * SPEC PSVI Assessment Outcome (Attribute)
25368: * [validity] = "notKnown"
25369: * [validation attempted] = "none"
25370: */
25371: iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25372: continue;
25373: }
25374: /*
25375: * Find an attribute declaration.
25376: */
25377: iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25378: iattr->localName, iattr->nsName);
25379: if (iattr->decl != NULL) {
25380: iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25381: /*
25382: * SPEC (cvc-complex-type)
25383: * (5) "Let [Definition:] the wild IDs be the set of
25384: * all attribute information item to which clause 3.2
25385: * applied and whose �validation� resulted in a
25386: * �context-determined declaration� of mustFind or no
25387: * �context-determined declaration� at all, and whose
25388: * [local name] and [namespace name] resolve (as
25389: * defined by QName resolution (Instance) (�3.15.4)) to
25390: * an attribute declaration whose {type definition} is
25391: * or is derived from ID. Then all of the following
25392: * must be true:"
25393: */
25394: iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25395: if (xmlSchemaIsDerivedFromBuiltInType(
25396: iattr->typeDef, XML_SCHEMAS_ID)) {
25397: /*
25398: * SPEC (5.1) "There must be no more than one
25399: * item in �wild IDs�."
25400: */
25401: if (wildIDs != 0) {
25402: /* VAL TODO */
25403: iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25404: TODO
25405: continue;
25406: }
25407: wildIDs++;
25408: /*
25409: * SPEC (cvc-complex-type)
25410: * (5.2) "If �wild IDs� is non-empty, there must not
25411: * be any attribute uses among the {attribute uses}
25412: * whose {attribute declaration}'s {type definition}
25413: * is or is derived from ID."
25414: */
25415: if (attrUseList != NULL) {
25416: for (j = 0; j < attrUseList->nbItems; j++) {
25417: if (xmlSchemaIsDerivedFromBuiltInType(
25418: WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25419: XML_SCHEMAS_ID)) {
25420: /* URGENT VAL TODO: implement */
25421: iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25422: TODO
25423: break;
25424: }
25425: }
25426: }
25427: }
25428: } else if (type->attributeWildcard->processContents ==
25429: XML_SCHEMAS_ANY_LAX) {
25430: iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25431: /*
25432: * SPEC PSVI Assessment Outcome (Attribute)
25433: * [validity] = "notKnown"
25434: * [validation attempted] = "none"
25435: */
25436: } else {
25437: iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25438: }
25439: }
25440: }
25441: }
25442:
25443: if (vctxt->nbAttrInfos == 0)
25444: return (0);
25445:
25446: /*
25447: * Get the owner element; needed for creation of default attributes.
25448: * This fixes bug #341337, reported by David Grohmann.
25449: */
25450: if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25451: xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25452: if (ielem && ielem->node && ielem->node->doc)
25453: defAttrOwnerElem = ielem->node;
25454: }
25455: /*
25456: * Validate values, create default attributes, evaluate IDCs.
25457: */
25458: for (i = 0; i < vctxt->nbAttrInfos; i++) {
25459: iattr = vctxt->attrInfos[i];
25460: /*
25461: * VAL TODO: Note that we won't try to resolve IDCs to
25462: * "lax" and "skip" validated attributes. Check what to
25463: * do in this case.
25464: */
25465: if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25466: (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25467: continue;
25468: /*
25469: * VAL TODO: What to do if the type definition is missing?
25470: */
25471: if (iattr->typeDef == NULL) {
25472: iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25473: continue;
25474: }
25475:
25476: ACTIVATE_ATTRIBUTE(iattr);
25477: fixed = 0;
25478: xpathRes = 0;
25479:
25480: if (vctxt->xpathStates != NULL) {
25481: /*
25482: * Evaluate IDCs.
25483: */
25484: xpathRes = xmlSchemaXPathEvaluate(vctxt,
25485: XML_ATTRIBUTE_NODE);
25486: if (xpathRes == -1) {
25487: VERROR_INT("xmlSchemaVAttributesComplex",
25488: "calling xmlSchemaXPathEvaluate()");
25489: goto internal_error;
25490: }
25491: }
25492:
25493: if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25494: /*
25495: * Default/fixed attributes.
25496: * We need the value only if we need to resolve IDCs or
25497: * will create default attributes.
25498: */
25499: if ((xpathRes) || (defAttrOwnerElem)) {
25500: if (iattr->use->defValue != NULL) {
25501: iattr->value = (xmlChar *) iattr->use->defValue;
25502: iattr->val = iattr->use->defVal;
25503: } else {
25504: iattr->value = (xmlChar *) iattr->decl->defValue;
25505: iattr->val = iattr->decl->defVal;
25506: }
25507: /*
25508: * IDCs will consume the precomputed default value,
25509: * so we need to clone it.
25510: */
25511: if (iattr->val == NULL) {
25512: VERROR_INT("xmlSchemaVAttributesComplex",
25513: "default/fixed value on an attribute use was "
25514: "not precomputed");
25515: goto internal_error;
25516: }
25517: iattr->val = xmlSchemaCopyValue(iattr->val);
25518: if (iattr->val == NULL) {
25519: VERROR_INT("xmlSchemaVAttributesComplex",
25520: "calling xmlSchemaCopyValue()");
25521: goto internal_error;
25522: }
25523: }
25524: /*
25525: * PSVI: Add the default attribute to the current element.
25526: * VAL TODO: Should we use the *normalized* value? This currently
25527: * uses the *initial* value.
25528: */
25529:
25530: if (defAttrOwnerElem) {
25531: xmlChar *normValue;
25532: const xmlChar *value;
25533:
25534: value = iattr->value;
25535: /*
25536: * Normalize the value.
25537: */
25538: normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25539: iattr->value);
25540: if (normValue != NULL)
25541: value = BAD_CAST normValue;
25542:
25543: if (iattr->nsName == NULL) {
25544: if (xmlNewProp(defAttrOwnerElem,
25545: iattr->localName, value) == NULL) {
25546: VERROR_INT("xmlSchemaVAttributesComplex",
25547: "callling xmlNewProp()");
25548: if (normValue != NULL)
25549: xmlFree(normValue);
25550: goto internal_error;
25551: }
25552: } else {
25553: xmlNsPtr ns;
25554:
25555: ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25556: defAttrOwnerElem, iattr->nsName);
25557: if (ns == NULL) {
25558: xmlChar prefix[12];
25559: int counter = 0;
25560:
25561: /*
25562: * Create a namespace declaration on the validation
25563: * root node if no namespace declaration is in scope.
25564: */
25565: do {
25566: snprintf((char *) prefix, 12, "p%d", counter++);
25567: ns = xmlSearchNs(defAttrOwnerElem->doc,
25568: defAttrOwnerElem, BAD_CAST prefix);
25569: if (counter > 1000) {
25570: VERROR_INT(
25571: "xmlSchemaVAttributesComplex",
25572: "could not compute a ns prefix for a "
25573: "default/fixed attribute");
25574: if (normValue != NULL)
25575: xmlFree(normValue);
25576: goto internal_error;
25577: }
25578: } while (ns != NULL);
25579: ns = xmlNewNs(vctxt->validationRoot,
25580: iattr->nsName, BAD_CAST prefix);
25581: }
25582: /*
25583: * TODO:
25584: * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25585: * If we have QNames: do we need to ensure there's a
25586: * prefix defined for the QName?
25587: */
25588: xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25589: }
25590: if (normValue != NULL)
25591: xmlFree(normValue);
25592: }
25593: /*
25594: * Go directly to IDC evaluation.
25595: */
25596: goto eval_idcs;
25597: }
25598: /*
25599: * Validate the value.
25600: */
25601: if (vctxt->value != NULL) {
25602: /*
25603: * Free last computed value; just for safety reasons.
25604: */
25605: xmlSchemaFreeValue(vctxt->value);
25606: vctxt->value = NULL;
25607: }
25608: /*
25609: * Note that the attribute *use* can be unavailable, if
25610: * the attribute was a wild attribute.
25611: */
25612: if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25613: ((iattr->use != NULL) &&
25614: (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25615: fixed = 1;
25616: else
25617: fixed = 0;
25618: /*
25619: * SPEC (cvc-attribute)
25620: * (3) "The item's �normalized value� must be locally �valid�
25621: * with respect to that {type definition} as per
25622: * String Valid (�3.14.4)."
25623: *
25624: * VAL TODO: Do we already have the
25625: * "normalized attribute value" here?
25626: */
25627: if (xpathRes || fixed) {
25628: iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25629: /*
25630: * Request a computed value.
25631: */
25632: res = xmlSchemaVCheckCVCSimpleType(
25633: ACTXT_CAST vctxt,
25634: iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25635: 1, 1, 0);
25636: } else {
25637: res = xmlSchemaVCheckCVCSimpleType(
25638: ACTXT_CAST vctxt,
25639: iattr->node, iattr->typeDef, iattr->value, NULL,
25640: 1, 0, 0);
25641: }
25642:
25643: if (res != 0) {
25644: if (res == -1) {
25645: VERROR_INT("xmlSchemaVAttributesComplex",
25646: "calling xmlSchemaStreamValidateSimpleTypeValue()");
25647: goto internal_error;
25648: }
25649: iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25650: /*
25651: * SPEC PSVI Assessment Outcome (Attribute)
25652: * [validity] = "invalid"
25653: */
25654: goto eval_idcs;
25655: }
25656:
25657: if (fixed) {
25658: /*
25659: * SPEC Attribute Locally Valid (Use) (cvc-au)
25660: * "For an attribute information item to be�valid�
25661: * with respect to an attribute use its *normalized*
25662: * value� must match the *canonical* lexical
25663: * representation of the attribute use's {value
25664: * constraint}value, if it is present and fixed."
25665: *
25666: * VAL TODO: The requirement for the *canonical* value
25667: * will be removed in XML Schema 1.1.
25668: */
25669: /*
25670: * SPEC Attribute Locally Valid (cvc-attribute)
25671: * (4) "The item's *actual* value� must match the *value* of
25672: * the {value constraint}, if it is present and fixed."
25673: */
25674: if (iattr->val == NULL) {
25675: /* VAL TODO: A value was not precomputed. */
25676: TODO
25677: goto eval_idcs;
25678: }
25679: if ((iattr->use != NULL) &&
25680: (iattr->use->defValue != NULL)) {
25681: if (iattr->use->defVal == NULL) {
25682: /* VAL TODO: A default value was not precomputed. */
25683: TODO
25684: goto eval_idcs;
25685: }
25686: iattr->vcValue = iattr->use->defValue;
25687: /*
25688: if (xmlSchemaCompareValuesWhtsp(attr->val,
25689: (xmlSchemaWhitespaceValueType) ws,
25690: attr->use->defVal,
25691: (xmlSchemaWhitespaceValueType) ws) != 0) {
25692: */
25693: if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25694: iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25695: } else {
25696: if (iattr->decl->defVal == NULL) {
25697: /* VAL TODO: A default value was not precomputed. */
25698: TODO
25699: goto eval_idcs;
25700: }
25701: iattr->vcValue = iattr->decl->defValue;
25702: /*
25703: if (xmlSchemaCompareValuesWhtsp(attr->val,
25704: (xmlSchemaWhitespaceValueType) ws,
25705: attrDecl->defVal,
25706: (xmlSchemaWhitespaceValueType) ws) != 0) {
25707: */
25708: if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25709: iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25710: }
25711: /*
25712: * [validity] = "valid"
25713: */
25714: }
25715: eval_idcs:
25716: /*
25717: * Evaluate IDCs.
25718: */
25719: if (xpathRes) {
25720: if (xmlSchemaXPathProcessHistory(vctxt,
25721: vctxt->depth +1) == -1) {
25722: VERROR_INT("xmlSchemaVAttributesComplex",
25723: "calling xmlSchemaXPathEvaluate()");
25724: goto internal_error;
25725: }
25726: } else if (vctxt->xpathStates != NULL)
25727: xmlSchemaXPathPop(vctxt);
25728: }
25729:
25730: /*
25731: * Report errors.
25732: */
25733: for (i = 0; i < vctxt->nbAttrInfos; i++) {
25734: iattr = vctxt->attrInfos[i];
25735: if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25736: (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25737: (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25738: (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25739: continue;
25740: ACTIVATE_ATTRIBUTE(iattr);
25741: switch (iattr->state) {
25742: case XML_SCHEMAS_ATTR_ERR_MISSING: {
25743: xmlChar *str = NULL;
25744: ACTIVATE_ELEM;
25745: xmlSchemaCustomErr(ACTXT_CAST vctxt,
25746: XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25747: "The attribute '%s' is required but missing",
25748: xmlSchemaFormatQName(&str,
25749: iattr->decl->targetNamespace,
25750: iattr->decl->name),
25751: NULL);
25752: FREE_AND_NULL(str)
25753: break;
25754: }
25755: case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25756: VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25757: "The type definition is absent");
25758: break;
25759: case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25760: xmlSchemaCustomErr(ACTXT_CAST vctxt,
25761: XML_SCHEMAV_CVC_AU, NULL, NULL,
25762: "The value '%s' does not match the fixed "
25763: "value constraint '%s'",
25764: iattr->value, iattr->vcValue);
25765: break;
25766: case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25767: VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25768: "No matching global attribute declaration available, but "
25769: "demanded by the strict wildcard");
25770: break;
25771: case XML_SCHEMAS_ATTR_UNKNOWN:
25772: if (iattr->metaType)
25773: break;
25774: /*
25775: * MAYBE VAL TODO: One might report different error messages
25776: * for the following errors.
25777: */
25778: if (type->attributeWildcard == NULL) {
25779: xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25780: XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25781: } else {
25782: xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25783: XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25784: }
25785: break;
25786: default:
25787: break;
25788: }
25789: }
25790:
25791: ACTIVATE_ELEM;
25792: return (0);
25793: internal_error:
25794: ACTIVATE_ELEM;
25795: return (-1);
25796: }
25797:
25798: static int
25799: xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25800: int *skip)
25801: {
25802: xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25803: /*
25804: * The namespace of the element was already identified to be
25805: * matching the wildcard.
25806: */
25807: if ((skip == NULL) || (wild == NULL) ||
25808: (wild->type != XML_SCHEMA_TYPE_ANY)) {
25809: VERROR_INT("xmlSchemaValidateElemWildcard",
25810: "bad arguments");
25811: return (-1);
25812: }
25813: *skip = 0;
25814: if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25815: /*
25816: * URGENT VAL TODO: Either we need to position the stream to the
25817: * next sibling, or walk the whole subtree.
25818: */
25819: *skip = 1;
25820: return (0);
25821: }
25822: {
25823: xmlSchemaElementPtr decl = NULL;
25824:
25825: decl = xmlSchemaGetElem(vctxt->schema,
25826: vctxt->inode->localName, vctxt->inode->nsName);
25827: if (decl != NULL) {
25828: vctxt->inode->decl = decl;
25829: return (0);
25830: }
25831: }
25832: if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25833: /* VAL TODO: Change to proper error code. */
25834: VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25835: "No matching global element declaration available, but "
25836: "demanded by the strict wildcard");
25837: return (vctxt->err);
25838: }
25839: if (vctxt->nbAttrInfos != 0) {
25840: xmlSchemaAttrInfoPtr iattr;
25841: /*
25842: * SPEC Validation Rule: Schema-Validity Assessment (Element)
25843: * (1.2.1.2.1) - (1.2.1.2.3 )
25844: *
25845: * Use the xsi:type attribute for the type definition.
25846: */
25847: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25848: XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25849: if (iattr != NULL) {
25850: if (xmlSchemaProcessXSIType(vctxt, iattr,
25851: &(vctxt->inode->typeDef), NULL) == -1) {
25852: VERROR_INT("xmlSchemaValidateElemWildcard",
25853: "calling xmlSchemaProcessXSIType() to "
25854: "process the attribute 'xsi:nil'");
25855: return (-1);
25856: }
25857: /*
25858: * Don't return an error on purpose.
25859: */
25860: return (0);
25861: }
25862: }
25863: /*
25864: * SPEC Validation Rule: Schema-Validity Assessment (Element)
25865: *
25866: * Fallback to "anyType".
25867: */
25868: vctxt->inode->typeDef =
25869: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25870: return (0);
25871: }
25872:
25873: /*
25874: * xmlSchemaCheckCOSValidDefault:
25875: *
25876: * This will be called if: not nilled, no content and a default/fixed
25877: * value is provided.
25878: */
25879:
25880: static int
25881: xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25882: const xmlChar *value,
25883: xmlSchemaValPtr *val)
25884: {
25885: int ret = 0;
25886: xmlSchemaNodeInfoPtr inode = vctxt->inode;
25887:
25888: /*
25889: * cos-valid-default:
25890: * Schema Component Constraint: Element Default Valid (Immediate)
25891: * For a string to be a valid default with respect to a type
25892: * definition the appropriate case among the following must be true:
25893: */
25894: if WXS_IS_COMPLEX(inode->typeDef) {
25895: /*
25896: * Complex type.
25897: *
25898: * SPEC (2.1) "its {content type} must be a simple type definition
25899: * or mixed."
25900: * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25901: * type}'s particle must be �emptiable� as defined by
25902: * Particle Emptiable (�3.9.6)."
25903: */
25904: if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25905: ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25906: (! WXS_EMPTIABLE(inode->typeDef)))) {
25907: ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25908: /* NOTE that this covers (2.2.2) as well. */
25909: VERROR(ret, NULL,
25910: "For a string to be a valid default, the type definition "
25911: "must be a simple type or a complex type with simple content "
25912: "or mixed content and a particle emptiable");
25913: return(ret);
25914: }
25915: }
25916: /*
25917: * 1 If the type definition is a simple type definition, then the string
25918: * must be �valid� with respect to that definition as defined by String
25919: * Valid (�3.14.4).
25920: *
25921: * AND
25922: *
25923: * 2.2.1 If the {content type} is a simple type definition, then the
25924: * string must be �valid� with respect to that simple type definition
25925: * as defined by String Valid (�3.14.4).
25926: */
25927: if (WXS_IS_SIMPLE(inode->typeDef)) {
25928:
25929: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25930: NULL, inode->typeDef, value, val, 1, 1, 0);
25931:
25932: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25933:
25934: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25935: NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25936: }
25937: if (ret < 0) {
25938: VERROR_INT("xmlSchemaCheckCOSValidDefault",
25939: "calling xmlSchemaVCheckCVCSimpleType()");
25940: }
25941: return (ret);
25942: }
25943:
25944: static void
25945: xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25946: const xmlChar * name ATTRIBUTE_UNUSED,
25947: xmlSchemaElementPtr item,
25948: xmlSchemaNodeInfoPtr inode)
25949: {
25950: inode->decl = item;
25951: #ifdef DEBUG_CONTENT
25952: {
25953: xmlChar *str = NULL;
25954:
25955: if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25956: xmlGenericError(xmlGenericErrorContext,
25957: "AUTOMATON callback for '%s' [declaration]\n",
25958: xmlSchemaFormatQName(&str,
25959: inode->localName, inode->nsName));
25960: } else {
25961: xmlGenericError(xmlGenericErrorContext,
25962: "AUTOMATON callback for '%s' [wildcard]\n",
25963: xmlSchemaFormatQName(&str,
25964: inode->localName, inode->nsName));
25965:
25966: }
25967: FREE_AND_NULL(str)
25968: }
25969: #endif
25970: }
25971:
25972: static int
25973: xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25974: {
25975: vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25976: if (vctxt->inode == NULL) {
25977: VERROR_INT("xmlSchemaValidatorPushElem",
25978: "calling xmlSchemaGetFreshElemInfo()");
25979: return (-1);
25980: }
25981: vctxt->nbAttrInfos = 0;
25982: return (0);
25983: }
25984:
25985: static int
25986: xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25987: xmlSchemaNodeInfoPtr inode,
25988: xmlSchemaTypePtr type,
25989: const xmlChar *value)
25990: {
25991: if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25992: return (xmlSchemaVCheckCVCSimpleType(
25993: ACTXT_CAST vctxt, NULL,
25994: type, value, &(inode->val), 1, 1, 0));
25995: else
25996: return (xmlSchemaVCheckCVCSimpleType(
25997: ACTXT_CAST vctxt, NULL,
25998: type, value, NULL, 1, 0, 0));
25999: }
26000:
26001:
26002:
26003: /*
26004: * Process END of element.
26005: */
26006: static int
26007: xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26008: {
26009: int ret = 0;
26010: xmlSchemaNodeInfoPtr inode = vctxt->inode;
26011:
26012: if (vctxt->nbAttrInfos != 0)
26013: xmlSchemaClearAttrInfos(vctxt);
26014: if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26015: /*
26016: * This element was not expected;
26017: * we will not validate child elements of broken parents.
26018: * Skip validation of all content of the parent.
26019: */
26020: vctxt->skipDepth = vctxt->depth -1;
26021: goto end_elem;
26022: }
26023: if ((inode->typeDef == NULL) ||
26024: (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26025: /*
26026: * 1. the type definition might be missing if the element was
26027: * error prone
26028: * 2. it might be abstract.
26029: */
26030: goto end_elem;
26031: }
26032: /*
26033: * Check the content model.
26034: */
26035: if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26036: (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26037:
26038: /*
26039: * Workaround for "anyType".
26040: */
26041: if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26042: goto character_content;
26043:
26044: if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26045: xmlChar *values[10];
26046: int terminal, nbval = 10, nbneg;
26047:
26048: if (inode->regexCtxt == NULL) {
26049: /*
26050: * Create the regex context.
26051: */
26052: inode->regexCtxt =
26053: xmlRegNewExecCtxt(inode->typeDef->contModel,
26054: (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26055: vctxt);
26056: if (inode->regexCtxt == NULL) {
26057: VERROR_INT("xmlSchemaValidatorPopElem",
26058: "failed to create a regex context");
26059: goto internal_error;
26060: }
26061: #ifdef DEBUG_AUTOMATA
26062: xmlGenericError(xmlGenericErrorContext,
26063: "AUTOMATON create on '%s'\n", inode->localName);
26064: #endif
26065: }
1.1.1.3 ! misho 26066:
! 26067: /*
! 26068: * Do not check further content if the node has been nilled
! 26069: */
! 26070: if (INODE_NILLED(inode)) {
! 26071: ret = 0;
! 26072: #ifdef DEBUG_AUTOMATA
! 26073: xmlGenericError(xmlGenericErrorContext,
! 26074: "AUTOMATON succeeded on nilled '%s'\n",
! 26075: inode->localName);
! 26076: #endif
! 26077: goto skip_nilled;
! 26078: }
! 26079:
1.1 misho 26080: /*
26081: * Get hold of the still expected content, since a further
26082: * call to xmlRegExecPushString() will loose this information.
26083: */
26084: xmlRegExecNextValues(inode->regexCtxt,
26085: &nbval, &nbneg, &values[0], &terminal);
26086: ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26087: if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26088: /*
26089: * Still missing something.
26090: */
26091: ret = 1;
26092: inode->flags |=
26093: XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26094: xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26095: XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26096: "Missing child element(s)",
26097: nbval, nbneg, values);
26098: #ifdef DEBUG_AUTOMATA
26099: xmlGenericError(xmlGenericErrorContext,
26100: "AUTOMATON missing ERROR on '%s'\n",
26101: inode->localName);
26102: #endif
26103: } else {
26104: /*
26105: * Content model is satisfied.
26106: */
26107: ret = 0;
26108: #ifdef DEBUG_AUTOMATA
26109: xmlGenericError(xmlGenericErrorContext,
26110: "AUTOMATON succeeded on '%s'\n",
26111: inode->localName);
26112: #endif
26113: }
26114:
26115: }
26116: }
1.1.1.3 ! misho 26117:
! 26118: skip_nilled:
! 26119:
1.1 misho 26120: if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26121: goto end_elem;
26122:
26123: character_content:
26124:
26125: if (vctxt->value != NULL) {
26126: xmlSchemaFreeValue(vctxt->value);
26127: vctxt->value = NULL;
26128: }
26129: /*
26130: * Check character content.
26131: */
26132: if (inode->decl == NULL) {
26133: /*
26134: * Speedup if no declaration exists.
26135: */
26136: if (WXS_IS_SIMPLE(inode->typeDef)) {
26137: ret = xmlSchemaVCheckINodeDataType(vctxt,
26138: inode, inode->typeDef, inode->value);
26139: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26140: ret = xmlSchemaVCheckINodeDataType(vctxt,
26141: inode, inode->typeDef->contentTypeDef,
26142: inode->value);
26143: }
26144: if (ret < 0) {
26145: VERROR_INT("xmlSchemaValidatorPopElem",
26146: "calling xmlSchemaVCheckCVCSimpleType()");
26147: goto internal_error;
26148: }
26149: goto end_elem;
26150: }
26151: /*
26152: * cvc-elt (3.3.4) : 5
26153: * The appropriate case among the following must be true:
26154: */
26155: /*
26156: * cvc-elt (3.3.4) : 5.1
26157: * If the declaration has a {value constraint},
26158: * the item has neither element nor character [children] and
26159: * clause 3.2 has not applied, then all of the following must be true:
26160: */
26161: if ((inode->decl->value != NULL) &&
26162: (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26163: (! INODE_NILLED(inode))) {
26164: /*
26165: * cvc-elt (3.3.4) : 5.1.1
26166: * If the �actual type definition� is a �local type definition�
26167: * then the canonical lexical representation of the {value constraint}
26168: * value must be a valid default for the �actual type definition� as
26169: * defined in Element Default Valid (Immediate) (�3.3.6).
26170: */
26171: /*
26172: * NOTE: 'local' above means types acquired by xsi:type.
26173: * NOTE: Although the *canonical* value is stated, it is not
26174: * relevant if canonical or not. Additionally XML Schema 1.1
26175: * will removed this requirement as well.
26176: */
26177: if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26178:
26179: ret = xmlSchemaCheckCOSValidDefault(vctxt,
26180: inode->decl->value, &(inode->val));
26181: if (ret != 0) {
26182: if (ret < 0) {
26183: VERROR_INT("xmlSchemaValidatorPopElem",
26184: "calling xmlSchemaCheckCOSValidDefault()");
26185: goto internal_error;
26186: }
26187: goto end_elem;
26188: }
26189: /*
26190: * Stop here, to avoid redundant validation of the value
26191: * (see following).
26192: */
26193: goto default_psvi;
26194: }
26195: /*
26196: * cvc-elt (3.3.4) : 5.1.2
26197: * The element information item with the canonical lexical
26198: * representation of the {value constraint} value used as its
26199: * �normalized value� must be �valid� with respect to the
26200: * �actual type definition� as defined by Element Locally Valid (Type)
26201: * (�3.3.4).
26202: */
26203: if (WXS_IS_SIMPLE(inode->typeDef)) {
26204: ret = xmlSchemaVCheckINodeDataType(vctxt,
26205: inode, inode->typeDef, inode->decl->value);
26206: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26207: ret = xmlSchemaVCheckINodeDataType(vctxt,
26208: inode, inode->typeDef->contentTypeDef,
26209: inode->decl->value);
26210: }
26211: if (ret != 0) {
26212: if (ret < 0) {
26213: VERROR_INT("xmlSchemaValidatorPopElem",
26214: "calling xmlSchemaVCheckCVCSimpleType()");
26215: goto internal_error;
26216: }
26217: goto end_elem;
26218: }
26219:
26220: default_psvi:
26221: /*
26222: * PSVI: Create a text node on the instance element.
26223: */
26224: if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26225: (inode->node != NULL)) {
26226: xmlNodePtr textChild;
26227: xmlChar *normValue;
26228: /*
26229: * VAL TODO: Normalize the value.
26230: */
26231: normValue = xmlSchemaNormalizeValue(inode->typeDef,
26232: inode->decl->value);
26233: if (normValue != NULL) {
26234: textChild = xmlNewText(BAD_CAST normValue);
26235: xmlFree(normValue);
26236: } else
26237: textChild = xmlNewText(inode->decl->value);
26238: if (textChild == NULL) {
26239: VERROR_INT("xmlSchemaValidatorPopElem",
26240: "calling xmlNewText()");
26241: goto internal_error;
26242: } else
26243: xmlAddChild(inode->node, textChild);
26244: }
26245:
26246: } else if (! INODE_NILLED(inode)) {
26247: /*
26248: * 5.2.1 The element information item must be �valid� with respect
26249: * to the �actual type definition� as defined by Element Locally
26250: * Valid (Type) (�3.3.4).
26251: */
26252: if (WXS_IS_SIMPLE(inode->typeDef)) {
26253: /*
26254: * SPEC (cvc-type) (3.1)
26255: * "If the type definition is a simple type definition, ..."
26256: * (3.1.3) "If clause 3.2 of Element Locally Valid
26257: * (Element) (�3.3.4) did not apply, then the �normalized value�
26258: * must be �valid� with respect to the type definition as defined
26259: * by String Valid (�3.14.4).
26260: */
26261: ret = xmlSchemaVCheckINodeDataType(vctxt,
26262: inode, inode->typeDef, inode->value);
26263: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26264: /*
26265: * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26266: * definition, then the element information item must be
26267: * �valid� with respect to the type definition as per
26268: * Element Locally Valid (Complex Type) (�3.4.4);"
26269: *
26270: * SPEC (cvc-complex-type) (2.2)
26271: * "If the {content type} is a simple type definition, ...
26272: * the �normalized value� of the element information item is
26273: * �valid� with respect to that simple type definition as
26274: * defined by String Valid (�3.14.4)."
26275: */
26276: ret = xmlSchemaVCheckINodeDataType(vctxt,
26277: inode, inode->typeDef->contentTypeDef, inode->value);
26278: }
26279: if (ret != 0) {
26280: if (ret < 0) {
26281: VERROR_INT("xmlSchemaValidatorPopElem",
26282: "calling xmlSchemaVCheckCVCSimpleType()");
26283: goto internal_error;
26284: }
26285: goto end_elem;
26286: }
26287: /*
26288: * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26289: * not applied, all of the following must be true:
26290: */
26291: if ((inode->decl->value != NULL) &&
26292: (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26293:
26294: /*
26295: * TODO: We will need a computed value, when comparison is
26296: * done on computed values.
26297: */
26298: /*
26299: * 5.2.2.1 The element information item must have no element
26300: * information item [children].
26301: */
26302: if (inode->flags &
26303: XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26304: ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26305: VERROR(ret, NULL,
26306: "The content must not containt element nodes since "
26307: "there is a fixed value constraint");
26308: goto end_elem;
26309: } else {
26310: /*
26311: * 5.2.2.2 The appropriate case among the following must
26312: * be true:
26313: */
26314: if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26315: /*
26316: * 5.2.2.2.1 If the {content type} of the �actual type
26317: * definition� is mixed, then the *initial value* of the
26318: * item must match the canonical lexical representation
26319: * of the {value constraint} value.
26320: *
26321: * ... the *initial value* of an element information
26322: * item is the string composed of, in order, the
26323: * [character code] of each character information item in
26324: * the [children] of that element information item.
26325: */
26326: if (! xmlStrEqual(inode->value, inode->decl->value)){
26327: /*
26328: * VAL TODO: Report invalid & expected values as well.
26329: * VAL TODO: Implement the canonical stuff.
26330: */
26331: ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26332: xmlSchemaCustomErr(ACTXT_CAST vctxt,
26333: ret, NULL, NULL,
26334: "The initial value '%s' does not match the fixed "
26335: "value constraint '%s'",
26336: inode->value, inode->decl->value);
26337: goto end_elem;
26338: }
26339: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26340: /*
26341: * 5.2.2.2.2 If the {content type} of the �actual type
26342: * definition� is a simple type definition, then the
26343: * *actual value* of the item must match the canonical
26344: * lexical representation of the {value constraint} value.
26345: */
26346: /*
26347: * VAL TODO: *actual value* is the normalized value, impl.
26348: * this.
26349: * VAL TODO: Report invalid & expected values as well.
26350: * VAL TODO: Implement a comparison with the computed values.
26351: */
26352: if (! xmlStrEqual(inode->value,
26353: inode->decl->value)) {
26354: ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26355: xmlSchemaCustomErr(ACTXT_CAST vctxt,
26356: ret, NULL, NULL,
26357: "The actual value '%s' does not match the fixed "
26358: "value constraint '%s'",
26359: inode->value,
26360: inode->decl->value);
26361: goto end_elem;
26362: }
26363: }
26364: }
26365: }
26366: }
26367:
26368: end_elem:
26369: if (vctxt->depth < 0) {
26370: /* TODO: raise error? */
26371: return (0);
26372: }
26373: if (vctxt->depth == vctxt->skipDepth)
26374: vctxt->skipDepth = -1;
26375: /*
26376: * Evaluate the history of XPath state objects.
26377: */
26378: if (inode->appliedXPath &&
26379: (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26380: goto internal_error;
26381: /*
26382: * MAYBE TODO:
26383: * SPEC (6) "The element information item must be �valid� with
26384: * respect to each of the {identity-constraint definitions} as per
26385: * Identity-constraint Satisfied (�3.11.4)."
26386: */
26387: /*
26388: * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26389: * need to be built in any case.
26390: * We will currently build IDC node-tables and bubble them only if
26391: * keyrefs do exist.
26392: */
26393:
26394: /*
26395: * Add the current IDC target-nodes to the IDC node-tables.
26396: */
26397: if ((inode->idcMatchers != NULL) &&
26398: (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26399: {
26400: if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26401: goto internal_error;
26402: }
26403: /*
26404: * Validate IDC keyrefs.
26405: */
26406: if (vctxt->inode->hasKeyrefs)
26407: if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26408: goto internal_error;
26409: /*
26410: * Merge/free the IDC table.
26411: */
26412: if (inode->idcTable != NULL) {
26413: #ifdef DEBUG_IDC_NODE_TABLE
26414: xmlSchemaDebugDumpIDCTable(stdout,
26415: inode->nsName,
26416: inode->localName,
26417: inode->idcTable);
26418: #endif
26419: if ((vctxt->depth > 0) &&
26420: (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26421: {
26422: /*
26423: * Merge the IDC node table with the table of the parent node.
26424: */
26425: if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26426: goto internal_error;
26427: }
26428: }
26429: /*
26430: * Clear the current ielem.
26431: * VAL TODO: Don't free the PSVI IDC tables if they are
26432: * requested for the PSVI.
26433: */
26434: xmlSchemaClearElemInfo(vctxt, inode);
26435: /*
26436: * Skip further processing if we are on the validation root.
26437: */
26438: if (vctxt->depth == 0) {
26439: vctxt->depth--;
26440: vctxt->inode = NULL;
26441: return (0);
26442: }
26443: /*
26444: * Reset the keyrefDepth if needed.
26445: */
26446: if (vctxt->aidcs != NULL) {
26447: xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26448: do {
26449: if (aidc->keyrefDepth == vctxt->depth) {
26450: /*
26451: * A 'keyrefDepth' of a key/unique IDC matches the current
26452: * depth, this means that we are leaving the scope of the
26453: * top-most keyref IDC which refers to this IDC.
26454: */
26455: aidc->keyrefDepth = -1;
26456: }
26457: aidc = aidc->next;
26458: } while (aidc != NULL);
26459: }
26460: vctxt->depth--;
26461: vctxt->inode = vctxt->elemInfos[vctxt->depth];
26462: /*
26463: * VAL TODO: 7 If the element information item is the �validation root�, it must be
26464: * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26465: */
26466: return (ret);
26467:
26468: internal_error:
26469: vctxt->err = -1;
26470: return (-1);
26471: }
26472:
26473: /*
26474: * 3.4.4 Complex Type Definition Validation Rules
26475: * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26476: */
26477: static int
26478: xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26479: {
26480: xmlSchemaNodeInfoPtr pielem;
26481: xmlSchemaTypePtr ptype;
26482: int ret = 0;
26483:
26484: if (vctxt->depth <= 0) {
26485: VERROR_INT("xmlSchemaValidateChildElem",
26486: "not intended for the validation root");
26487: return (-1);
26488: }
26489: pielem = vctxt->elemInfos[vctxt->depth -1];
26490: if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26491: pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26492: /*
26493: * Handle 'nilled' elements.
26494: */
26495: if (INODE_NILLED(pielem)) {
26496: /*
26497: * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26498: */
26499: ACTIVATE_PARENT_ELEM;
26500: ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26501: VERROR(ret, NULL,
26502: "Neither character nor element content is allowed, "
26503: "because the element was 'nilled'");
26504: ACTIVATE_ELEM;
26505: goto unexpected_elem;
26506: }
26507:
26508: ptype = pielem->typeDef;
26509:
26510: if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26511: /*
26512: * Workaround for "anyType": we have currently no content model
26513: * assigned for "anyType", so handle it explicitely.
26514: * "anyType" has an unbounded, lax "any" wildcard.
26515: */
26516: vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26517: vctxt->inode->localName,
26518: vctxt->inode->nsName);
26519:
26520: if (vctxt->inode->decl == NULL) {
26521: xmlSchemaAttrInfoPtr iattr;
26522: /*
26523: * Process "xsi:type".
26524: * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26525: */
26526: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26527: XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26528: if (iattr != NULL) {
26529: ret = xmlSchemaProcessXSIType(vctxt, iattr,
26530: &(vctxt->inode->typeDef), NULL);
26531: if (ret != 0) {
26532: if (ret == -1) {
26533: VERROR_INT("xmlSchemaValidateChildElem",
26534: "calling xmlSchemaProcessXSIType() to "
26535: "process the attribute 'xsi:nil'");
26536: return (-1);
26537: }
26538: return (ret);
26539: }
26540: } else {
26541: /*
26542: * Fallback to "anyType".
26543: *
26544: * SPEC (cvc-assess-elt)
26545: * "If the item cannot be �strictly assessed�, [...]
26546: * an element information item's schema validity may be laxly
26547: * assessed if its �context-determined declaration� is not
26548: * skip by �validating� with respect to the �ur-type
26549: * definition� as per Element Locally Valid (Type) (�3.3.4)."
26550: */
26551: vctxt->inode->typeDef =
26552: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26553: }
26554: }
26555: return (0);
26556: }
26557:
26558: switch (ptype->contentType) {
26559: case XML_SCHEMA_CONTENT_EMPTY:
26560: /*
26561: * SPEC (2.1) "If the {content type} is empty, then the
26562: * element information item has no character or element
26563: * information item [children]."
26564: */
26565: ACTIVATE_PARENT_ELEM
26566: ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26567: VERROR(ret, NULL,
26568: "Element content is not allowed, "
26569: "because the content type is empty");
26570: ACTIVATE_ELEM
26571: goto unexpected_elem;
26572: break;
26573:
26574: case XML_SCHEMA_CONTENT_MIXED:
26575: case XML_SCHEMA_CONTENT_ELEMENTS: {
26576: xmlRegExecCtxtPtr regexCtxt;
26577: xmlChar *values[10];
26578: int terminal, nbval = 10, nbneg;
26579:
26580: /* VAL TODO: Optimized "anyType" validation.*/
26581:
26582: if (ptype->contModel == NULL) {
26583: VERROR_INT("xmlSchemaValidateChildElem",
26584: "type has elem content but no content model");
26585: return (-1);
26586: }
26587: /*
26588: * Safety belf for evaluation if the cont. model was already
26589: * examined to be invalid.
26590: */
26591: if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26592: VERROR_INT("xmlSchemaValidateChildElem",
26593: "validating elem, but elem content is already invalid");
26594: return (-1);
26595: }
26596:
26597: regexCtxt = pielem->regexCtxt;
26598: if (regexCtxt == NULL) {
26599: /*
26600: * Create the regex context.
26601: */
26602: regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26603: (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26604: vctxt);
26605: if (regexCtxt == NULL) {
26606: VERROR_INT("xmlSchemaValidateChildElem",
26607: "failed to create a regex context");
26608: return (-1);
26609: }
26610: pielem->regexCtxt = regexCtxt;
26611: #ifdef DEBUG_AUTOMATA
26612: xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26613: pielem->localName);
26614: #endif
26615: }
26616:
26617: /*
26618: * SPEC (2.4) "If the {content type} is element-only or mixed,
26619: * then the sequence of the element information item's
26620: * element information item [children], if any, taken in
26621: * order, is �valid� with respect to the {content type}'s
26622: * particle, as defined in Element Sequence Locally Valid
26623: * (Particle) (�3.9.4)."
26624: */
26625: ret = xmlRegExecPushString2(regexCtxt,
26626: vctxt->inode->localName,
26627: vctxt->inode->nsName,
26628: vctxt->inode);
26629: #ifdef DEBUG_AUTOMATA
26630: if (ret < 0)
26631: xmlGenericError(xmlGenericErrorContext,
26632: "AUTOMATON push ERROR for '%s' on '%s'\n",
26633: vctxt->inode->localName, pielem->localName);
26634: else
26635: xmlGenericError(xmlGenericErrorContext,
26636: "AUTOMATON push OK for '%s' on '%s'\n",
26637: vctxt->inode->localName, pielem->localName);
26638: #endif
26639: if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26640: VERROR_INT("xmlSchemaValidateChildElem",
26641: "calling xmlRegExecPushString2()");
26642: return (-1);
26643: }
26644: if (ret < 0) {
26645: xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26646: &values[0], &terminal);
26647: xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26648: XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26649: "This element is not expected",
26650: nbval, nbneg, values);
26651: ret = vctxt->err;
26652: goto unexpected_elem;
26653: } else
26654: ret = 0;
26655: }
26656: break;
26657: case XML_SCHEMA_CONTENT_SIMPLE:
26658: case XML_SCHEMA_CONTENT_BASIC:
26659: ACTIVATE_PARENT_ELEM
26660: if (WXS_IS_COMPLEX(ptype)) {
26661: /*
26662: * SPEC (cvc-complex-type) (2.2)
26663: * "If the {content type} is a simple type definition, then
26664: * the element information item has no element information
26665: * item [children], ..."
26666: */
26667: ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26668: VERROR(ret, NULL, "Element content is not allowed, "
26669: "because the content type is a simple type definition");
26670: } else {
26671: /*
26672: * SPEC (cvc-type) (3.1.2) "The element information item must
26673: * have no element information item [children]."
26674: */
26675: ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26676: VERROR(ret, NULL, "Element content is not allowed, "
26677: "because the type definition is simple");
26678: }
26679: ACTIVATE_ELEM
26680: ret = vctxt->err;
26681: goto unexpected_elem;
26682: break;
26683:
26684: default:
26685: break;
26686: }
26687: return (ret);
26688: unexpected_elem:
26689: /*
26690: * Pop this element and set the skipDepth to skip
26691: * all further content of the parent element.
26692: */
26693: vctxt->skipDepth = vctxt->depth;
26694: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26695: pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26696: return (ret);
26697: }
26698:
26699: #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26700: #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26701: #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26702:
26703: static int
26704: xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26705: int nodeType, const xmlChar *value, int len,
26706: int mode, int *consumed)
26707: {
26708: /*
26709: * Unfortunately we have to duplicate the text sometimes.
26710: * OPTIMIZE: Maybe we could skip it, if:
26711: * 1. content type is simple
26712: * 2. whitespace is "collapse"
26713: * 3. it consists of whitespace only
26714: *
26715: * Process character content.
26716: */
26717: if (consumed != NULL)
26718: *consumed = 0;
26719: if (INODE_NILLED(vctxt->inode)) {
26720: /*
26721: * SPEC cvc-elt (3.3.4 - 3.2.1)
26722: * "The element information item must have no character or
26723: * element information item [children]."
26724: */
26725: VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26726: "Neither character nor element content is allowed "
26727: "because the element is 'nilled'");
26728: return (vctxt->err);
26729: }
26730: /*
26731: * SPEC (2.1) "If the {content type} is empty, then the
26732: * element information item has no character or element
26733: * information item [children]."
26734: */
26735: if (vctxt->inode->typeDef->contentType ==
26736: XML_SCHEMA_CONTENT_EMPTY) {
26737: VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26738: "Character content is not allowed, "
26739: "because the content type is empty");
26740: return (vctxt->err);
26741: }
26742:
26743: if (vctxt->inode->typeDef->contentType ==
26744: XML_SCHEMA_CONTENT_ELEMENTS) {
26745: if ((nodeType != XML_TEXT_NODE) ||
26746: (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26747: /*
26748: * SPEC cvc-complex-type (2.3)
26749: * "If the {content type} is element-only, then the
26750: * element information item has no character information
26751: * item [children] other than those whose [character
26752: * code] is defined as a white space in [XML 1.0 (Second
26753: * Edition)]."
26754: */
26755: VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26756: "Character content other than whitespace is not allowed "
26757: "because the content type is 'element-only'");
26758: return (vctxt->err);
26759: }
26760: return (0);
26761: }
26762:
26763: if ((value == NULL) || (value[0] == 0))
26764: return (0);
26765: /*
26766: * Save the value.
26767: * NOTE that even if the content type is *mixed*, we need the
26768: * *initial value* for default/fixed value constraints.
26769: */
26770: if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26771: ((vctxt->inode->decl == NULL) ||
26772: (vctxt->inode->decl->value == NULL)))
26773: return (0);
26774:
26775: if (vctxt->inode->value == NULL) {
26776: /*
26777: * Set the value.
26778: */
26779: switch (mode) {
26780: case XML_SCHEMA_PUSH_TEXT_PERSIST:
26781: /*
26782: * When working on a tree.
26783: */
26784: vctxt->inode->value = value;
26785: break;
26786: case XML_SCHEMA_PUSH_TEXT_CREATED:
26787: /*
26788: * When working with the reader.
26789: * The value will be freed by the element info.
26790: */
26791: vctxt->inode->value = value;
26792: if (consumed != NULL)
26793: *consumed = 1;
26794: vctxt->inode->flags |=
26795: XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26796: break;
26797: case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26798: /*
26799: * When working with SAX.
26800: * The value will be freed by the element info.
26801: */
26802: if (len != -1)
26803: vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26804: else
26805: vctxt->inode->value = BAD_CAST xmlStrdup(value);
26806: vctxt->inode->flags |=
26807: XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26808: break;
26809: default:
26810: break;
26811: }
26812: } else {
26813: if (len < 0)
26814: len = xmlStrlen(value);
26815: /*
26816: * Concat the value.
26817: */
26818: if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26819: vctxt->inode->value = BAD_CAST xmlStrncat(
26820: (xmlChar *) vctxt->inode->value, value, len);
26821: } else {
26822: vctxt->inode->value =
26823: BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26824: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26825: }
26826: }
26827:
26828: return (0);
26829: }
26830:
26831: static int
26832: xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26833: {
26834: int ret = 0;
26835:
26836: if ((vctxt->skipDepth != -1) &&
26837: (vctxt->depth >= vctxt->skipDepth)) {
26838: VERROR_INT("xmlSchemaValidateElem",
26839: "in skip-state");
26840: goto internal_error;
26841: }
26842: if (vctxt->xsiAssemble) {
26843: /*
26844: * We will stop validation if there was an error during
26845: * dynamic schema construction.
26846: * Note that we simply set @skipDepth to 0, this could
26847: * mean that a streaming document via SAX would be
26848: * still read to the end but it won't be validated any more.
26849: * TODO: If we are sure how to stop the validation at once
26850: * for all input scenarios, then this should be changed to
26851: * instantly stop the validation.
26852: */
26853: ret = xmlSchemaAssembleByXSI(vctxt);
26854: if (ret != 0) {
26855: if (ret == -1)
26856: goto internal_error;
26857: vctxt->skipDepth = 0;
26858: return(ret);
26859: }
26860: /*
26861: * Augment the IDC definitions for the main schema and all imported ones
26862: * NOTE: main schema is the first in the imported list
26863: */
26864: xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
26865: }
26866: if (vctxt->depth > 0) {
26867: /*
26868: * Validate this element against the content model
26869: * of the parent.
26870: */
26871: ret = xmlSchemaValidateChildElem(vctxt);
26872: if (ret != 0) {
26873: if (ret < 0) {
26874: VERROR_INT("xmlSchemaValidateElem",
26875: "calling xmlSchemaStreamValidateChildElement()");
26876: goto internal_error;
26877: }
26878: goto exit;
26879: }
26880: if (vctxt->depth == vctxt->skipDepth)
26881: goto exit;
26882: if ((vctxt->inode->decl == NULL) &&
26883: (vctxt->inode->typeDef == NULL)) {
26884: VERROR_INT("xmlSchemaValidateElem",
26885: "the child element was valid but neither the "
26886: "declaration nor the type was set");
26887: goto internal_error;
26888: }
26889: } else {
26890: /*
26891: * Get the declaration of the validation root.
26892: */
26893: vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26894: vctxt->inode->localName,
26895: vctxt->inode->nsName);
26896: if (vctxt->inode->decl == NULL) {
26897: ret = XML_SCHEMAV_CVC_ELT_1;
26898: VERROR(ret, NULL,
26899: "No matching global declaration available "
26900: "for the validation root");
26901: goto exit;
26902: }
26903: }
26904:
26905: if (vctxt->inode->decl == NULL)
26906: goto type_validation;
26907:
26908: if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26909: int skip;
26910: /*
26911: * Wildcards.
26912: */
26913: ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26914: if (ret != 0) {
26915: if (ret < 0) {
26916: VERROR_INT("xmlSchemaValidateElem",
26917: "calling xmlSchemaValidateElemWildcard()");
26918: goto internal_error;
26919: }
26920: goto exit;
26921: }
26922: if (skip) {
26923: vctxt->skipDepth = vctxt->depth;
26924: goto exit;
26925: }
26926: /*
26927: * The declaration might be set by the wildcard validation,
26928: * when the processContents is "lax" or "strict".
26929: */
26930: if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26931: /*
26932: * Clear the "decl" field to not confuse further processing.
26933: */
26934: vctxt->inode->decl = NULL;
26935: goto type_validation;
26936: }
26937: }
26938: /*
26939: * Validate against the declaration.
26940: */
26941: ret = xmlSchemaValidateElemDecl(vctxt);
26942: if (ret != 0) {
26943: if (ret < 0) {
26944: VERROR_INT("xmlSchemaValidateElem",
26945: "calling xmlSchemaValidateElemDecl()");
26946: goto internal_error;
26947: }
26948: goto exit;
26949: }
26950: /*
26951: * Validate against the type definition.
26952: */
26953: type_validation:
26954:
26955: if (vctxt->inode->typeDef == NULL) {
26956: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26957: ret = XML_SCHEMAV_CVC_TYPE_1;
1.1.1.3 ! misho 26958: VERROR(ret, NULL,
! 26959: "The type definition is absent");
1.1 misho 26960: goto exit;
26961: }
26962: if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26963: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26964: ret = XML_SCHEMAV_CVC_TYPE_2;
1.1.1.3 ! misho 26965: VERROR(ret, NULL,
! 26966: "The type definition is abstract");
1.1 misho 26967: goto exit;
26968: }
26969: /*
26970: * Evaluate IDCs. Do it here, since new IDC matchers are registered
26971: * during validation against the declaration. This must be done
26972: * _before_ attribute validation.
26973: */
26974: if (vctxt->xpathStates != NULL) {
26975: ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26976: vctxt->inode->appliedXPath = 1;
26977: if (ret == -1) {
26978: VERROR_INT("xmlSchemaValidateElem",
26979: "calling xmlSchemaXPathEvaluate()");
26980: goto internal_error;
26981: }
26982: }
26983: /*
26984: * Validate attributes.
26985: */
26986: if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26987: if ((vctxt->nbAttrInfos != 0) ||
26988: (vctxt->inode->typeDef->attrUses != NULL)) {
26989:
26990: ret = xmlSchemaVAttributesComplex(vctxt);
26991: }
26992: } else if (vctxt->nbAttrInfos != 0) {
26993:
26994: ret = xmlSchemaVAttributesSimple(vctxt);
26995: }
26996: /*
26997: * Clear registered attributes.
26998: */
26999: if (vctxt->nbAttrInfos != 0)
27000: xmlSchemaClearAttrInfos(vctxt);
27001: if (ret == -1) {
27002: VERROR_INT("xmlSchemaValidateElem",
27003: "calling attributes validation");
27004: goto internal_error;
27005: }
27006: /*
27007: * Don't return an error if attributes are invalid on purpose.
27008: */
27009: ret = 0;
27010:
27011: exit:
27012: if (ret != 0)
27013: vctxt->skipDepth = vctxt->depth;
27014: return (ret);
27015: internal_error:
27016: return (-1);
27017: }
27018:
27019: #ifdef XML_SCHEMA_READER_ENABLED
27020: static int
27021: xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27022: {
27023: const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27024: int depth, nodeType, ret = 0, consumed;
27025: xmlSchemaNodeInfoPtr ielem;
27026:
27027: vctxt->depth = -1;
27028: ret = xmlTextReaderRead(vctxt->reader);
27029: /*
27030: * Move to the document element.
27031: */
27032: while (ret == 1) {
27033: nodeType = xmlTextReaderNodeType(vctxt->reader);
27034: if (nodeType == XML_ELEMENT_NODE)
27035: goto root_found;
27036: ret = xmlTextReaderRead(vctxt->reader);
27037: }
27038: goto exit;
27039:
27040: root_found:
27041:
27042: do {
27043: depth = xmlTextReaderDepth(vctxt->reader);
27044: nodeType = xmlTextReaderNodeType(vctxt->reader);
27045:
27046: if (nodeType == XML_ELEMENT_NODE) {
27047:
27048: vctxt->depth++;
27049: if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27050: VERROR_INT("xmlSchemaVReaderWalk",
27051: "calling xmlSchemaValidatorPushElem()");
27052: goto internal_error;
27053: }
27054: ielem = vctxt->inode;
27055: ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27056: ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27057: ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27058: /*
27059: * Is the element empty?
27060: */
27061: ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27062: if (ret == -1) {
27063: VERROR_INT("xmlSchemaVReaderWalk",
27064: "calling xmlTextReaderIsEmptyElement()");
27065: goto internal_error;
27066: }
27067: if (ret) {
27068: ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27069: }
27070: /*
27071: * Register attributes.
27072: */
27073: vctxt->nbAttrInfos = 0;
27074: ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27075: if (ret == -1) {
27076: VERROR_INT("xmlSchemaVReaderWalk",
27077: "calling xmlTextReaderMoveToFirstAttribute()");
27078: goto internal_error;
27079: }
27080: if (ret == 1) {
27081: do {
27082: /*
27083: * VAL TODO: How do we know that the reader works on a
27084: * node tree, to be able to pass a node here?
27085: */
27086: if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27087: (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27088: xmlTextReaderNamespaceUri(vctxt->reader), 1,
27089: xmlTextReaderValue(vctxt->reader), 1) == -1) {
27090:
27091: VERROR_INT("xmlSchemaVReaderWalk",
27092: "calling xmlSchemaValidatorPushAttribute()");
27093: goto internal_error;
27094: }
27095: ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27096: if (ret == -1) {
27097: VERROR_INT("xmlSchemaVReaderWalk",
27098: "calling xmlTextReaderMoveToFirstAttribute()");
27099: goto internal_error;
27100: }
27101: } while (ret == 1);
27102: /*
27103: * Back to element position.
27104: */
27105: ret = xmlTextReaderMoveToElement(vctxt->reader);
27106: if (ret == -1) {
27107: VERROR_INT("xmlSchemaVReaderWalk",
27108: "calling xmlTextReaderMoveToElement()");
27109: goto internal_error;
27110: }
27111: }
27112: /*
27113: * Validate the element.
27114: */
27115: ret= xmlSchemaValidateElem(vctxt);
27116: if (ret != 0) {
27117: if (ret == -1) {
27118: VERROR_INT("xmlSchemaVReaderWalk",
27119: "calling xmlSchemaValidateElem()");
27120: goto internal_error;
27121: }
27122: goto exit;
27123: }
27124: if (vctxt->depth == vctxt->skipDepth) {
27125: int curDepth;
27126: /*
27127: * Skip all content.
27128: */
27129: if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27130: ret = xmlTextReaderRead(vctxt->reader);
27131: curDepth = xmlTextReaderDepth(vctxt->reader);
27132: while ((ret == 1) && (curDepth != depth)) {
27133: ret = xmlTextReaderRead(vctxt->reader);
27134: curDepth = xmlTextReaderDepth(vctxt->reader);
27135: }
27136: if (ret < 0) {
27137: /*
27138: * VAL TODO: A reader error occured; what to do here?
27139: */
27140: ret = 1;
27141: goto exit;
27142: }
27143: }
27144: goto leave_elem;
27145: }
27146: /*
27147: * READER VAL TODO: Is an END_ELEM really never called
27148: * if the elem is empty?
27149: */
27150: if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27151: goto leave_elem;
27152: } else if (nodeType == END_ELEM) {
27153: /*
27154: * Process END of element.
27155: */
27156: leave_elem:
27157: ret = xmlSchemaValidatorPopElem(vctxt);
27158: if (ret != 0) {
27159: if (ret < 0) {
27160: VERROR_INT("xmlSchemaVReaderWalk",
27161: "calling xmlSchemaValidatorPopElem()");
27162: goto internal_error;
27163: }
27164: goto exit;
27165: }
27166: if (vctxt->depth >= 0)
27167: ielem = vctxt->inode;
27168: else
27169: ielem = NULL;
27170: } else if ((nodeType == XML_TEXT_NODE) ||
27171: (nodeType == XML_CDATA_SECTION_NODE) ||
27172: (nodeType == WHTSP) ||
27173: (nodeType == SIGN_WHTSP)) {
27174: /*
27175: * Process character content.
27176: */
27177: xmlChar *value;
27178:
27179: if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27180: nodeType = XML_TEXT_NODE;
27181:
27182: value = xmlTextReaderValue(vctxt->reader);
27183: ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27184: -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27185: if (! consumed)
27186: xmlFree(value);
27187: if (ret == -1) {
27188: VERROR_INT("xmlSchemaVReaderWalk",
27189: "calling xmlSchemaVPushText()");
27190: goto internal_error;
27191: }
27192: } else if ((nodeType == XML_ENTITY_NODE) ||
27193: (nodeType == XML_ENTITY_REF_NODE)) {
27194: /*
27195: * VAL TODO: What to do with entities?
27196: */
27197: TODO
27198: }
27199: /*
27200: * Read next node.
27201: */
27202: ret = xmlTextReaderRead(vctxt->reader);
27203: } while (ret == 1);
27204:
27205: exit:
27206: return (ret);
27207: internal_error:
27208: return (-1);
27209: }
27210: #endif
27211:
27212: /************************************************************************
1.1.1.3 ! misho 27213: * *
! 27214: * SAX validation handlers *
! 27215: * *
1.1 misho 27216: ************************************************************************/
27217:
27218: /*
27219: * Process text content.
27220: */
27221: static void
27222: xmlSchemaSAXHandleText(void *ctx,
27223: const xmlChar * ch,
27224: int len)
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: if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27233: vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27234: if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27235: XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27236: VERROR_INT("xmlSchemaSAXHandleCDataSection",
27237: "calling xmlSchemaVPushText()");
27238: vctxt->err = -1;
27239: xmlStopParser(vctxt->parserCtxt);
27240: }
27241: }
27242:
27243: /*
27244: * Process CDATA content.
27245: */
27246: static void
27247: xmlSchemaSAXHandleCDataSection(void *ctx,
27248: const xmlChar * ch,
27249: int len)
27250: {
27251: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27252:
27253: if (vctxt->depth < 0)
27254: return;
27255: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27256: return;
27257: if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27258: vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27259: if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27260: XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27261: VERROR_INT("xmlSchemaSAXHandleCDataSection",
27262: "calling xmlSchemaVPushText()");
27263: vctxt->err = -1;
27264: xmlStopParser(vctxt->parserCtxt);
27265: }
27266: }
27267:
27268: static void
27269: xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27270: const xmlChar * name ATTRIBUTE_UNUSED)
27271: {
27272: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27273:
27274: if (vctxt->depth < 0)
27275: return;
27276: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27277: return;
27278: /* SAX VAL TODO: What to do here? */
27279: TODO
27280: }
27281:
27282: static void
27283: xmlSchemaSAXHandleStartElementNs(void *ctx,
27284: const xmlChar * localname,
27285: const xmlChar * prefix ATTRIBUTE_UNUSED,
27286: const xmlChar * URI,
27287: int nb_namespaces,
27288: const xmlChar ** namespaces,
27289: int nb_attributes,
27290: int nb_defaulted ATTRIBUTE_UNUSED,
27291: const xmlChar ** attributes)
27292: {
27293: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27294: int ret;
27295: xmlSchemaNodeInfoPtr ielem;
27296: int i, j;
27297:
27298: /*
27299: * SAX VAL TODO: What to do with nb_defaulted?
27300: */
27301: /*
27302: * Skip elements if inside a "skip" wildcard or invalid.
27303: */
27304: vctxt->depth++;
27305: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27306: return;
27307: /*
27308: * Push the element.
27309: */
27310: if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27311: VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27312: "calling xmlSchemaValidatorPushElem()");
27313: goto internal_error;
27314: }
27315: ielem = vctxt->inode;
27316: /*
27317: * TODO: Is this OK?
27318: */
27319: ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27320: ielem->localName = localname;
27321: ielem->nsName = URI;
27322: ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27323: /*
27324: * Register namespaces on the elem info.
27325: */
27326: if (nb_namespaces != 0) {
27327: /*
27328: * Although the parser builds its own namespace list,
27329: * we have no access to it, so we'll use an own one.
27330: */
27331: for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27332: /*
27333: * Store prefix and namespace name.
27334: */
27335: if (ielem->nsBindings == NULL) {
27336: ielem->nsBindings =
27337: (const xmlChar **) xmlMalloc(10 *
27338: sizeof(const xmlChar *));
27339: if (ielem->nsBindings == NULL) {
27340: xmlSchemaVErrMemory(vctxt,
27341: "allocating namespace bindings for SAX validation",
27342: NULL);
27343: goto internal_error;
27344: }
27345: ielem->nbNsBindings = 0;
27346: ielem->sizeNsBindings = 5;
27347: } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27348: ielem->sizeNsBindings *= 2;
27349: ielem->nsBindings =
27350: (const xmlChar **) xmlRealloc(
27351: (void *) ielem->nsBindings,
27352: ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27353: if (ielem->nsBindings == NULL) {
27354: xmlSchemaVErrMemory(vctxt,
27355: "re-allocating namespace bindings for SAX validation",
27356: NULL);
27357: goto internal_error;
27358: }
27359: }
27360:
27361: ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27362: if (namespaces[j+1][0] == 0) {
27363: /*
27364: * Handle xmlns="".
27365: */
27366: ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27367: } else
27368: ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27369: namespaces[j+1];
27370: ielem->nbNsBindings++;
27371: }
27372: }
27373: /*
27374: * Register attributes.
27375: * SAX VAL TODO: We are not adding namespace declaration
27376: * attributes yet.
27377: */
27378: if (nb_attributes != 0) {
27379: xmlChar *value;
27380:
27381: for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27382: /*
27383: * Duplicate the value.
27384: */
27385: value = xmlStrndup(attributes[j+3],
27386: attributes[j+4] - attributes[j+3]);
27387: /*
27388: * TODO: Set the node line.
27389: */
27390: ret = xmlSchemaValidatorPushAttribute(vctxt,
27391: NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27392: value, 1);
27393: if (ret == -1) {
27394: VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27395: "calling xmlSchemaValidatorPushAttribute()");
27396: goto internal_error;
27397: }
27398: }
27399: }
27400: /*
27401: * Validate the element.
27402: */
27403: ret = xmlSchemaValidateElem(vctxt);
27404: if (ret != 0) {
27405: if (ret == -1) {
27406: VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27407: "calling xmlSchemaValidateElem()");
27408: goto internal_error;
27409: }
27410: goto exit;
27411: }
27412:
27413: exit:
27414: return;
27415: internal_error:
27416: vctxt->err = -1;
27417: xmlStopParser(vctxt->parserCtxt);
27418: return;
27419: }
27420:
27421: static void
27422: xmlSchemaSAXHandleEndElementNs(void *ctx,
27423: const xmlChar * localname ATTRIBUTE_UNUSED,
27424: const xmlChar * prefix ATTRIBUTE_UNUSED,
27425: const xmlChar * URI ATTRIBUTE_UNUSED)
27426: {
27427: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27428: int res;
27429:
27430: /*
27431: * Skip elements if inside a "skip" wildcard or if invalid.
27432: */
27433: if (vctxt->skipDepth != -1) {
27434: if (vctxt->depth > vctxt->skipDepth) {
27435: vctxt->depth--;
27436: return;
27437: } else
27438: vctxt->skipDepth = -1;
27439: }
27440: /*
27441: * SAX VAL TODO: Just a temporary check.
27442: */
27443: if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27444: (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27445: VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27446: "elem pop mismatch");
27447: }
27448: res = xmlSchemaValidatorPopElem(vctxt);
27449: if (res != 0) {
27450: if (res < 0) {
27451: VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27452: "calling xmlSchemaValidatorPopElem()");
27453: goto internal_error;
27454: }
27455: goto exit;
27456: }
27457: exit:
27458: return;
27459: internal_error:
27460: vctxt->err = -1;
27461: xmlStopParser(vctxt->parserCtxt);
27462: return;
27463: }
27464:
27465: /************************************************************************
1.1.1.3 ! misho 27466: * *
! 27467: * Validation interfaces *
! 27468: * *
1.1 misho 27469: ************************************************************************/
27470:
27471: /**
27472: * xmlSchemaNewValidCtxt:
27473: * @schema: a precompiled XML Schemas
27474: *
27475: * Create an XML Schemas validation context based on the given schema.
27476: *
27477: * Returns the validation context or NULL in case of error
27478: */
27479: xmlSchemaValidCtxtPtr
27480: xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27481: {
27482: xmlSchemaValidCtxtPtr ret;
27483:
27484: ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27485: if (ret == NULL) {
27486: xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27487: return (NULL);
27488: }
27489: memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27490: ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27491: ret->dict = xmlDictCreate();
27492: ret->nodeQNames = xmlSchemaItemListCreate();
27493: ret->schema = schema;
27494: return (ret);
27495: }
27496:
27497: /**
1.1.1.3 ! misho 27498: * xmlSchemaValidateSetFilename:
! 27499: * @vctxt: the schema validation context
! 27500: * @filename: the file name
! 27501: *
! 27502: * Workaround to provide file error reporting information when this is
! 27503: * not provided by current APIs
! 27504: */
! 27505: void
! 27506: xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
! 27507: if (vctxt == NULL)
! 27508: return;
! 27509: if (vctxt->filename != NULL)
! 27510: xmlFree(vctxt->filename);
! 27511: if (filename != NULL)
! 27512: vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
! 27513: else
! 27514: vctxt->filename = NULL;
! 27515: }
! 27516:
! 27517: /**
1.1 misho 27518: * xmlSchemaClearValidCtxt:
1.1.1.3 ! misho 27519: * @vctxt: the schema validation context
1.1 misho 27520: *
27521: * Free the resources associated to the schema validation context;
27522: * leaves some fields alive intended for reuse of the context.
27523: */
27524: static void
27525: xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27526: {
27527: if (vctxt == NULL)
27528: return;
27529:
27530: /*
27531: * TODO: Should we clear the flags?
27532: * Might be problematic if one reuses the context
27533: * and assumes that the options remain the same.
27534: */
27535: vctxt->flags = 0;
27536: vctxt->validationRoot = NULL;
27537: vctxt->doc = NULL;
27538: #ifdef LIBXML_READER_ENABLED
27539: vctxt->reader = NULL;
27540: #endif
27541: vctxt->hasKeyrefs = 0;
27542:
27543: if (vctxt->value != NULL) {
27544: xmlSchemaFreeValue(vctxt->value);
27545: vctxt->value = NULL;
27546: }
27547: /*
27548: * Augmented IDC information.
27549: */
27550: if (vctxt->aidcs != NULL) {
27551: xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27552: do {
27553: next = cur->next;
27554: xmlFree(cur);
27555: cur = next;
27556: } while (cur != NULL);
27557: vctxt->aidcs = NULL;
27558: }
27559: if (vctxt->idcMatcherCache != NULL) {
27560: xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27561:
27562: while (matcher) {
27563: tmp = matcher;
27564: matcher = matcher->nextCached;
27565: xmlSchemaIDCFreeMatcherList(tmp);
27566: }
27567: vctxt->idcMatcherCache = NULL;
27568: }
27569:
27570:
27571: if (vctxt->idcNodes != NULL) {
27572: int i;
27573: xmlSchemaPSVIIDCNodePtr item;
27574:
27575: for (i = 0; i < vctxt->nbIdcNodes; i++) {
27576: item = vctxt->idcNodes[i];
27577: xmlFree(item->keys);
27578: xmlFree(item);
27579: }
27580: xmlFree(vctxt->idcNodes);
27581: vctxt->idcNodes = NULL;
27582: vctxt->nbIdcNodes = 0;
27583: vctxt->sizeIdcNodes = 0;
27584: }
27585: /*
27586: * Note that we won't delete the XPath state pool here.
27587: */
27588: if (vctxt->xpathStates != NULL) {
27589: xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27590: vctxt->xpathStates = NULL;
27591: }
27592: /*
27593: * Attribute info.
27594: */
27595: if (vctxt->nbAttrInfos != 0) {
27596: xmlSchemaClearAttrInfos(vctxt);
27597: }
27598: /*
27599: * Element info.
27600: */
27601: if (vctxt->elemInfos != NULL) {
27602: int i;
27603: xmlSchemaNodeInfoPtr ei;
27604:
27605: for (i = 0; i < vctxt->sizeElemInfos; i++) {
27606: ei = vctxt->elemInfos[i];
27607: if (ei == NULL)
27608: break;
27609: xmlSchemaClearElemInfo(vctxt, ei);
27610: }
27611: }
27612: xmlSchemaItemListClear(vctxt->nodeQNames);
27613: /* Recreate the dict. */
27614: xmlDictFree(vctxt->dict);
27615: /*
27616: * TODO: Is is save to recreate it? Do we have a scenario
27617: * where the user provides the dict?
27618: */
27619: vctxt->dict = xmlDictCreate();
1.1.1.3 ! misho 27620:
! 27621: if (vctxt->filename != NULL) {
! 27622: xmlFree(vctxt->filename);
! 27623: vctxt->filename = NULL;
! 27624: }
1.1 misho 27625: }
27626:
27627: /**
27628: * xmlSchemaFreeValidCtxt:
27629: * @ctxt: the schema validation context
27630: *
27631: * Free the resources associated to the schema validation context
27632: */
27633: void
27634: xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27635: {
27636: if (ctxt == NULL)
27637: return;
27638: if (ctxt->value != NULL)
27639: xmlSchemaFreeValue(ctxt->value);
27640: if (ctxt->pctxt != NULL)
27641: xmlSchemaFreeParserCtxt(ctxt->pctxt);
27642: if (ctxt->idcNodes != NULL) {
27643: int i;
27644: xmlSchemaPSVIIDCNodePtr item;
27645:
27646: for (i = 0; i < ctxt->nbIdcNodes; i++) {
27647: item = ctxt->idcNodes[i];
27648: xmlFree(item->keys);
27649: xmlFree(item);
27650: }
27651: xmlFree(ctxt->idcNodes);
27652: }
27653: if (ctxt->idcKeys != NULL) {
27654: int i;
27655: for (i = 0; i < ctxt->nbIdcKeys; i++)
27656: xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27657: xmlFree(ctxt->idcKeys);
27658: }
27659:
27660: if (ctxt->xpathStates != NULL) {
27661: xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27662: ctxt->xpathStates = NULL;
27663: }
27664: if (ctxt->xpathStatePool != NULL) {
27665: xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27666: ctxt->xpathStatePool = NULL;
27667: }
27668:
27669: /*
27670: * Augmented IDC information.
27671: */
27672: if (ctxt->aidcs != NULL) {
27673: xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27674: do {
27675: next = cur->next;
27676: xmlFree(cur);
27677: cur = next;
27678: } while (cur != NULL);
27679: }
27680: if (ctxt->attrInfos != NULL) {
27681: int i;
27682: xmlSchemaAttrInfoPtr attr;
27683:
27684: /* Just a paranoid call to the cleanup. */
27685: if (ctxt->nbAttrInfos != 0)
27686: xmlSchemaClearAttrInfos(ctxt);
27687: for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27688: attr = ctxt->attrInfos[i];
27689: xmlFree(attr);
27690: }
27691: xmlFree(ctxt->attrInfos);
27692: }
27693: if (ctxt->elemInfos != NULL) {
27694: int i;
27695: xmlSchemaNodeInfoPtr ei;
27696:
27697: for (i = 0; i < ctxt->sizeElemInfos; i++) {
27698: ei = ctxt->elemInfos[i];
27699: if (ei == NULL)
27700: break;
27701: xmlSchemaClearElemInfo(ctxt, ei);
27702: xmlFree(ei);
27703: }
27704: xmlFree(ctxt->elemInfos);
27705: }
27706: if (ctxt->nodeQNames != NULL)
27707: xmlSchemaItemListFree(ctxt->nodeQNames);
27708: if (ctxt->dict != NULL)
27709: xmlDictFree(ctxt->dict);
1.1.1.3 ! misho 27710: if (ctxt->filename != NULL)
! 27711: xmlFree(ctxt->filename);
1.1 misho 27712: xmlFree(ctxt);
27713: }
27714:
27715: /**
27716: * xmlSchemaIsValid:
27717: * @ctxt: the schema validation context
27718: *
27719: * Check if any error was detected during validation.
27720: *
27721: * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27722: * of internal error.
27723: */
27724: int
27725: xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27726: {
27727: if (ctxt == NULL)
27728: return(-1);
27729: return(ctxt->err == 0);
27730: }
27731:
27732: /**
27733: * xmlSchemaSetValidErrors:
27734: * @ctxt: a schema validation context
27735: * @err: the error function
27736: * @warn: the warning function
27737: * @ctx: the functions context
27738: *
27739: * Set the error and warning callback informations
27740: */
27741: void
27742: xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27743: xmlSchemaValidityErrorFunc err,
27744: xmlSchemaValidityWarningFunc warn, void *ctx)
27745: {
27746: if (ctxt == NULL)
27747: return;
27748: ctxt->error = err;
27749: ctxt->warning = warn;
27750: ctxt->errCtxt = ctx;
27751: if (ctxt->pctxt != NULL)
27752: xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27753: }
27754:
27755: /**
27756: * xmlSchemaSetValidStructuredErrors:
27757: * @ctxt: a schema validation context
27758: * @serror: the structured error function
27759: * @ctx: the functions context
27760: *
27761: * Set the structured error callback
27762: */
27763: void
27764: xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27765: xmlStructuredErrorFunc serror, void *ctx)
27766: {
27767: if (ctxt == NULL)
27768: return;
27769: ctxt->serror = serror;
27770: ctxt->error = NULL;
27771: ctxt->warning = NULL;
27772: ctxt->errCtxt = ctx;
27773: if (ctxt->pctxt != NULL)
27774: xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27775: }
27776:
27777: /**
27778: * xmlSchemaGetValidErrors:
27779: * @ctxt: a XML-Schema validation context
27780: * @err: the error function result
27781: * @warn: the warning function result
27782: * @ctx: the functions context result
27783: *
27784: * Get the error and warning callback informations
27785: *
27786: * Returns -1 in case of error and 0 otherwise
27787: */
27788: int
27789: xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27790: xmlSchemaValidityErrorFunc * err,
27791: xmlSchemaValidityWarningFunc * warn, void **ctx)
27792: {
27793: if (ctxt == NULL)
27794: return (-1);
27795: if (err != NULL)
27796: *err = ctxt->error;
27797: if (warn != NULL)
27798: *warn = ctxt->warning;
27799: if (ctx != NULL)
27800: *ctx = ctxt->errCtxt;
27801: return (0);
27802: }
27803:
27804:
27805: /**
27806: * xmlSchemaSetValidOptions:
27807: * @ctxt: a schema validation context
27808: * @options: a combination of xmlSchemaValidOption
27809: *
27810: * Sets the options to be used during the validation.
27811: *
27812: * Returns 0 in case of success, -1 in case of an
27813: * API error.
27814: */
27815: int
27816: xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27817: int options)
27818:
27819: {
27820: int i;
27821:
27822: if (ctxt == NULL)
27823: return (-1);
27824: /*
27825: * WARNING: Change the start value if adding to the
27826: * xmlSchemaValidOption.
27827: * TODO: Is there an other, more easy to maintain,
27828: * way?
27829: */
27830: for (i = 1; i < (int) sizeof(int) * 8; i++) {
27831: if (options & 1<<i)
27832: return (-1);
27833: }
27834: ctxt->options = options;
27835: return (0);
27836: }
27837:
27838: /**
27839: * xmlSchemaValidCtxtGetOptions:
27840: * @ctxt: a schema validation context
27841: *
27842: * Get the validation context options.
27843: *
27844: * Returns the option combination or -1 on error.
27845: */
27846: int
27847: xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27848:
27849: {
27850: if (ctxt == NULL)
27851: return (-1);
27852: else
27853: return (ctxt->options);
27854: }
27855:
27856: static int
27857: xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27858: {
27859: xmlAttrPtr attr;
27860: int ret = 0;
27861: xmlSchemaNodeInfoPtr ielem = NULL;
27862: xmlNodePtr node, valRoot;
27863: const xmlChar *nsName;
27864:
27865: /* DOC VAL TODO: Move this to the start function. */
1.1.1.3 ! misho 27866: if (vctxt->validationRoot != NULL)
! 27867: valRoot = vctxt->validationRoot;
! 27868: else
! 27869: valRoot = xmlDocGetRootElement(vctxt->doc);
1.1 misho 27870: if (valRoot == NULL) {
27871: /* VAL TODO: Error code? */
27872: VERROR(1, NULL, "The document has no document element");
27873: return (1);
27874: }
27875: vctxt->depth = -1;
27876: vctxt->validationRoot = valRoot;
27877: node = valRoot;
27878: while (node != NULL) {
27879: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27880: goto next_sibling;
27881: if (node->type == XML_ELEMENT_NODE) {
27882:
27883: /*
27884: * Init the node-info.
27885: */
27886: vctxt->depth++;
27887: if (xmlSchemaValidatorPushElem(vctxt) == -1)
27888: goto internal_error;
27889: ielem = vctxt->inode;
27890: ielem->node = node;
27891: ielem->nodeLine = node->line;
27892: ielem->localName = node->name;
27893: if (node->ns != NULL)
27894: ielem->nsName = node->ns->href;
27895: ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27896: /*
27897: * Register attributes.
27898: * DOC VAL TODO: We do not register namespace declaration
27899: * attributes yet.
27900: */
27901: vctxt->nbAttrInfos = 0;
27902: if (node->properties != NULL) {
27903: attr = node->properties;
27904: do {
27905: if (attr->ns != NULL)
27906: nsName = attr->ns->href;
27907: else
27908: nsName = NULL;
27909: ret = xmlSchemaValidatorPushAttribute(vctxt,
27910: (xmlNodePtr) attr,
27911: /*
27912: * Note that we give it the line number of the
27913: * parent element.
27914: */
27915: ielem->nodeLine,
27916: attr->name, nsName, 0,
27917: xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27918: if (ret == -1) {
27919: VERROR_INT("xmlSchemaDocWalk",
27920: "calling xmlSchemaValidatorPushAttribute()");
27921: goto internal_error;
27922: }
27923: attr = attr->next;
27924: } while (attr);
27925: }
27926: /*
27927: * Validate the element.
27928: */
27929: ret = xmlSchemaValidateElem(vctxt);
27930: if (ret != 0) {
27931: if (ret == -1) {
27932: VERROR_INT("xmlSchemaDocWalk",
27933: "calling xmlSchemaValidateElem()");
27934: goto internal_error;
27935: }
27936: /*
27937: * Don't stop validation; just skip the content
27938: * of this element.
27939: */
27940: goto leave_node;
27941: }
27942: if ((vctxt->skipDepth != -1) &&
27943: (vctxt->depth >= vctxt->skipDepth))
27944: goto leave_node;
27945: } else if ((node->type == XML_TEXT_NODE) ||
27946: (node->type == XML_CDATA_SECTION_NODE)) {
27947: /*
27948: * Process character content.
27949: */
27950: if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27951: ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27952: ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27953: -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27954: if (ret < 0) {
27955: VERROR_INT("xmlSchemaVDocWalk",
27956: "calling xmlSchemaVPushText()");
27957: goto internal_error;
27958: }
27959: /*
27960: * DOC VAL TODO: Should we skip further validation of the
27961: * element content here?
27962: */
27963: } else if ((node->type == XML_ENTITY_NODE) ||
27964: (node->type == XML_ENTITY_REF_NODE)) {
27965: /*
27966: * DOC VAL TODO: What to do with entities?
27967: */
27968: VERROR_INT("xmlSchemaVDocWalk",
27969: "there is at least one entity reference in the node-tree "
27970: "currently being validated. Processing of entities with "
27971: "this XML Schema processor is not supported (yet). Please "
27972: "substitute entities before validation.");
27973: goto internal_error;
27974: } else {
27975: goto leave_node;
27976: /*
27977: * DOC VAL TODO: XInclude nodes, etc.
27978: */
27979: }
27980: /*
27981: * Walk the doc.
27982: */
27983: if (node->children != NULL) {
27984: node = node->children;
27985: continue;
27986: }
27987: leave_node:
27988: if (node->type == XML_ELEMENT_NODE) {
27989: /*
27990: * Leaving the scope of an element.
27991: */
27992: if (node != vctxt->inode->node) {
27993: VERROR_INT("xmlSchemaVDocWalk",
27994: "element position mismatch");
27995: goto internal_error;
27996: }
27997: ret = xmlSchemaValidatorPopElem(vctxt);
27998: if (ret != 0) {
27999: if (ret < 0) {
28000: VERROR_INT("xmlSchemaVDocWalk",
28001: "calling xmlSchemaValidatorPopElem()");
28002: goto internal_error;
28003: }
28004: }
28005: if (node == valRoot)
28006: goto exit;
28007: }
28008: next_sibling:
28009: if (node->next != NULL)
28010: node = node->next;
28011: else {
28012: node = node->parent;
28013: goto leave_node;
28014: }
28015: }
28016:
28017: exit:
28018: return (ret);
28019: internal_error:
28020: return (-1);
28021: }
28022:
28023: static int
28024: xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28025: /*
28026: * Some initialization.
28027: */
28028: vctxt->err = 0;
28029: vctxt->nberrors = 0;
28030: vctxt->depth = -1;
28031: vctxt->skipDepth = -1;
28032: vctxt->xsiAssemble = 0;
28033: vctxt->hasKeyrefs = 0;
28034: #ifdef ENABLE_IDC_NODE_TABLES_TEST
28035: vctxt->createIDCNodeTables = 1;
28036: #else
28037: vctxt->createIDCNodeTables = 0;
28038: #endif
28039: /*
28040: * Create a schema + parser if necessary.
28041: */
28042: if (vctxt->schema == NULL) {
28043: xmlSchemaParserCtxtPtr pctxt;
28044:
28045: vctxt->xsiAssemble = 1;
28046: /*
28047: * If not schema was given then we will create a schema
28048: * dynamically using XSI schema locations.
28049: *
28050: * Create the schema parser context.
28051: */
28052: if ((vctxt->pctxt == NULL) &&
28053: (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28054: return (-1);
28055: pctxt = vctxt->pctxt;
28056: pctxt->xsiAssemble = 1;
28057: /*
28058: * Create the schema.
28059: */
28060: vctxt->schema = xmlSchemaNewSchema(pctxt);
28061: if (vctxt->schema == NULL)
28062: return (-1);
28063: /*
28064: * Create the schema construction context.
28065: */
28066: pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28067: if (pctxt->constructor == NULL)
28068: return(-1);
28069: pctxt->constructor->mainSchema = vctxt->schema;
28070: /*
28071: * Take ownership of the constructor to be able to free it.
28072: */
28073: pctxt->ownsConstructor = 1;
28074: }
28075: /*
28076: * Augment the IDC definitions for the main schema and all imported ones
28077: * NOTE: main schema if the first in the imported list
28078: */
28079: xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
28080:
28081: return(0);
28082: }
28083:
28084: static void
28085: xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28086: if (vctxt->xsiAssemble) {
28087: if (vctxt->schema != NULL) {
28088: xmlSchemaFree(vctxt->schema);
28089: vctxt->schema = NULL;
28090: }
28091: }
28092: xmlSchemaClearValidCtxt(vctxt);
28093: }
28094:
28095: static int
28096: xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28097: {
28098: int ret = 0;
28099:
28100: if (xmlSchemaPreRun(vctxt) < 0)
28101: return(-1);
28102:
28103: if (vctxt->doc != NULL) {
28104: /*
28105: * Tree validation.
28106: */
28107: ret = xmlSchemaVDocWalk(vctxt);
28108: #ifdef LIBXML_READER_ENABLED
28109: } else if (vctxt->reader != NULL) {
28110: /*
28111: * XML Reader validation.
28112: */
28113: #ifdef XML_SCHEMA_READER_ENABLED
28114: ret = xmlSchemaVReaderWalk(vctxt);
28115: #endif
28116: #endif
28117: } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28118: /*
28119: * SAX validation.
28120: */
28121: ret = xmlParseDocument(vctxt->parserCtxt);
28122: } else {
28123: VERROR_INT("xmlSchemaVStart",
28124: "no instance to validate");
28125: ret = -1;
28126: }
28127:
28128: xmlSchemaPostRun(vctxt);
28129: if (ret == 0)
28130: ret = vctxt->err;
28131: return (ret);
28132: }
28133:
28134: /**
28135: * xmlSchemaValidateOneElement:
28136: * @ctxt: a schema validation context
28137: * @elem: an element node
28138: *
28139: * Validate a branch of a tree, starting with the given @elem.
28140: *
28141: * Returns 0 if the element and its subtree is valid, a positive error
28142: * code number otherwise and -1 in case of an internal or API error.
28143: */
28144: int
28145: xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28146: {
28147: if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28148: return (-1);
28149:
28150: if (ctxt->schema == NULL)
28151: return (-1);
28152:
28153: ctxt->doc = elem->doc;
28154: ctxt->node = elem;
28155: ctxt->validationRoot = elem;
28156: return(xmlSchemaVStart(ctxt));
28157: }
28158:
28159: /**
28160: * xmlSchemaValidateDoc:
28161: * @ctxt: a schema validation context
28162: * @doc: a parsed document tree
28163: *
28164: * Validate a document tree in memory.
28165: *
28166: * Returns 0 if the document is schemas valid, a positive error code
28167: * number otherwise and -1 in case of internal or API error.
28168: */
28169: int
28170: xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28171: {
28172: if ((ctxt == NULL) || (doc == NULL))
28173: return (-1);
28174:
28175: ctxt->doc = doc;
28176: ctxt->node = xmlDocGetRootElement(doc);
28177: if (ctxt->node == NULL) {
28178: xmlSchemaCustomErr(ACTXT_CAST ctxt,
28179: XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28180: (xmlNodePtr) doc, NULL,
28181: "The document has no document element", NULL, NULL);
28182: return (ctxt->err);
28183: }
28184: ctxt->validationRoot = ctxt->node;
28185: return (xmlSchemaVStart(ctxt));
28186: }
28187:
28188:
28189: /************************************************************************
1.1.1.3 ! misho 28190: * *
! 28191: * Function and data for SAX streaming API *
! 28192: * *
1.1 misho 28193: ************************************************************************/
28194: typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28195: typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28196:
28197: struct _xmlSchemaSplitSAXData {
28198: xmlSAXHandlerPtr user_sax;
28199: void *user_data;
28200: xmlSchemaValidCtxtPtr ctxt;
28201: xmlSAXHandlerPtr schemas_sax;
28202: };
28203:
28204: #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28205:
28206: struct _xmlSchemaSAXPlug {
28207: unsigned int magic;
28208:
28209: /* the original callbacks informations */
28210: xmlSAXHandlerPtr *user_sax_ptr;
28211: xmlSAXHandlerPtr user_sax;
28212: void **user_data_ptr;
28213: void *user_data;
28214:
28215: /* the block plugged back and validation informations */
28216: xmlSAXHandler schemas_sax;
28217: xmlSchemaValidCtxtPtr ctxt;
28218: };
28219:
28220: /* All those functions just bounces to the user provided SAX handlers */
28221: static void
28222: internalSubsetSplit(void *ctx, const xmlChar *name,
28223: const xmlChar *ExternalID, const xmlChar *SystemID)
28224: {
28225: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28226: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28227: (ctxt->user_sax->internalSubset != NULL))
28228: ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28229: SystemID);
28230: }
28231:
28232: static int
28233: isStandaloneSplit(void *ctx)
28234: {
28235: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28236: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28237: (ctxt->user_sax->isStandalone != NULL))
28238: return(ctxt->user_sax->isStandalone(ctxt->user_data));
28239: return(0);
28240: }
28241:
28242: static int
28243: hasInternalSubsetSplit(void *ctx)
28244: {
28245: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28246: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28247: (ctxt->user_sax->hasInternalSubset != NULL))
28248: return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28249: return(0);
28250: }
28251:
28252: static int
28253: hasExternalSubsetSplit(void *ctx)
28254: {
28255: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28256: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28257: (ctxt->user_sax->hasExternalSubset != NULL))
28258: return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28259: return(0);
28260: }
28261:
28262: static void
28263: externalSubsetSplit(void *ctx, const xmlChar *name,
28264: const xmlChar *ExternalID, const xmlChar *SystemID)
28265: {
28266: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28267: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28268: (ctxt->user_sax->externalSubset != NULL))
28269: ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28270: SystemID);
28271: }
28272:
28273: static xmlParserInputPtr
28274: resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28275: {
28276: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28277: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28278: (ctxt->user_sax->resolveEntity != NULL))
28279: return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28280: systemId));
28281: return(NULL);
28282: }
28283:
28284: static xmlEntityPtr
28285: getEntitySplit(void *ctx, const xmlChar *name)
28286: {
28287: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28288: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28289: (ctxt->user_sax->getEntity != NULL))
28290: return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28291: return(NULL);
28292: }
28293:
28294: static xmlEntityPtr
28295: getParameterEntitySplit(void *ctx, const xmlChar *name)
28296: {
28297: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28298: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28299: (ctxt->user_sax->getParameterEntity != NULL))
28300: return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28301: return(NULL);
28302: }
28303:
28304:
28305: static void
28306: entityDeclSplit(void *ctx, const xmlChar *name, int type,
28307: const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28308: {
28309: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28310: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28311: (ctxt->user_sax->entityDecl != NULL))
28312: ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28313: systemId, content);
28314: }
28315:
28316: static void
28317: attributeDeclSplit(void *ctx, const xmlChar * elem,
28318: const xmlChar * name, int type, int def,
28319: const xmlChar * defaultValue, xmlEnumerationPtr tree)
28320: {
28321: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28322: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28323: (ctxt->user_sax->attributeDecl != NULL)) {
28324: ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28325: def, defaultValue, tree);
28326: } else {
28327: xmlFreeEnumeration(tree);
28328: }
28329: }
28330:
28331: static void
28332: elementDeclSplit(void *ctx, const xmlChar *name, int type,
28333: xmlElementContentPtr content)
28334: {
28335: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28336: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28337: (ctxt->user_sax->elementDecl != NULL))
28338: ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28339: }
28340:
28341: static void
28342: notationDeclSplit(void *ctx, const xmlChar *name,
28343: const xmlChar *publicId, const xmlChar *systemId)
28344: {
28345: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28346: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28347: (ctxt->user_sax->notationDecl != NULL))
28348: ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28349: systemId);
28350: }
28351:
28352: static void
28353: unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28354: const xmlChar *publicId, const xmlChar *systemId,
28355: const xmlChar *notationName)
28356: {
28357: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28358: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28359: (ctxt->user_sax->unparsedEntityDecl != NULL))
28360: ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28361: systemId, notationName);
28362: }
28363:
28364: static void
28365: setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28366: {
28367: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28368: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28369: (ctxt->user_sax->setDocumentLocator != NULL))
28370: ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28371: }
28372:
28373: static void
28374: startDocumentSplit(void *ctx)
28375: {
28376: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28377: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28378: (ctxt->user_sax->startDocument != NULL))
28379: ctxt->user_sax->startDocument(ctxt->user_data);
28380: }
28381:
28382: static void
28383: endDocumentSplit(void *ctx)
28384: {
28385: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28386: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28387: (ctxt->user_sax->endDocument != NULL))
28388: ctxt->user_sax->endDocument(ctxt->user_data);
28389: }
28390:
28391: static void
28392: processingInstructionSplit(void *ctx, const xmlChar *target,
28393: const xmlChar *data)
28394: {
28395: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28396: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28397: (ctxt->user_sax->processingInstruction != NULL))
28398: ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28399: }
28400:
28401: static void
28402: commentSplit(void *ctx, const xmlChar *value)
28403: {
28404: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28405: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28406: (ctxt->user_sax->comment != NULL))
28407: ctxt->user_sax->comment(ctxt->user_data, value);
28408: }
28409:
28410: /*
28411: * Varargs error callbacks to the user application, harder ...
28412: */
28413:
28414: static void XMLCDECL
28415: warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28416: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28417: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28418: (ctxt->user_sax->warning != NULL)) {
28419: TODO
28420: }
28421: }
28422: static void XMLCDECL
28423: errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28424: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28425: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28426: (ctxt->user_sax->error != NULL)) {
28427: TODO
28428: }
28429: }
28430: static void XMLCDECL
28431: fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28432: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28433: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28434: (ctxt->user_sax->fatalError != NULL)) {
28435: TODO
28436: }
28437: }
28438:
28439: /*
28440: * Those are function where both the user handler and the schemas handler
28441: * need to be called.
28442: */
28443: static void
28444: charactersSplit(void *ctx, const xmlChar *ch, int len)
28445: {
28446: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28447: if (ctxt == NULL)
28448: return;
28449: if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28450: ctxt->user_sax->characters(ctxt->user_data, ch, len);
28451: if (ctxt->ctxt != NULL)
28452: xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28453: }
28454:
28455: static void
28456: ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28457: {
28458: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28459: if (ctxt == NULL)
28460: return;
28461: if ((ctxt->user_sax != NULL) &&
28462: (ctxt->user_sax->ignorableWhitespace != NULL))
28463: ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28464: if (ctxt->ctxt != NULL)
28465: xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28466: }
28467:
28468: static void
28469: cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28470: {
28471: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28472: if (ctxt == NULL)
28473: return;
28474: if ((ctxt->user_sax != NULL) &&
28475: (ctxt->user_sax->cdataBlock != NULL))
28476: ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28477: if (ctxt->ctxt != NULL)
28478: xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28479: }
28480:
28481: static void
28482: referenceSplit(void *ctx, const xmlChar *name)
28483: {
28484: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28485: if (ctxt == NULL)
28486: return;
28487: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28488: (ctxt->user_sax->reference != NULL))
28489: ctxt->user_sax->reference(ctxt->user_data, name);
28490: if (ctxt->ctxt != NULL)
28491: xmlSchemaSAXHandleReference(ctxt->user_data, name);
28492: }
28493:
28494: static void
28495: startElementNsSplit(void *ctx, const xmlChar * localname,
28496: const xmlChar * prefix, const xmlChar * URI,
28497: int nb_namespaces, const xmlChar ** namespaces,
28498: int nb_attributes, int nb_defaulted,
28499: const xmlChar ** attributes) {
28500: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28501: if (ctxt == NULL)
28502: return;
28503: if ((ctxt->user_sax != NULL) &&
28504: (ctxt->user_sax->startElementNs != NULL))
28505: ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28506: URI, nb_namespaces, namespaces,
28507: nb_attributes, nb_defaulted,
28508: attributes);
28509: if (ctxt->ctxt != NULL)
28510: xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28511: URI, nb_namespaces, namespaces,
28512: nb_attributes, nb_defaulted,
28513: attributes);
28514: }
28515:
28516: static void
28517: endElementNsSplit(void *ctx, const xmlChar * localname,
28518: const xmlChar * prefix, const xmlChar * URI) {
28519: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28520: if (ctxt == NULL)
28521: return;
28522: if ((ctxt->user_sax != NULL) &&
28523: (ctxt->user_sax->endElementNs != NULL))
28524: ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28525: if (ctxt->ctxt != NULL)
28526: xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28527: }
28528:
28529: /**
28530: * xmlSchemaSAXPlug:
28531: * @ctxt: a schema validation context
28532: * @sax: a pointer to the original xmlSAXHandlerPtr
28533: * @user_data: a pointer to the original SAX user data pointer
28534: *
28535: * Plug a SAX based validation layer in a SAX parsing event flow.
28536: * The original @saxptr and @dataptr data are replaced by new pointers
28537: * but the calls to the original will be maintained.
28538: *
28539: * Returns a pointer to a data structure needed to unplug the validation layer
28540: * or NULL in case of errors.
28541: */
28542: xmlSchemaSAXPlugPtr
28543: xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28544: xmlSAXHandlerPtr *sax, void **user_data)
28545: {
28546: xmlSchemaSAXPlugPtr ret;
28547: xmlSAXHandlerPtr old_sax;
28548:
28549: if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28550: return(NULL);
28551:
28552: /*
28553: * We only allow to plug into SAX2 event streams
28554: */
28555: old_sax = *sax;
28556: if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28557: return(NULL);
28558: if ((old_sax != NULL) &&
28559: (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28560: ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28561: return(NULL);
28562:
28563: /*
28564: * everything seems right allocate the local data needed for that layer
28565: */
28566: ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28567: if (ret == NULL) {
28568: return(NULL);
28569: }
28570: memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28571: ret->magic = XML_SAX_PLUG_MAGIC;
28572: ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28573: ret->ctxt = ctxt;
28574: ret->user_sax_ptr = sax;
28575: ret->user_sax = old_sax;
28576: if (old_sax == NULL) {
28577: /*
28578: * go direct, no need for the split block and functions.
28579: */
28580: ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28581: ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28582: /*
28583: * Note that we use the same text-function for both, to prevent
28584: * the parser from testing for ignorable whitespace.
28585: */
28586: ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28587: ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28588:
28589: ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28590: ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28591:
28592: ret->user_data = ctxt;
28593: *user_data = ctxt;
28594: } else {
28595: /*
28596: * for each callback unused by Schemas initialize it to the Split
28597: * routine only if non NULL in the user block, this can speed up
28598: * things at the SAX level.
28599: */
28600: if (old_sax->internalSubset != NULL)
28601: ret->schemas_sax.internalSubset = internalSubsetSplit;
28602: if (old_sax->isStandalone != NULL)
28603: ret->schemas_sax.isStandalone = isStandaloneSplit;
28604: if (old_sax->hasInternalSubset != NULL)
28605: ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28606: if (old_sax->hasExternalSubset != NULL)
28607: ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28608: if (old_sax->resolveEntity != NULL)
28609: ret->schemas_sax.resolveEntity = resolveEntitySplit;
28610: if (old_sax->getEntity != NULL)
28611: ret->schemas_sax.getEntity = getEntitySplit;
28612: if (old_sax->entityDecl != NULL)
28613: ret->schemas_sax.entityDecl = entityDeclSplit;
28614: if (old_sax->notationDecl != NULL)
28615: ret->schemas_sax.notationDecl = notationDeclSplit;
28616: if (old_sax->attributeDecl != NULL)
28617: ret->schemas_sax.attributeDecl = attributeDeclSplit;
28618: if (old_sax->elementDecl != NULL)
28619: ret->schemas_sax.elementDecl = elementDeclSplit;
28620: if (old_sax->unparsedEntityDecl != NULL)
28621: ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28622: if (old_sax->setDocumentLocator != NULL)
28623: ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28624: if (old_sax->startDocument != NULL)
28625: ret->schemas_sax.startDocument = startDocumentSplit;
28626: if (old_sax->endDocument != NULL)
28627: ret->schemas_sax.endDocument = endDocumentSplit;
28628: if (old_sax->processingInstruction != NULL)
28629: ret->schemas_sax.processingInstruction = processingInstructionSplit;
28630: if (old_sax->comment != NULL)
28631: ret->schemas_sax.comment = commentSplit;
28632: if (old_sax->warning != NULL)
28633: ret->schemas_sax.warning = warningSplit;
28634: if (old_sax->error != NULL)
28635: ret->schemas_sax.error = errorSplit;
28636: if (old_sax->fatalError != NULL)
28637: ret->schemas_sax.fatalError = fatalErrorSplit;
28638: if (old_sax->getParameterEntity != NULL)
28639: ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28640: if (old_sax->externalSubset != NULL)
28641: ret->schemas_sax.externalSubset = externalSubsetSplit;
28642:
28643: /*
28644: * the 6 schemas callback have to go to the splitter functions
28645: * Note that we use the same text-function for ignorableWhitespace
28646: * if possible, to prevent the parser from testing for ignorable
28647: * whitespace.
28648: */
28649: ret->schemas_sax.characters = charactersSplit;
28650: if ((old_sax->ignorableWhitespace != NULL) &&
28651: (old_sax->ignorableWhitespace != old_sax->characters))
28652: ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28653: else
28654: ret->schemas_sax.ignorableWhitespace = charactersSplit;
28655: ret->schemas_sax.cdataBlock = cdataBlockSplit;
28656: ret->schemas_sax.reference = referenceSplit;
28657: ret->schemas_sax.startElementNs = startElementNsSplit;
28658: ret->schemas_sax.endElementNs = endElementNsSplit;
28659:
28660: ret->user_data_ptr = user_data;
28661: ret->user_data = *user_data;
28662: *user_data = ret;
28663: }
28664:
28665: /*
28666: * plug the pointers back.
28667: */
28668: *sax = &(ret->schemas_sax);
28669: ctxt->sax = *sax;
28670: ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28671: xmlSchemaPreRun(ctxt);
28672: return(ret);
28673: }
28674:
28675: /**
28676: * xmlSchemaSAXUnplug:
28677: * @plug: a data structure returned by xmlSchemaSAXPlug
28678: *
28679: * Unplug a SAX based validation layer in a SAX parsing event flow.
28680: * The original pointers used in the call are restored.
28681: *
28682: * Returns 0 in case of success and -1 in case of failure.
28683: */
28684: int
28685: xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28686: {
28687: xmlSAXHandlerPtr *sax;
28688: void **user_data;
28689:
28690: if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28691: return(-1);
28692: plug->magic = 0;
28693:
28694: xmlSchemaPostRun(plug->ctxt);
28695: /* restore the data */
28696: sax = plug->user_sax_ptr;
28697: *sax = plug->user_sax;
28698: if (plug->user_sax != NULL) {
28699: user_data = plug->user_data_ptr;
28700: *user_data = plug->user_data;
28701: }
28702:
28703: /* free and return */
28704: xmlFree(plug);
28705: return(0);
28706: }
28707:
28708: /**
1.1.1.3 ! misho 28709: * xmlSchemaValidateSetLocator:
! 28710: * @vctxt: a schema validation context
! 28711: * @f: the locator function pointer
! 28712: * @ctxt: the locator context
! 28713: *
! 28714: * Allows to set a locator function to the validation context,
! 28715: * which will be used to provide file and line information since
! 28716: * those are not provided as part of the SAX validation flow
! 28717: * Setting @f to NULL disable the locator.
! 28718: */
! 28719:
! 28720: void
! 28721: xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
! 28722: xmlSchemaValidityLocatorFunc f,
! 28723: void *ctxt)
! 28724: {
! 28725: if (vctxt == NULL) return;
! 28726: vctxt->locFunc = f;
! 28727: vctxt->locCtxt = ctxt;
! 28728: }
! 28729:
! 28730: /**
! 28731: * xmlSchemaValidateStreamLocator:
! 28732: * @ctx: the xmlTextReaderPtr used
! 28733: * @file: returned file information
! 28734: * @line: returned line information
! 28735: *
! 28736: * Internal locator function for the readers
! 28737: *
! 28738: * Returns 0 in case the Schema validation could be (des)activated and
! 28739: * -1 in case of error.
! 28740: */
! 28741: static int
! 28742: xmlSchemaValidateStreamLocator(void *ctx, const char **file,
! 28743: unsigned long *line) {
! 28744: xmlParserCtxtPtr ctxt;
! 28745:
! 28746: if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
! 28747: return(-1);
! 28748:
! 28749: if (file != NULL)
! 28750: *file = NULL;
! 28751: if (line != NULL)
! 28752: *line = 0;
! 28753:
! 28754: ctxt = (xmlParserCtxtPtr) ctx;
! 28755: if (ctxt->input != NULL) {
! 28756: if (file != NULL)
! 28757: *file = ctxt->input->filename;
! 28758: if (line != NULL)
! 28759: *line = ctxt->input->line;
! 28760: return(0);
! 28761: }
! 28762: return(-1);
! 28763: }
! 28764:
! 28765: /**
1.1 misho 28766: * xmlSchemaValidateStream:
28767: * @ctxt: a schema validation context
28768: * @input: the input to use for reading the data
28769: * @enc: an optional encoding information
28770: * @sax: a SAX handler for the resulting events
28771: * @user_data: the context to provide to the SAX handler.
28772: *
28773: * Validate an input based on a flow of SAX event from the parser
28774: * and forward the events to the @sax handler with the provided @user_data
28775: * the user provided @sax handler must be a SAX2 one.
28776: *
28777: * Returns 0 if the document is schemas valid, a positive error code
28778: * number otherwise and -1 in case of internal or API error.
28779: */
28780: int
28781: xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28782: xmlParserInputBufferPtr input, xmlCharEncoding enc,
28783: xmlSAXHandlerPtr sax, void *user_data)
28784: {
28785: xmlSchemaSAXPlugPtr plug = NULL;
28786: xmlSAXHandlerPtr old_sax = NULL;
28787: xmlParserCtxtPtr pctxt = NULL;
28788: xmlParserInputPtr inputStream = NULL;
28789: int ret;
28790:
28791: if ((ctxt == NULL) || (input == NULL))
28792: return (-1);
28793:
28794: /*
28795: * prepare the parser
28796: */
28797: pctxt = xmlNewParserCtxt();
28798: if (pctxt == NULL)
28799: return (-1);
28800: old_sax = pctxt->sax;
28801: pctxt->sax = sax;
28802: pctxt->userData = user_data;
28803: #if 0
28804: if (options)
28805: xmlCtxtUseOptions(pctxt, options);
28806: #endif
28807: pctxt->linenumbers = 1;
1.1.1.3 ! misho 28808: xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
1.1 misho 28809:
28810: inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28811: if (inputStream == NULL) {
28812: ret = -1;
28813: goto done;
28814: }
28815: inputPush(pctxt, inputStream);
28816: ctxt->parserCtxt = pctxt;
28817: ctxt->input = input;
28818:
28819: /*
28820: * Plug the validation and launch the parsing
28821: */
28822: plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28823: if (plug == NULL) {
28824: ret = -1;
28825: goto done;
28826: }
28827: ctxt->input = input;
28828: ctxt->enc = enc;
28829: ctxt->sax = pctxt->sax;
28830: ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28831: ret = xmlSchemaVStart(ctxt);
28832:
28833: if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28834: ret = ctxt->parserCtxt->errNo;
28835: if (ret == 0)
28836: ret = 1;
28837: }
28838:
28839: done:
28840: ctxt->parserCtxt = NULL;
28841: ctxt->sax = NULL;
28842: ctxt->input = NULL;
28843: if (plug != NULL) {
28844: xmlSchemaSAXUnplug(plug);
28845: }
28846: /* cleanup */
28847: if (pctxt != NULL) {
28848: pctxt->sax = old_sax;
28849: xmlFreeParserCtxt(pctxt);
28850: }
28851: return (ret);
28852: }
28853:
28854: /**
28855: * xmlSchemaValidateFile:
28856: * @ctxt: a schema validation context
28857: * @filename: the URI of the instance
28858: * @options: a future set of options, currently unused
28859: *
28860: * Do a schemas validation of the given resource, it will use the
28861: * SAX streamable validation internally.
28862: *
28863: * Returns 0 if the document is valid, a positive error code
28864: * number otherwise and -1 in case of an internal or API error.
28865: */
28866: int
28867: xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28868: const char * filename,
28869: int options ATTRIBUTE_UNUSED)
28870: {
28871: int ret;
28872: xmlParserInputBufferPtr input;
28873:
28874: if ((ctxt == NULL) || (filename == NULL))
28875: return (-1);
28876:
28877: input = xmlParserInputBufferCreateFilename(filename,
28878: XML_CHAR_ENCODING_NONE);
28879: if (input == NULL)
28880: return (-1);
28881: ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28882: NULL, NULL);
28883: return (ret);
28884: }
28885:
28886: /**
28887: * xmlSchemaValidCtxtGetParserCtxt:
28888: * @ctxt: a schema validation context
28889: *
28890: * allow access to the parser context of the schema validation context
28891: *
28892: * Returns the parser context of the schema validation context or NULL
28893: * in case of error.
28894: */
28895: xmlParserCtxtPtr
28896: xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28897: {
28898: if (ctxt == NULL)
28899: return(NULL);
28900: return (ctxt->parserCtxt);
28901: }
28902:
28903: #define bottom_xmlschemas
28904: #include "elfgcchack.h"
28905: #endif /* LIBXML_SCHEMAS_ENABLED */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>