| OLD | NEW |
| (Empty) |
| 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/03
37.html | |
| 30 * IDC XPath expression and chameleon includes: the targetNamespace is chang
ed, so | |
| 31 * XPath will have trouble to resolve to this namespace, since not known. | |
| 32 * | |
| 33 * | |
| 34 * CONSTRAINTS: | |
| 35 * | |
| 36 * Schema Component Constraint: | |
| 37 * All Group Limited (cos-all-limited) | |
| 38 * Status: complete | |
| 39 * (1.2) | |
| 40 * In xmlSchemaGroupDefReferenceTermFixup() and | |
| 41 * (2) | |
| 42 * In xmlSchemaParseModelGroup() | |
| 43 * TODO: Actually this should go to component-level checks, | |
| 44 * but is done here due to performance. Move it to an other layer | |
| 45 * is schema construction via an API is implemented. | |
| 46 */ | |
| 47 #define IN_LIBXML | |
| 48 #include "libxml.h" | |
| 49 | |
| 50 #ifdef LIBXML_SCHEMAS_ENABLED | |
| 51 | |
| 52 #include <string.h> | |
| 53 #include <libxml/xmlmemory.h> | |
| 54 #include <libxml/parser.h> | |
| 55 #include <libxml/parserInternals.h> | |
| 56 #include <libxml/hash.h> | |
| 57 #include <libxml/uri.h> | |
| 58 #include <libxml/xmlschemas.h> | |
| 59 #include <libxml/schemasInternals.h> | |
| 60 #include <libxml/xmlschemastypes.h> | |
| 61 #include <libxml/xmlautomata.h> | |
| 62 #include <libxml/xmlregexp.h> | |
| 63 #include <libxml/dict.h> | |
| 64 #include <libxml/encoding.h> | |
| 65 #include <libxml/xmlIO.h> | |
| 66 #ifdef LIBXML_PATTERN_ENABLED | |
| 67 #include <libxml/pattern.h> | |
| 68 #endif | |
| 69 #ifdef LIBXML_READER_ENABLED | |
| 70 #include <libxml/xmlreader.h> | |
| 71 #endif | |
| 72 | |
| 73 /* #define DEBUG 1 */ | |
| 74 | |
| 75 /* #define DEBUG_CONTENT 1 */ | |
| 76 | |
| 77 /* #define DEBUG_TYPE 1 */ | |
| 78 | |
| 79 /* #define DEBUG_CONTENT_REGEXP 1 */ | |
| 80 | |
| 81 /* #define DEBUG_AUTOMATA 1 */ | |
| 82 | |
| 83 /* #define DEBUG_IDC */ | |
| 84 | |
| 85 /* #define DEBUG_IDC_NODE_TABLE */ | |
| 86 | |
| 87 /* #define WXS_ELEM_DECL_CONS_ENABLED */ | |
| 88 | |
| 89 #ifdef DEBUG_IDC | |
| 90 #ifndef DEBUG_IDC_NODE_TABLE | |
| 91 #define DEBUG_IDC_NODE_TABLE | |
| 92 #endif | |
| 93 #endif | |
| 94 | |
| 95 /* #define ENABLE_PARTICLE_RESTRICTION 1 */ | |
| 96 | |
| 97 #define ENABLE_REDEFINE | |
| 98 | |
| 99 /* #define ENABLE_NAMED_LOCALS */ | |
| 100 | |
| 101 /* #define ENABLE_IDC_NODE_TABLES_TEST */ | |
| 102 | |
| 103 #define DUMP_CONTENT_MODEL | |
| 104 | |
| 105 #ifdef LIBXML_READER_ENABLED | |
| 106 /* #define XML_SCHEMA_READER_ENABLED */ | |
| 107 #endif | |
| 108 | |
| 109 #define UNBOUNDED (1 << 30) | |
| 110 #define TODO \ | |
| 111 xmlGenericError(xmlGenericErrorContext, \ | |
| 112 "Unimplemented block at %s:%d\n", \ | |
| 113 __FILE__, __LINE__); | |
| 114 | |
| 115 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##" | |
| 116 | |
| 117 /* | |
| 118 * The XML Schemas namespaces | |
| 119 */ | |
| 120 static const xmlChar *xmlSchemaNs = (const xmlChar *) | |
| 121 "http://www.w3.org/2001/XMLSchema"; | |
| 122 | |
| 123 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *) | |
| 124 "http://www.w3.org/2001/XMLSchema-instance"; | |
| 125 | |
| 126 static const xmlChar *xmlNamespaceNs = (const xmlChar *) | |
| 127 "http://www.w3.org/2000/xmlns/"; | |
| 128 | |
| 129 /* | |
| 130 * Come casting macros. | |
| 131 */ | |
| 132 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr) | |
| 133 #define PCTXT_CAST (xmlSchemaParserCtxtPtr) | |
| 134 #define VCTXT_CAST (xmlSchemaValidCtxtPtr) | |
| 135 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr) | |
| 136 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr) | |
| 137 #define WXS_PTC_CAST (xmlSchemaParticlePtr) | |
| 138 #define WXS_TYPE_CAST (xmlSchemaTypePtr) | |
| 139 #define WXS_ELEM_CAST (xmlSchemaElementPtr) | |
| 140 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr) | |
| 141 #define WXS_ATTR_CAST (xmlSchemaAttributePtr) | |
| 142 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr) | |
| 143 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr) | |
| 144 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr) | |
| 145 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr) | |
| 146 #define WXS_IDC_CAST (xmlSchemaIDCPtr) | |
| 147 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr) | |
| 148 #define WXS_LIST_CAST (xmlSchemaItemListPtr) | |
| 149 | |
| 150 /* | |
| 151 * Macros to query common properties of components. | |
| 152 */ | |
| 153 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i)) | |
| 154 | |
| 155 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i)) | |
| 156 /* | |
| 157 * Macros for element declarations. | |
| 158 */ | |
| 159 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes | |
| 160 | |
| 161 #define WXS_SUBST_HEAD(item) (item)->refDecl | |
| 162 /* | |
| 163 * Macros for attribute declarations. | |
| 164 */ | |
| 165 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes | |
| 166 /* | |
| 167 * Macros for attribute uses. | |
| 168 */ | |
| 169 #define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl | |
| 170 | |
| 171 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_
CAST au)) | |
| 172 | |
| 173 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name | |
| 174 | |
| 175 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace | |
| 176 /* | |
| 177 * Macros for attribute groups. | |
| 178 */ | |
| 179 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCH
EMAS_ATTRGROUP_HAS_REFS) | |
| 180 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCH
EMAS_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 warni
ng */ | |
| 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; /* dictionary 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 "wild
card") */ | |
| 686 xmlNodePtr node; | |
| 687 }; | |
| 688 | |
| 689 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0 | |
| 690 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1 | |
| 691 /** | |
| 692 * xmlSchemaModelGroupDef: | |
| 693 * | |
| 694 * A model group definition component. | |
| 695 * (Extends xmlSchemaTreeItem) | |
| 696 */ | |
| 697 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef; | |
| 698 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr; | |
| 699 struct _xmlSchemaModelGroupDef { | |
| 700 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */ | |
| 701 xmlSchemaAnnotPtr annot; | |
| 702 xmlSchemaTreeItemPtr next; /* not used */ | |
| 703 xmlSchemaTreeItemPtr children; /* the "model group" */ | |
| 704 const xmlChar *name; | |
| 705 const xmlChar *targetNamespace; | |
| 706 xmlNodePtr node; | |
| 707 int flags; | |
| 708 }; | |
| 709 | |
| 710 typedef struct _xmlSchemaIDC xmlSchemaIDC; | |
| 711 typedef xmlSchemaIDC *xmlSchemaIDCPtr; | |
| 712 | |
| 713 /** | |
| 714 * xmlSchemaIDCSelect: | |
| 715 * | |
| 716 * The identity-constraint "field" and "selector" item, holding the | |
| 717 * XPath expression. | |
| 718 */ | |
| 719 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect; | |
| 720 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr; | |
| 721 struct _xmlSchemaIDCSelect { | |
| 722 xmlSchemaIDCSelectPtr next; | |
| 723 xmlSchemaIDCPtr idc; | |
| 724 int index; /* an index position if significant for IDC key-sequences */ | |
| 725 const xmlChar *xpath; /* the XPath expression */ | |
| 726 void *xpathComp; /* the compiled XPath expression */ | |
| 727 }; | |
| 728 | |
| 729 /** | |
| 730 * xmlSchemaIDC: | |
| 731 * | |
| 732 * The identity-constraint definition component. | |
| 733 * (Extends xmlSchemaAnnotItem) | |
| 734 */ | |
| 735 | |
| 736 struct _xmlSchemaIDC { | |
| 737 xmlSchemaTypeType type; | |
| 738 xmlSchemaAnnotPtr annot; | |
| 739 xmlSchemaIDCPtr next; | |
| 740 xmlNodePtr node; | |
| 741 const xmlChar *name; | |
| 742 const xmlChar *targetNamespace; | |
| 743 xmlSchemaIDCSelectPtr selector; | |
| 744 xmlSchemaIDCSelectPtr fields; | |
| 745 int nbFields; | |
| 746 xmlSchemaQNameRefPtr ref; | |
| 747 }; | |
| 748 | |
| 749 /** | |
| 750 * xmlSchemaIDCAug: | |
| 751 * | |
| 752 * The augmented IDC information used for validation. | |
| 753 */ | |
| 754 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug; | |
| 755 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr; | |
| 756 struct _xmlSchemaIDCAug { | |
| 757 xmlSchemaIDCAugPtr next; /* next in a list */ | |
| 758 xmlSchemaIDCPtr def; /* the IDC definition */ | |
| 759 int keyrefDepth; /* the lowest tree level to which IDC | |
| 760 tables need to be bubbled upwards */ | |
| 761 }; | |
| 762 | |
| 763 /** | |
| 764 * xmlSchemaPSVIIDCKeySequence: | |
| 765 * | |
| 766 * The key sequence of a node table item. | |
| 767 */ | |
| 768 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey; | |
| 769 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr; | |
| 770 struct _xmlSchemaPSVIIDCKey { | |
| 771 xmlSchemaTypePtr type; | |
| 772 xmlSchemaValPtr val; | |
| 773 }; | |
| 774 | |
| 775 /** | |
| 776 * xmlSchemaPSVIIDCNode: | |
| 777 * | |
| 778 * The node table item of a node table. | |
| 779 */ | |
| 780 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode; | |
| 781 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr; | |
| 782 struct _xmlSchemaPSVIIDCNode { | |
| 783 xmlNodePtr node; | |
| 784 xmlSchemaPSVIIDCKeyPtr *keys; | |
| 785 int nodeLine; | |
| 786 int nodeQNameID; | |
| 787 | |
| 788 }; | |
| 789 | |
| 790 /** | |
| 791 * xmlSchemaPSVIIDCBinding: | |
| 792 * | |
| 793 * The identity-constraint binding item of the [identity-constraint table]. | |
| 794 */ | |
| 795 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding; | |
| 796 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr; | |
| 797 struct _xmlSchemaPSVIIDCBinding { | |
| 798 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */ | |
| 799 xmlSchemaIDCPtr definition; /* the IDC definition */ | |
| 800 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */ | |
| 801 int nbNodes; /* number of entries in the node table */ | |
| 802 int sizeNodes; /* size of the node table */ | |
| 803 xmlSchemaItemListPtr dupls; | |
| 804 }; | |
| 805 | |
| 806 | |
| 807 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1 | |
| 808 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2 | |
| 809 | |
| 810 #define XPATH_STATE_OBJ_MATCHES -2 | |
| 811 #define XPATH_STATE_OBJ_BLOCKED -3 | |
| 812 | |
| 813 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher; | |
| 814 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr; | |
| 815 | |
| 816 /** | |
| 817 * xmlSchemaIDCStateObj: | |
| 818 * | |
| 819 * The state object used to evaluate XPath expressions. | |
| 820 */ | |
| 821 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj; | |
| 822 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr; | |
| 823 struct _xmlSchemaIDCStateObj { | |
| 824 int type; | |
| 825 xmlSchemaIDCStateObjPtr next; /* next if in a list */ | |
| 826 int depth; /* depth of creation */ | |
| 827 int *history; /* list of (depth, state-id) tuples */ | |
| 828 int nbHistory; | |
| 829 int sizeHistory; | |
| 830 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector | |
| 831 matcher */ | |
| 832 xmlSchemaIDCSelectPtr sel; | |
| 833 void *xpathCtxt; | |
| 834 }; | |
| 835 | |
| 836 #define IDC_MATCHER 0 | |
| 837 | |
| 838 /** | |
| 839 * xmlSchemaIDCMatcher: | |
| 840 * | |
| 841 * Used to evaluate IDC selectors (and fields). | |
| 842 */ | |
| 843 struct _xmlSchemaIDCMatcher { | |
| 844 int type; | |
| 845 int depth; /* the tree depth at creation time */ | |
| 846 xmlSchemaIDCMatcherPtr next; /* next in the list */ | |
| 847 xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */ | |
| 848 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */ | |
| 849 int idcType; | |
| 850 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target | |
| 851 elements */ | |
| 852 int sizeKeySeqs; | |
| 853 xmlSchemaItemListPtr targets; /* list of target-node | |
| 854 (xmlSchemaPSVIIDCNodePtr) entries */ | |
| 855 }; | |
| 856 | |
| 857 /* | |
| 858 * Element info flags. | |
| 859 */ | |
| 860 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0 | |
| 861 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1 | |
| 862 #define XML_SCHEMA_ELEM_INFO_NILLED 1<<2 | |
| 863 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3 | |
| 864 | |
| 865 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4 | |
| 866 #define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5 | |
| 867 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6 | |
| 868 | |
| 869 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7 | |
| 870 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8 | |
| 871 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9 | |
| 872 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10 | |
| 873 | |
| 874 /** | |
| 875 * xmlSchemaNodeInfo: | |
| 876 * | |
| 877 * Holds information of an element node. | |
| 878 */ | |
| 879 struct _xmlSchemaNodeInfo { | |
| 880 int nodeType; | |
| 881 xmlNodePtr node; | |
| 882 int nodeLine; | |
| 883 const xmlChar *localName; | |
| 884 const xmlChar *nsName; | |
| 885 const xmlChar *value; | |
| 886 xmlSchemaValPtr val; /* the pre-computed value if any */ | |
| 887 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */ | |
| 888 | |
| 889 int flags; /* combination of node info flags */ | |
| 890 | |
| 891 int valNeeded; | |
| 892 int normVal; | |
| 893 | |
| 894 xmlSchemaElementPtr decl; /* the element/attribute declaration */ | |
| 895 int depth; | |
| 896 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings | |
| 897 for the scope element*/ | |
| 898 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope | |
| 899 element */ | |
| 900 xmlRegExecCtxtPtr regexCtxt; | |
| 901 | |
| 902 const xmlChar **nsBindings; /* Namespace bindings on this element */ | |
| 903 int nbNsBindings; | |
| 904 int sizeNsBindings; | |
| 905 | |
| 906 int hasKeyrefs; | |
| 907 int appliedXPath; /* Indicates that an XPath has been applied. */ | |
| 908 }; | |
| 909 | |
| 910 #define XML_SCHEMAS_ATTR_UNKNOWN 1 | |
| 911 #define XML_SCHEMAS_ATTR_ASSESSED 2 | |
| 912 #define XML_SCHEMAS_ATTR_PROHIBITED 3 | |
| 913 #define XML_SCHEMAS_ATTR_ERR_MISSING 4 | |
| 914 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5 | |
| 915 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6 | |
| 916 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7 | |
| 917 #define XML_SCHEMAS_ATTR_DEFAULT 8 | |
| 918 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9 | |
| 919 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10 | |
| 920 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11 | |
| 921 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12 | |
| 922 #define XML_SCHEMAS_ATTR_WILD_SKIP 13 | |
| 923 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14 | |
| 924 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15 | |
| 925 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16 | |
| 926 #define XML_SCHEMAS_ATTR_META 17 | |
| 927 /* | |
| 928 * @metaType values of xmlSchemaAttrInfo. | |
| 929 */ | |
| 930 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1 | |
| 931 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2 | |
| 932 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3 | |
| 933 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4 | |
| 934 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5 | |
| 935 | |
| 936 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo; | |
| 937 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr; | |
| 938 struct _xmlSchemaAttrInfo { | |
| 939 int nodeType; | |
| 940 xmlNodePtr node; | |
| 941 int nodeLine; | |
| 942 const xmlChar *localName; | |
| 943 const xmlChar *nsName; | |
| 944 const xmlChar *value; | |
| 945 xmlSchemaValPtr val; /* the pre-computed value if any */ | |
| 946 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */ | |
| 947 int flags; /* combination of node info flags */ | |
| 948 | |
| 949 xmlSchemaAttributePtr decl; /* the attribute declaration */ | |
| 950 xmlSchemaAttributeUsePtr use; /* the attribute use */ | |
| 951 int state; | |
| 952 int metaType; | |
| 953 const xmlChar *vcValue; /* the value constraint value */ | |
| 954 xmlSchemaNodeInfoPtr parent; | |
| 955 }; | |
| 956 | |
| 957 | |
| 958 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1 | |
| 959 /** | |
| 960 * xmlSchemaValidCtxt: | |
| 961 * | |
| 962 * A Schemas validation context | |
| 963 */ | |
| 964 struct _xmlSchemaValidCtxt { | |
| 965 int type; | |
| 966 void *errCtxt; /* user specific data block */ | |
| 967 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */ | |
| 968 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */ | |
| 969 xmlStructuredErrorFunc serror; | |
| 970 | |
| 971 xmlSchemaPtr schema; /* The schema in use */ | |
| 972 xmlDocPtr doc; | |
| 973 xmlParserInputBufferPtr input; | |
| 974 xmlCharEncoding enc; | |
| 975 xmlSAXHandlerPtr sax; | |
| 976 xmlParserCtxtPtr parserCtxt; | |
| 977 void *user_data; /* TODO: What is this for? */ | |
| 978 char *filename; | |
| 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; | |
| 1032 | |
| 1033 /* Locator for error reporting in streaming mode */ | |
| 1034 xmlSchemaValidityLocatorFunc locFunc; | |
| 1035 void *locCtxt; | |
| 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 /************************************************************************ | |
| 1051 * * | |
| 1052 * Some predeclarations * | |
| 1053 * * | |
| 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) LIBXML_ATTR_FORMAT(3,0); | |
| 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 * * | |
| 1106 * Helper functions * | |
| 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 canonical 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 (xmlEscapeFormatString(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 * * | |
| 1844 * Error functions * | |
| 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 LIBXML_ATTR_FORMAT(4,0) | |
| 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 LIBXML_ATTR_FORMAT(5,0) | |
| 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 LIBXML_ATTR_FORMAT(7,0) | |
| 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 * * | |
| 1982 * Allround error functions * | |
| 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 LIBXML_ATTR_FORMAT(2,0) | |
| 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 * xmlSchemaErr4Line: | |
| 2017 * @ctxt: the validation context | |
| 2018 * @errorLevel: the error level | |
| 2019 * @error: the error code | |
| 2020 * @node: the context node | |
| 2021 * @line: the line number | |
| 2022 * @msg: the error message | |
| 2023 * @str1: extra data | |
| 2024 * @str2: extra data | |
| 2025 * @str3: extra data | |
| 2026 * @str4: extra data | |
| 2027 * | |
| 2028 * Handle a validation error | |
| 2029 */ | |
| 2030 static void LIBXML_ATTR_FORMAT(6,0) | |
| 2031 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt, | |
| 2032 xmlErrorLevel errorLevel, | |
| 2033 int error, xmlNodePtr node, int line, const char *msg, | |
| 2034 const xmlChar *str1, const xmlChar *str2, | |
| 2035 const xmlChar *str3, const xmlChar *str4) | |
| 2036 { | |
| 2037 xmlStructuredErrorFunc schannel = NULL; | |
| 2038 xmlGenericErrorFunc channel = NULL; | |
| 2039 void *data = NULL; | |
| 2040 | |
| 2041 if (ctxt != NULL) { | |
| 2042 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) { | |
| 2043 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt; | |
| 2044 const char *file = NULL; | |
| 2045 int col = 0; | |
| 2046 if (errorLevel != XML_ERR_WARNING) { | |
| 2047 vctxt->nberrors++; | |
| 2048 vctxt->err = error; | |
| 2049 channel = vctxt->error; | |
| 2050 } else { | |
| 2051 channel = vctxt->warning; | |
| 2052 } | |
| 2053 schannel = vctxt->serror; | |
| 2054 data = vctxt->errCtxt; | |
| 2055 | |
| 2056 /* | |
| 2057 * Error node. If we specify a line number, then | |
| 2058 * do not channel any node to the error function. | |
| 2059 */ | |
| 2060 if (line == 0) { | |
| 2061 if ((node == NULL) && | |
| 2062 (vctxt->depth >= 0) && | |
| 2063 (vctxt->inode != NULL)) { | |
| 2064 node = vctxt->inode->node; | |
| 2065 } | |
| 2066 /* | |
| 2067 * Get filename and line if no node-tree. | |
| 2068 */ | |
| 2069 if ((node == NULL) && | |
| 2070 (vctxt->parserCtxt != NULL) && | |
| 2071 (vctxt->parserCtxt->input != NULL)) { | |
| 2072 file = vctxt->parserCtxt->input->filename; | |
| 2073 line = vctxt->parserCtxt->input->line; | |
| 2074 col = vctxt->parserCtxt->input->col; | |
| 2075 } | |
| 2076 } else { | |
| 2077 /* | |
| 2078 * Override the given node's (if any) position | |
| 2079 * and channel only the given line number. | |
| 2080 */ | |
| 2081 node = NULL; | |
| 2082 /* | |
| 2083 * Get filename. | |
| 2084 */ | |
| 2085 if (vctxt->doc != NULL) | |
| 2086 file = (const char *) vctxt->doc->URL; | |
| 2087 else if ((vctxt->parserCtxt != NULL) && | |
| 2088 (vctxt->parserCtxt->input != NULL)) | |
| 2089 file = vctxt->parserCtxt->input->filename; | |
| 2090 } | |
| 2091 if (vctxt->locFunc != NULL) { | |
| 2092 if ((file == NULL) || (line == 0)) { | |
| 2093 unsigned long l; | |
| 2094 const char *f; | |
| 2095 vctxt->locFunc(vctxt->locCtxt, &f, &l); | |
| 2096 if (file == NULL) | |
| 2097 file = f; | |
| 2098 if (line == 0) | |
| 2099 line = (int) l; | |
| 2100 } | |
| 2101 } | |
| 2102 if ((file == NULL) && (vctxt->filename != NULL)) | |
| 2103 file = vctxt->filename; | |
| 2104 | |
| 2105 __xmlRaiseError(schannel, channel, data, ctxt, | |
| 2106 node, XML_FROM_SCHEMASV, | |
| 2107 error, errorLevel, file, line, | |
| 2108 (const char *) str1, (const char *) str2, | |
| 2109 (const char *) str3, 0, col, msg, str1, str2, str3, str4); | |
| 2110 | |
| 2111 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) { | |
| 2112 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt; | |
| 2113 if (errorLevel != XML_ERR_WARNING) { | |
| 2114 pctxt->nberrors++; | |
| 2115 pctxt->err = error; | |
| 2116 channel = pctxt->error; | |
| 2117 } else { | |
| 2118 channel = pctxt->warning; | |
| 2119 } | |
| 2120 schannel = pctxt->serror; | |
| 2121 data = pctxt->errCtxt; | |
| 2122 __xmlRaiseError(schannel, channel, data, ctxt, | |
| 2123 node, XML_FROM_SCHEMASP, error, | |
| 2124 errorLevel, NULL, 0, | |
| 2125 (const char *) str1, (const char *) str2, | |
| 2126 (const char *) str3, 0, 0, msg, str1, str2, str3, str4); | |
| 2127 } else { | |
| 2128 TODO | |
| 2129 } | |
| 2130 } | |
| 2131 } | |
| 2132 | |
| 2133 /** | |
| 2134 * xmlSchemaErr3: | |
| 2135 * @ctxt: the validation context | |
| 2136 * @node: the context node | |
| 2137 * @error: the error code | |
| 2138 * @msg: the error message | |
| 2139 * @str1: extra data | |
| 2140 * @str2: extra data | |
| 2141 * @str3: extra data | |
| 2142 * | |
| 2143 * Handle a validation error | |
| 2144 */ | |
| 2145 static void LIBXML_ATTR_FORMAT(4,0) | |
| 2146 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt, | |
| 2147 int error, xmlNodePtr node, const char *msg, | |
| 2148 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3) | |
| 2149 { | |
| 2150 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0, | |
| 2151 msg, str1, str2, str3, NULL); | |
| 2152 } | |
| 2153 | |
| 2154 static void LIBXML_ATTR_FORMAT(4,0) | |
| 2155 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt, | |
| 2156 int error, xmlNodePtr node, const char *msg, | |
| 2157 const xmlChar *str1, const xmlChar *str2, | |
| 2158 const xmlChar *str3, const xmlChar *str4) | |
| 2159 { | |
| 2160 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0, | |
| 2161 msg, str1, str2, str3, str4); | |
| 2162 } | |
| 2163 | |
| 2164 static void LIBXML_ATTR_FORMAT(4,0) | |
| 2165 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt, | |
| 2166 int error, xmlNodePtr node, const char *msg, | |
| 2167 const xmlChar *str1, const xmlChar *str2) | |
| 2168 { | |
| 2169 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL); | |
| 2170 } | |
| 2171 | |
| 2172 static xmlChar * | |
| 2173 xmlSchemaFormatNodeForError(xmlChar ** msg, | |
| 2174 xmlSchemaAbstractCtxtPtr actxt, | |
| 2175 xmlNodePtr node) | |
| 2176 { | |
| 2177 xmlChar *str = NULL; | |
| 2178 | |
| 2179 *msg = NULL; | |
| 2180 if ((node != NULL) && | |
| 2181 (node->type != XML_ELEMENT_NODE) && | |
| 2182 (node->type != XML_ATTRIBUTE_NODE)) | |
| 2183 { | |
| 2184 /* | |
| 2185 * Don't try to format other nodes than element and | |
| 2186 * attribute nodes. | |
| 2187 * Play safe and return an empty string. | |
| 2188 */ | |
| 2189 *msg = xmlStrdup(BAD_CAST ""); | |
| 2190 return(*msg); | |
| 2191 } | |
| 2192 if (node != NULL) { | |
| 2193 /* | |
| 2194 * Work on tree nodes. | |
| 2195 */ | |
| 2196 if (node->type == XML_ATTRIBUTE_NODE) { | |
| 2197 xmlNodePtr elem = node->parent; | |
| 2198 | |
| 2199 *msg = xmlStrdup(BAD_CAST "Element '"); | |
| 2200 if (elem->ns != NULL) | |
| 2201 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, | |
| 2202 elem->ns->href, elem->name)); | |
| 2203 else | |
| 2204 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, | |
| 2205 NULL, elem->name)); | |
| 2206 FREE_AND_NULL(str); | |
| 2207 *msg = xmlStrcat(*msg, BAD_CAST "', "); | |
| 2208 *msg = xmlStrcat(*msg, BAD_CAST "attribute '"); | |
| 2209 } else { | |
| 2210 *msg = xmlStrdup(BAD_CAST "Element '"); | |
| 2211 } | |
| 2212 if (node->ns != NULL) | |
| 2213 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, | |
| 2214 node->ns->href, node->name)); | |
| 2215 else | |
| 2216 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, | |
| 2217 NULL, node->name)); | |
| 2218 FREE_AND_NULL(str); | |
| 2219 *msg = xmlStrcat(*msg, BAD_CAST "': "); | |
| 2220 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) { | |
| 2221 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt; | |
| 2222 /* | |
| 2223 * Work on node infos. | |
| 2224 */ | |
| 2225 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) { | |
| 2226 xmlSchemaNodeInfoPtr ielem = | |
| 2227 vctxt->elemInfos[vctxt->depth]; | |
| 2228 | |
| 2229 *msg = xmlStrdup(BAD_CAST "Element '"); | |
| 2230 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, | |
| 2231 ielem->nsName, ielem->localName)); | |
| 2232 FREE_AND_NULL(str); | |
| 2233 *msg = xmlStrcat(*msg, BAD_CAST "', "); | |
| 2234 *msg = xmlStrcat(*msg, BAD_CAST "attribute '"); | |
| 2235 } else { | |
| 2236 *msg = xmlStrdup(BAD_CAST "Element '"); | |
| 2237 } | |
| 2238 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, | |
| 2239 vctxt->inode->nsName, vctxt->inode->localName)); | |
| 2240 FREE_AND_NULL(str); | |
| 2241 *msg = xmlStrcat(*msg, BAD_CAST "': "); | |
| 2242 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) { | |
| 2243 /* | |
| 2244 * Hmm, no node while parsing? | |
| 2245 * Return an empty string, in case NULL will break something. | |
| 2246 */ | |
| 2247 *msg = xmlStrdup(BAD_CAST ""); | |
| 2248 } else { | |
| 2249 TODO | |
| 2250 return (NULL); | |
| 2251 } | |
| 2252 | |
| 2253 /* | |
| 2254 * xmlSchemaFormatItemForReport() also returns an escaped format | |
| 2255 * string, so do this before calling it below (in the future). | |
| 2256 */ | |
| 2257 xmlEscapeFormatString(msg); | |
| 2258 | |
| 2259 /* | |
| 2260 * VAL TODO: The output of the given schema component is currently | |
| 2261 * disabled. | |
| 2262 */ | |
| 2263 #if 0 | |
| 2264 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) { | |
| 2265 *msg = xmlStrcat(*msg, BAD_CAST " ["); | |
| 2266 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str, | |
| 2267 NULL, type, NULL, 0)); | |
| 2268 FREE_AND_NULL(str) | |
| 2269 *msg = xmlStrcat(*msg, BAD_CAST "]"); | |
| 2270 } | |
| 2271 #endif | |
| 2272 return (*msg); | |
| 2273 } | |
| 2274 | |
| 2275 static void LIBXML_ATTR_FORMAT(3,0) | |
| 2276 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt, | |
| 2277 const char *funcName, | |
| 2278 const char *message, | |
| 2279 const xmlChar *str1, | |
| 2280 const xmlChar *str2) | |
| 2281 { | |
| 2282 xmlChar *msg = NULL; | |
| 2283 | |
| 2284 if (actxt == NULL) | |
| 2285 return; | |
| 2286 msg = xmlStrdup(BAD_CAST "Internal error: %s, "); | |
| 2287 msg = xmlStrcat(msg, BAD_CAST message); | |
| 2288 msg = xmlStrcat(msg, BAD_CAST ".\n"); | |
| 2289 | |
| 2290 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) | |
| 2291 xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL, | |
| 2292 (const char *) msg, (const xmlChar *) funcName, str1, str2); | |
| 2293 else if (actxt->type == XML_SCHEMA_CTXT_PARSER) | |
| 2294 xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL, | |
| 2295 (const char *) msg, (const xmlChar *) funcName, str1, str2); | |
| 2296 | |
| 2297 FREE_AND_NULL(msg) | |
| 2298 } | |
| 2299 | |
| 2300 static void LIBXML_ATTR_FORMAT(3,0) | |
| 2301 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt, | |
| 2302 const char *funcName, | |
| 2303 const char *message) | |
| 2304 { | |
| 2305 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL); | |
| 2306 } | |
| 2307 | |
| 2308 #if 0 | |
| 2309 static void LIBXML_ATTR_FORMAT(3,0) | |
| 2310 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt, | |
| 2311 const char *funcName, | |
| 2312 const char *message, | |
| 2313 const xmlChar *str1, | |
| 2314 const xmlChar *str2) | |
| 2315 { | |
| 2316 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message, | |
| 2317 str1, str2); | |
| 2318 } | |
| 2319 #endif | |
| 2320 | |
| 2321 static void LIBXML_ATTR_FORMAT(5,0) | |
| 2322 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt, | |
| 2323 xmlParserErrors error, | |
| 2324 xmlNodePtr node, | |
| 2325 xmlSchemaBasicItemPtr item, | |
| 2326 const char *message, | |
| 2327 const xmlChar *str1, const xmlChar *str2, | |
| 2328 const xmlChar *str3, const xmlChar *str4) | |
| 2329 { | |
| 2330 xmlChar *msg = NULL; | |
| 2331 | |
| 2332 if ((node == NULL) && (item != NULL) && | |
| 2333 (actxt->type == XML_SCHEMA_CTXT_PARSER)) { | |
| 2334 node = WXS_ITEM_NODE(item); | |
| 2335 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL); | |
| 2336 msg = xmlStrcat(msg, BAD_CAST ": "); | |
| 2337 } else | |
| 2338 xmlSchemaFormatNodeForError(&msg, actxt, node); | |
| 2339 msg = xmlStrcat(msg, (const xmlChar *) message); | |
| 2340 msg = xmlStrcat(msg, BAD_CAST ".\n"); | |
| 2341 xmlSchemaErr4(actxt, error, node, | |
| 2342 (const char *) msg, str1, str2, str3, str4); | |
| 2343 FREE_AND_NULL(msg) | |
| 2344 } | |
| 2345 | |
| 2346 static void LIBXML_ATTR_FORMAT(5,0) | |
| 2347 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt, | |
| 2348 xmlParserErrors error, | |
| 2349 xmlNodePtr node, | |
| 2350 xmlSchemaBasicItemPtr item, | |
| 2351 const char *message, | |
| 2352 const xmlChar *str1, | |
| 2353 const xmlChar *str2) | |
| 2354 { | |
| 2355 xmlSchemaCustomErr4(actxt, error, node, item, | |
| 2356 message, str1, str2, NULL, NULL); | |
| 2357 } | |
| 2358 | |
| 2359 | |
| 2360 | |
| 2361 static void LIBXML_ATTR_FORMAT(5,0) | |
| 2362 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt, | |
| 2363 xmlParserErrors error, | |
| 2364 xmlNodePtr node, | |
| 2365 xmlSchemaTypePtr type ATTRIBUTE_UNUSED, | |
| 2366 const char *message, | |
| 2367 const xmlChar *str1, | |
| 2368 const xmlChar *str2, | |
| 2369 const xmlChar *str3) | |
| 2370 { | |
| 2371 xmlChar *msg = NULL; | |
| 2372 | |
| 2373 xmlSchemaFormatNodeForError(&msg, actxt, node); | |
| 2374 msg = xmlStrcat(msg, (const xmlChar *) message); | |
| 2375 msg = xmlStrcat(msg, BAD_CAST ".\n"); | |
| 2376 | |
| 2377 /* URGENT TODO: Set the error code to something sane. */ | |
| 2378 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0, | |
| 2379 (const char *) msg, str1, str2, str3, NULL); | |
| 2380 | |
| 2381 FREE_AND_NULL(msg) | |
| 2382 } | |
| 2383 | |
| 2384 | |
| 2385 | |
| 2386 static void LIBXML_ATTR_FORMAT(5,0) | |
| 2387 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt, | |
| 2388 xmlParserErrors error, | |
| 2389 xmlSchemaPSVIIDCNodePtr idcNode, | |
| 2390 xmlSchemaTypePtr type ATTRIBUTE_UNUSED, | |
| 2391 const char *message, | |
| 2392 const xmlChar *str1, | |
| 2393 const xmlChar *str2) | |
| 2394 { | |
| 2395 xmlChar *msg = NULL, *qname = NULL; | |
| 2396 | |
| 2397 msg = xmlStrdup(BAD_CAST "Element '%s': "); | |
| 2398 msg = xmlStrcat(msg, (const xmlChar *) message); | |
| 2399 msg = xmlStrcat(msg, BAD_CAST ".\n"); | |
| 2400 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR, | |
| 2401 error, NULL, idcNode->nodeLine, (const char *) msg, | |
| 2402 xmlSchemaFormatQName(&qname, | |
| 2403 vctxt->nodeQNames->items[idcNode->nodeQNameID +1], | |
| 2404 vctxt->nodeQNames->items[idcNode->nodeQNameID]), | |
| 2405 str1, str2, NULL); | |
| 2406 FREE_AND_NULL(qname); | |
| 2407 FREE_AND_NULL(msg); | |
| 2408 } | |
| 2409 | |
| 2410 static int | |
| 2411 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt, | |
| 2412 xmlNodePtr node) | |
| 2413 { | |
| 2414 if (node != NULL) | |
| 2415 return (node->type); | |
| 2416 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) && | |
| 2417 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL)) | |
| 2418 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType); | |
| 2419 return (-1); | |
| 2420 } | |
| 2421 | |
| 2422 static int | |
| 2423 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item) | |
| 2424 { | |
| 2425 switch (item->type) { | |
| 2426 case XML_SCHEMA_TYPE_COMPLEX: | |
| 2427 case XML_SCHEMA_TYPE_SIMPLE: | |
| 2428 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) | |
| 2429 return(1); | |
| 2430 break; | |
| 2431 case XML_SCHEMA_TYPE_GROUP: | |
| 2432 return (1); | |
| 2433 case XML_SCHEMA_TYPE_ELEMENT: | |
| 2434 if ( ((xmlSchemaElementPtr) item)->flags & | |
| 2435 XML_SCHEMAS_ELEM_GLOBAL) | |
| 2436 return(1); | |
| 2437 break; | |
| 2438 case XML_SCHEMA_TYPE_ATTRIBUTE: | |
| 2439 if ( ((xmlSchemaAttributePtr) item)->flags & | |
| 2440 XML_SCHEMAS_ATTR_GLOBAL) | |
| 2441 return(1); | |
| 2442 break; | |
| 2443 /* Note that attribute groups are always global. */ | |
| 2444 default: | |
| 2445 return(1); | |
| 2446 } | |
| 2447 return (0); | |
| 2448 } | |
| 2449 | |
| 2450 static void | |
| 2451 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt, | |
| 2452 xmlParserErrors error, | |
| 2453 xmlNodePtr node, | |
| 2454 const xmlChar *value, | |
| 2455 xmlSchemaTypePtr type, | |
| 2456 int displayValue) | |
| 2457 { | |
| 2458 xmlChar *msg = NULL; | |
| 2459 | |
| 2460 xmlSchemaFormatNodeForError(&msg, actxt, node); | |
| 2461 | |
| 2462 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) == | |
| 2463 XML_ATTRIBUTE_NODE)) | |
| 2464 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of "); | |
| 2465 else | |
| 2466 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid " | |
| 2467 "value of "); | |
| 2468 | |
| 2469 if (! xmlSchemaIsGlobalItem(type)) | |
| 2470 msg = xmlStrcat(msg, BAD_CAST "the local "); | |
| 2471 else | |
| 2472 msg = xmlStrcat(msg, BAD_CAST "the "); | |
| 2473 | |
| 2474 if (WXS_IS_ATOMIC(type)) | |
| 2475 msg = xmlStrcat(msg, BAD_CAST "atomic type"); | |
| 2476 else if (WXS_IS_LIST(type)) | |
| 2477 msg = xmlStrcat(msg, BAD_CAST "list type"); | |
| 2478 else if (WXS_IS_UNION(type)) | |
| 2479 msg = xmlStrcat(msg, BAD_CAST "union type"); | |
| 2480 | |
| 2481 if (xmlSchemaIsGlobalItem(type)) { | |
| 2482 xmlChar *str = NULL; | |
| 2483 msg = xmlStrcat(msg, BAD_CAST " '"); | |
| 2484 if (type->builtInType != 0) { | |
| 2485 msg = xmlStrcat(msg, BAD_CAST "xs:"); | |
| 2486 str = xmlStrdup(type->name); | |
| 2487 } else { | |
| 2488 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamesp
ace, type->name); | |
| 2489 if (!str) | |
| 2490 str = xmlStrdup(qName); | |
| 2491 } | |
| 2492 msg = xmlStrcat(msg, xmlEscapeFormatString(&str)); | |
| 2493 msg = xmlStrcat(msg, BAD_CAST "'"); | |
| 2494 FREE_AND_NULL(str); | |
| 2495 } | |
| 2496 msg = xmlStrcat(msg, BAD_CAST ".\n"); | |
| 2497 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) == | |
| 2498 XML_ATTRIBUTE_NODE)) | |
| 2499 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL); | |
| 2500 else | |
| 2501 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL); | |
| 2502 FREE_AND_NULL(msg) | |
| 2503 } | |
| 2504 | |
| 2505 static const xmlChar * | |
| 2506 xmlSchemaFormatErrorNodeQName(xmlChar ** str, | |
| 2507 xmlSchemaNodeInfoPtr ni, | |
| 2508 xmlNodePtr node) | |
| 2509 { | |
| 2510 if (node != NULL) { | |
| 2511 if (node->ns != NULL) | |
| 2512 return (xmlSchemaFormatQName(str, node->ns->href, node->name)); | |
| 2513 else | |
| 2514 return (xmlSchemaFormatQName(str, NULL, node->name)); | |
| 2515 } else if (ni != NULL) | |
| 2516 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName)); | |
| 2517 return (NULL); | |
| 2518 } | |
| 2519 | |
| 2520 static void | |
| 2521 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt, | |
| 2522 xmlParserErrors error, | |
| 2523 xmlSchemaAttrInfoPtr ni, | |
| 2524 xmlNodePtr node) | |
| 2525 { | |
| 2526 xmlChar *msg = NULL, *str = NULL; | |
| 2527 | |
| 2528 xmlSchemaFormatNodeForError(&msg, actxt, node); | |
| 2529 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n"); | |
| 2530 xmlSchemaErr(actxt, error, node, (const char *) msg, | |
| 2531 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node), | |
| 2532 NULL); | |
| 2533 FREE_AND_NULL(str) | |
| 2534 FREE_AND_NULL(msg) | |
| 2535 } | |
| 2536 | |
| 2537 static void LIBXML_ATTR_FORMAT(5,0) | |
| 2538 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt, | |
| 2539 xmlParserErrors error, | |
| 2540 xmlNodePtr node, | |
| 2541 xmlSchemaTypePtr type ATTRIBUTE_UNUSED, | |
| 2542 const char *message, | |
| 2543 int nbval, | |
| 2544 int nbneg, | |
| 2545 xmlChar **values) | |
| 2546 { | |
| 2547 xmlChar *str = NULL, *msg = NULL; | |
| 2548 xmlChar *localName, *nsName; | |
| 2549 const xmlChar *cur, *end; | |
| 2550 int i; | |
| 2551 | |
| 2552 xmlSchemaFormatNodeForError(&msg, actxt, node); | |
| 2553 msg = xmlStrcat(msg, (const xmlChar *) message); | |
| 2554 msg = xmlStrcat(msg, BAD_CAST "."); | |
| 2555 /* | |
| 2556 * Note that is does not make sense to report that we have a | |
| 2557 * wildcard here, since the wildcard might be unfolded into | |
| 2558 * multiple transitions. | |
| 2559 */ | |
| 2560 if (nbval + nbneg > 0) { | |
| 2561 if (nbval + nbneg > 1) { | |
| 2562 str = xmlStrdup(BAD_CAST " Expected is one of ( "); | |
| 2563 } else | |
| 2564 str = xmlStrdup(BAD_CAST " Expected is ( "); | |
| 2565 nsName = NULL; | |
| 2566 | |
| 2567 for (i = 0; i < nbval + nbneg; i++) { | |
| 2568 cur = values[i]; | |
| 2569 if (cur == NULL) | |
| 2570 continue; | |
| 2571 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') && | |
| 2572 (cur[3] == ' ')) { | |
| 2573 cur += 4; | |
| 2574 str = xmlStrcat(str, BAD_CAST "##other"); | |
| 2575 } | |
| 2576 /* | |
| 2577 * Get the local name. | |
| 2578 */ | |
| 2579 localName = NULL; | |
| 2580 | |
| 2581 end = cur; | |
| 2582 if (*end == '*') { | |
| 2583 localName = xmlStrdup(BAD_CAST "*"); | |
| 2584 end++; | |
| 2585 } else { | |
| 2586 while ((*end != 0) && (*end != '|')) | |
| 2587 end++; | |
| 2588 localName = xmlStrncat(localName, BAD_CAST cur, end - cur); | |
| 2589 } | |
| 2590 if (*end != 0) { | |
| 2591 end++; | |
| 2592 /* | |
| 2593 * Skip "*|*" if they come with negated expressions, since | |
| 2594 * they represent the same negated wildcard. | |
| 2595 */ | |
| 2596 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) { | |
| 2597 /* | |
| 2598 * Get the namespace name. | |
| 2599 */ | |
| 2600 cur = end; | |
| 2601 if (*end == '*') { | |
| 2602 nsName = xmlStrdup(BAD_CAST "{*}"); | |
| 2603 } else { | |
| 2604 while (*end != 0) | |
| 2605 end++; | |
| 2606 | |
| 2607 if (i >= nbval) | |
| 2608 nsName = xmlStrdup(BAD_CAST "{##other:"); | |
| 2609 else | |
| 2610 nsName = xmlStrdup(BAD_CAST "{"); | |
| 2611 | |
| 2612 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur); | |
| 2613 nsName = xmlStrcat(nsName, BAD_CAST "}"); | |
| 2614 } | |
| 2615 str = xmlStrcat(str, BAD_CAST nsName); | |
| 2616 FREE_AND_NULL(nsName) | |
| 2617 } else { | |
| 2618 FREE_AND_NULL(localName); | |
| 2619 continue; | |
| 2620 } | |
| 2621 } | |
| 2622 str = xmlStrcat(str, BAD_CAST localName); | |
| 2623 FREE_AND_NULL(localName); | |
| 2624 | |
| 2625 if (i < nbval + nbneg -1) | |
| 2626 str = xmlStrcat(str, BAD_CAST ", "); | |
| 2627 } | |
| 2628 str = xmlStrcat(str, BAD_CAST " ).\n"); | |
| 2629 msg = xmlStrcat(msg, xmlEscapeFormatString(&str)); | |
| 2630 FREE_AND_NULL(str) | |
| 2631 } else | |
| 2632 msg = xmlStrcat(msg, BAD_CAST "\n"); | |
| 2633 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL); | |
| 2634 xmlFree(msg); | |
| 2635 } | |
| 2636 | |
| 2637 static void LIBXML_ATTR_FORMAT(8,0) | |
| 2638 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt, | |
| 2639 xmlParserErrors error, | |
| 2640 xmlNodePtr node, | |
| 2641 const xmlChar *value, | |
| 2642 unsigned long length, | |
| 2643 xmlSchemaTypePtr type, | |
| 2644 xmlSchemaFacetPtr facet, | |
| 2645 const char *message, | |
| 2646 const xmlChar *str1, | |
| 2647 const xmlChar *str2) | |
| 2648 { | |
| 2649 xmlChar *str = NULL, *msg = NULL; | |
| 2650 xmlSchemaTypeType facetType; | |
| 2651 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node); | |
| 2652 | |
| 2653 xmlSchemaFormatNodeForError(&msg, actxt, node); | |
| 2654 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) { | |
| 2655 facetType = XML_SCHEMA_FACET_ENUMERATION; | |
| 2656 /* | |
| 2657 * If enumerations are validated, one must not expect the | |
| 2658 * facet to be given. | |
| 2659 */ | |
| 2660 } else | |
| 2661 facetType = facet->type; | |
| 2662 msg = xmlStrcat(msg, BAD_CAST "["); | |
| 2663 msg = xmlStrcat(msg, BAD_CAST "facet '"); | |
| 2664 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType)); | |
| 2665 msg = xmlStrcat(msg, BAD_CAST "'] "); | |
| 2666 if (message == NULL) { | |
| 2667 /* | |
| 2668 * Use a default message. | |
| 2669 */ | |
| 2670 if ((facetType == XML_SCHEMA_FACET_LENGTH) || | |
| 2671 (facetType == XML_SCHEMA_FACET_MINLENGTH) || | |
| 2672 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) { | |
| 2673 | |
| 2674 char len[25], actLen[25]; | |
| 2675 | |
| 2676 /* FIXME, TODO: What is the max expected string length of the | |
| 2677 * this value? | |
| 2678 */ | |
| 2679 if (nodeType == XML_ATTRIBUTE_NODE) | |
| 2680 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%
s'; "); | |
| 2681 else | |
| 2682 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; "
); | |
| 2683 | |
| 2684 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet)); | |
| 2685 snprintf(actLen, 24, "%lu", length); | |
| 2686 | |
| 2687 if (facetType == XML_SCHEMA_FACET_LENGTH) | |
| 2688 msg = xmlStrcat(msg, | |
| 2689 BAD_CAST "this differs from the allowed length of '%s'.\n"); | |
| 2690 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH) | |
| 2691 msg = xmlStrcat(msg, | |
| 2692 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n"); | |
| 2693 else if (facetType == XML_SCHEMA_FACET_MINLENGTH) | |
| 2694 msg = xmlStrcat(msg, | |
| 2695 BAD_CAST "this underruns the allowed minimum length of '%s'.\n")
; | |
| 2696 | |
| 2697 if (nodeType == XML_ATTRIBUTE_NODE) | |
| 2698 xmlSchemaErr3(actxt, error, node, (const char *) msg, | |
| 2699 value, (const xmlChar *) actLen, (const xmlChar *) len); | |
| 2700 else | |
| 2701 xmlSchemaErr(actxt, error, node, (const char *) msg, | |
| 2702 (const xmlChar *) actLen, (const xmlChar *) len); | |
| 2703 | |
| 2704 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) { | |
| 2705 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element " | |
| 2706 "of the set {%s}.\n"); | |
| 2707 xmlSchemaErr(actxt, error, node, (const char *) msg, value, | |
| 2708 xmlSchemaFormatFacetEnumSet(actxt, &str, type)); | |
| 2709 } else if (facetType == XML_SCHEMA_FACET_PATTERN) { | |
| 2710 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted " | |
| 2711 "by the pattern '%s'.\n"); | |
| 2712 xmlSchemaErr(actxt, error, node, (const char *) msg, value, | |
| 2713 facet->value); | |
| 2714 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) { | |
| 2715 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the " | |
| 2716 "minimum value allowed ('%s').\n"); | |
| 2717 xmlSchemaErr(actxt, error, node, (const char *) msg, value, | |
| 2718 facet->value); | |
| 2719 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) { | |
| 2720 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the " | |
| 2721 "maximum value allowed ('%s').\n"); | |
| 2722 xmlSchemaErr(actxt, error, node, (const char *) msg, value, | |
| 2723 facet->value); | |
| 2724 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) { | |
| 2725 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than " | |
| 2726 "'%s'.\n"); | |
| 2727 xmlSchemaErr(actxt, error, node, (const char *) msg, value, | |
| 2728 facet->value); | |
| 2729 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) { | |
| 2730 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than " | |
| 2731 "'%s'.\n"); | |
| 2732 xmlSchemaErr(actxt, error, node, (const char *) msg, value, | |
| 2733 facet->value); | |
| 2734 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) { | |
| 2735 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more " | |
| 2736 "digits than are allowed ('%s').\n"); | |
| 2737 xmlSchemaErr(actxt, error, node, (const char*) msg, value, | |
| 2738 facet->value); | |
| 2739 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) { | |
| 2740 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional " | |
| 2741 "digits than are allowed ('%s').\n"); | |
| 2742 xmlSchemaErr(actxt, error, node, (const char*) msg, value, | |
| 2743 facet->value); | |
| 2744 } else if (nodeType == XML_ATTRIBUTE_NODE) { | |
| 2745 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n"
); | |
| 2746 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL); | |
| 2747 } else { | |
| 2748 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n"); | |
| 2749 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL); | |
| 2750 } | |
| 2751 } else { | |
| 2752 msg = xmlStrcat(msg, (const xmlChar *) message); | |
| 2753 msg = xmlStrcat(msg, BAD_CAST ".\n"); | |
| 2754 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2); | |
| 2755 } | |
| 2756 FREE_AND_NULL(str) | |
| 2757 xmlFree(msg); | |
| 2758 } | |
| 2759 | |
| 2760 #define VERROR(err, type, msg) \ | |
| 2761 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL); | |
| 2762 | |
| 2763 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg); | |
| 2764 | |
| 2765 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg); | |
| 2766 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg); | |
| 2767 | |
| 2768 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg); | |
| 2769 | |
| 2770 | |
| 2771 /** | |
| 2772 * xmlSchemaPMissingAttrErr: | |
| 2773 * @ctxt: the schema validation context | |
| 2774 * @ownerDes: the designation of the owner | |
| 2775 * @ownerName: the name of the owner | |
| 2776 * @ownerItem: the owner as a schema object | |
| 2777 * @ownerElem: the owner as an element node | |
| 2778 * @node: the parent element node of the missing attribute node | |
| 2779 * @type: the corresponding type of the attribute node | |
| 2780 * | |
| 2781 * Reports an illegal attribute. | |
| 2782 */ | |
| 2783 static void | |
| 2784 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt, | |
| 2785 xmlParserErrors error, | |
| 2786 xmlSchemaBasicItemPtr ownerItem, | |
| 2787 xmlNodePtr ownerElem, | |
| 2788 const char *name, | |
| 2789 const char *message) | |
| 2790 { | |
| 2791 xmlChar *des = NULL; | |
| 2792 | |
| 2793 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem); | |
| 2794 | |
| 2795 if (message != NULL) | |
| 2796 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAS
T message); | |
| 2797 else | |
| 2798 xmlSchemaPErr(ctxt, ownerElem, error, | |
| 2799 "%s: The attribute '%s' is required but missing.\n", | |
| 2800 BAD_CAST des, BAD_CAST name); | |
| 2801 FREE_AND_NULL(des); | |
| 2802 } | |
| 2803 | |
| 2804 | |
| 2805 /** | |
| 2806 * xmlSchemaPResCompAttrErr: | |
| 2807 * @ctxt: the schema validation context | |
| 2808 * @error: the error code | |
| 2809 * @ownerDes: the designation of the owner | |
| 2810 * @ownerItem: the owner as a schema object | |
| 2811 * @ownerElem: the owner as an element node | |
| 2812 * @name: the name of the attribute holding the QName | |
| 2813 * @refName: the referenced local name | |
| 2814 * @refURI: the referenced namespace URI | |
| 2815 * @message: optional message | |
| 2816 * | |
| 2817 * Used to report QName attribute values that failed to resolve | |
| 2818 * to schema components. | |
| 2819 */ | |
| 2820 static void | |
| 2821 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt, | |
| 2822 xmlParserErrors error, | |
| 2823 xmlSchemaBasicItemPtr ownerItem, | |
| 2824 xmlNodePtr ownerElem, | |
| 2825 const char *name, | |
| 2826 const xmlChar *refName, | |
| 2827 const xmlChar *refURI, | |
| 2828 xmlSchemaTypeType refType, | |
| 2829 const char *refTypeStr) | |
| 2830 { | |
| 2831 xmlChar *des = NULL, *strA = NULL; | |
| 2832 | |
| 2833 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem); | |
| 2834 if (refTypeStr == NULL) | |
| 2835 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType); | |
| 2836 xmlSchemaPErrExt(ctxt, ownerElem, error, | |
| 2837 NULL, NULL, NULL, | |
| 2838 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) " | |
| 2839 "%s.\n", BAD_CAST des, BAD_CAST name, | |
| 2840 xmlSchemaFormatQName(&strA, refURI, refName), | |
| 2841 BAD_CAST refTypeStr, NULL); | |
| 2842 FREE_AND_NULL(des) | |
| 2843 FREE_AND_NULL(strA) | |
| 2844 } | |
| 2845 | |
| 2846 /** | |
| 2847 * xmlSchemaPCustomAttrErr: | |
| 2848 * @ctxt: the schema parser context | |
| 2849 * @error: the error code | |
| 2850 * @ownerDes: the designation of the owner | |
| 2851 * @ownerItem: the owner as a schema object | |
| 2852 * @attr: the illegal attribute node | |
| 2853 * | |
| 2854 * Reports an illegal attribute during the parse. | |
| 2855 */ | |
| 2856 static void | |
| 2857 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt, | |
| 2858 xmlParserErrors error, | |
| 2859 xmlChar **ownerDes, | |
| 2860 xmlSchemaBasicItemPtr ownerItem, | |
| 2861 xmlAttrPtr attr, | |
| 2862 const char *msg) | |
| 2863 { | |
| 2864 xmlChar *des = NULL; | |
| 2865 | |
| 2866 if (ownerDes == NULL) | |
| 2867 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent); | |
| 2868 else if (*ownerDes == NULL) { | |
| 2869 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent); | |
| 2870 des = *ownerDes; | |
| 2871 } else | |
| 2872 des = *ownerDes; | |
| 2873 if (attr == NULL) { | |
| 2874 xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL, | |
| 2875 "%s, attribute '%s': %s.\n", | |
| 2876 BAD_CAST des, (const xmlChar *) "Unknown", | |
| 2877 (const xmlChar *) msg, NULL, NULL); | |
| 2878 } else { | |
| 2879 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL, | |
| 2880 "%s, attribute '%s': %s.\n", | |
| 2881 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL); | |
| 2882 } | |
| 2883 if (ownerDes == NULL) | |
| 2884 FREE_AND_NULL(des); | |
| 2885 } | |
| 2886 | |
| 2887 /** | |
| 2888 * xmlSchemaPIllegalAttrErr: | |
| 2889 * @ctxt: the schema parser context | |
| 2890 * @error: the error code | |
| 2891 * @ownerDes: the designation of the attribute's owner | |
| 2892 * @ownerItem: the attribute's owner item | |
| 2893 * @attr: the illegal attribute node | |
| 2894 * | |
| 2895 * Reports an illegal attribute during the parse. | |
| 2896 */ | |
| 2897 static void | |
| 2898 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt, | |
| 2899 xmlParserErrors error, | |
| 2900 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED, | |
| 2901 xmlAttrPtr attr) | |
| 2902 { | |
| 2903 xmlChar *strA = NULL, *strB = NULL; | |
| 2904 | |
| 2905 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent); | |
| 2906 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr, | |
| 2907 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA, | |
| 2908 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name), | |
| 2909 NULL, NULL); | |
| 2910 FREE_AND_NULL(strA); | |
| 2911 FREE_AND_NULL(strB); | |
| 2912 } | |
| 2913 | |
| 2914 /** | |
| 2915 * xmlSchemaPCustomErr: | |
| 2916 * @ctxt: the schema parser context | |
| 2917 * @error: the error code | |
| 2918 * @itemDes: the designation of the schema item | |
| 2919 * @item: the schema item | |
| 2920 * @itemElem: the node of the schema item | |
| 2921 * @message: the error message | |
| 2922 * @str1: an optional param for the error message | |
| 2923 * @str2: an optional param for the error message | |
| 2924 * @str3: an optional param for the error message | |
| 2925 * | |
| 2926 * Reports an error during parsing. | |
| 2927 */ | |
| 2928 static void LIBXML_ATTR_FORMAT(5,0) | |
| 2929 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt, | |
| 2930 xmlParserErrors error, | |
| 2931 xmlSchemaBasicItemPtr item, | |
| 2932 xmlNodePtr itemElem, | |
| 2933 const char *message, | |
| 2934 const xmlChar *str1, | |
| 2935 const xmlChar *str2, | |
| 2936 const xmlChar *str3) | |
| 2937 { | |
| 2938 xmlChar *des = NULL, *msg = NULL; | |
| 2939 | |
| 2940 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem); | |
| 2941 msg = xmlStrdup(BAD_CAST "%s: "); | |
| 2942 msg = xmlStrcat(msg, (const xmlChar *) message); | |
| 2943 msg = xmlStrcat(msg, BAD_CAST ".\n"); | |
| 2944 if ((itemElem == NULL) && (item != NULL)) | |
| 2945 itemElem = WXS_ITEM_NODE(item); | |
| 2946 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL, | |
| 2947 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL); | |
| 2948 FREE_AND_NULL(des); | |
| 2949 FREE_AND_NULL(msg); | |
| 2950 } | |
| 2951 | |
| 2952 /** | |
| 2953 * xmlSchemaPCustomErr: | |
| 2954 * @ctxt: the schema parser context | |
| 2955 * @error: the error code | |
| 2956 * @itemDes: the designation of the schema item | |
| 2957 * @item: the schema item | |
| 2958 * @itemElem: the node of the schema item | |
| 2959 * @message: the error message | |
| 2960 * @str1: the optional param for the error message | |
| 2961 * | |
| 2962 * Reports an error during parsing. | |
| 2963 */ | |
| 2964 static void LIBXML_ATTR_FORMAT(5,0) | |
| 2965 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt, | |
| 2966 xmlParserErrors error, | |
| 2967 xmlSchemaBasicItemPtr item, | |
| 2968 xmlNodePtr itemElem, | |
| 2969 const char *message, | |
| 2970 const xmlChar *str1) | |
| 2971 { | |
| 2972 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message, | |
| 2973 str1, NULL, NULL); | |
| 2974 } | |
| 2975 | |
| 2976 /** | |
| 2977 * xmlSchemaPAttrUseErr: | |
| 2978 * @ctxt: the schema parser context | |
| 2979 * @error: the error code | |
| 2980 * @itemDes: the designation of the schema type | |
| 2981 * @item: the schema type | |
| 2982 * @itemElem: the node of the schema type | |
| 2983 * @attr: the invalid schema attribute | |
| 2984 * @message: the error message | |
| 2985 * @str1: the optional param for the error message | |
| 2986 * | |
| 2987 * Reports an attribute use error during parsing. | |
| 2988 */ | |
| 2989 static void LIBXML_ATTR_FORMAT(6,0) | |
| 2990 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt, | |
| 2991 xmlParserErrors error, | |
| 2992 xmlNodePtr node, | |
| 2993 xmlSchemaBasicItemPtr ownerItem, | |
| 2994 const xmlSchemaAttributeUsePtr attruse, | |
| 2995 const char *message, | |
| 2996 const xmlChar *str1, const xmlChar *str2, | |
| 2997 const xmlChar *str3,const xmlChar *str4) | |
| 2998 { | |
| 2999 xmlChar *str = NULL, *msg = NULL; | |
| 3000 | |
| 3001 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL); | |
| 3002 msg = xmlStrcat(msg, BAD_CAST ", "); | |
| 3003 msg = xmlStrcat(msg, | |
| 3004 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL, | |
| 3005 WXS_BASIC_CAST attruse, NULL)); | |
| 3006 FREE_AND_NULL(str); | |
| 3007 msg = xmlStrcat(msg, BAD_CAST ": "); | |
| 3008 msg = xmlStrcat(msg, (const xmlChar *) message); | |
| 3009 msg = xmlStrcat(msg, BAD_CAST ".\n"); | |
| 3010 xmlSchemaErr4(ACTXT_CAST ctxt, error, node, | |
| 3011 (const char *) msg, str1, str2, str3, str4); | |
| 3012 xmlFree(msg); | |
| 3013 } | |
| 3014 | |
| 3015 /** | |
| 3016 * xmlSchemaPIllegalFacetAtomicErr: | |
| 3017 * @ctxt: the schema parser context | |
| 3018 * @error: the error code | |
| 3019 * @type: the schema type | |
| 3020 * @baseType: the base type of type | |
| 3021 * @facet: the illegal facet | |
| 3022 * | |
| 3023 * Reports an illegal facet for atomic simple types. | |
| 3024 */ | |
| 3025 static void | |
| 3026 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt, | |
| 3027 xmlParserErrors error, | |
| 3028 xmlSchemaTypePtr type, | |
| 3029 xmlSchemaTypePtr baseType, | |
| 3030 xmlSchemaFacetPtr facet) | |
| 3031 { | |
| 3032 xmlChar *des = NULL, *strT = NULL; | |
| 3033 | |
| 3034 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node); | |
| 3035 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL, | |
| 3036 "%s: The facet '%s' is not allowed on types derived from the " | |
| 3037 "type %s.\n", | |
| 3038 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type), | |
| 3039 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL)
, | |
| 3040 NULL, NULL); | |
| 3041 FREE_AND_NULL(des); | |
| 3042 FREE_AND_NULL(strT); | |
| 3043 } | |
| 3044 | |
| 3045 /** | |
| 3046 * xmlSchemaPIllegalFacetListUnionErr: | |
| 3047 * @ctxt: the schema parser context | |
| 3048 * @error: the error code | |
| 3049 * @itemDes: the designation of the schema item involved | |
| 3050 * @item: the schema item involved | |
| 3051 * @facet: the illegal facet | |
| 3052 * | |
| 3053 * Reports an illegal facet for <list> and <union>. | |
| 3054 */ | |
| 3055 static void | |
| 3056 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt, | |
| 3057 xmlParserErrors error, | |
| 3058 xmlSchemaTypePtr type, | |
| 3059 xmlSchemaFacetPtr facet) | |
| 3060 { | |
| 3061 xmlChar *des = NULL; | |
| 3062 | |
| 3063 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, | |
| 3064 type->node); | |
| 3065 xmlSchemaPErr(ctxt, type->node, error, | |
| 3066 "%s: The facet '%s' is not allowed.\n", | |
| 3067 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type)); | |
| 3068 FREE_AND_NULL(des); | |
| 3069 } | |
| 3070 | |
| 3071 /** | |
| 3072 * xmlSchemaPMutualExclAttrErr: | |
| 3073 * @ctxt: the schema validation context | |
| 3074 * @error: the error code | |
| 3075 * @elemDes: the designation of the parent element node | |
| 3076 * @attr: the bad attribute node | |
| 3077 * @type: the corresponding type of the attribute node | |
| 3078 * | |
| 3079 * Reports an illegal attribute. | |
| 3080 */ | |
| 3081 static void | |
| 3082 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt, | |
| 3083 xmlParserErrors error, | |
| 3084 xmlSchemaBasicItemPtr ownerItem, | |
| 3085 xmlAttrPtr attr, | |
| 3086 const char *name1, | |
| 3087 const char *name2) | |
| 3088 { | |
| 3089 xmlChar *des = NULL; | |
| 3090 | |
| 3091 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->par
ent); | |
| 3092 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL, | |
| 3093 "%s: The attributes '%s' and '%s' are mutually exclusive.\n", | |
| 3094 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL); | |
| 3095 FREE_AND_NULL(des); | |
| 3096 } | |
| 3097 | |
| 3098 /** | |
| 3099 * xmlSchemaPSimpleTypeErr: | |
| 3100 * @ctxt: the schema validation context | |
| 3101 * @error: the error code | |
| 3102 * @type: the type specifier | |
| 3103 * @ownerDes: the designation of the owner | |
| 3104 * @ownerItem: the schema object if existent | |
| 3105 * @node: the validated node | |
| 3106 * @value: the validated value | |
| 3107 * | |
| 3108 * Reports a simple type validation error. | |
| 3109 * TODO: Should this report the value of an element as well? | |
| 3110 */ | |
| 3111 static void LIBXML_ATTR_FORMAT(8,0) | |
| 3112 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt, | |
| 3113 xmlParserErrors error, | |
| 3114 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED, | |
| 3115 xmlNodePtr node, | |
| 3116 xmlSchemaTypePtr type, | |
| 3117 const char *expected, | |
| 3118 const xmlChar *value, | |
| 3119 const char *message, | |
| 3120 const xmlChar *str1, | |
| 3121 const xmlChar *str2) | |
| 3122 { | |
| 3123 xmlChar *msg = NULL; | |
| 3124 | |
| 3125 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node); | |
| 3126 if (message == NULL) { | |
| 3127 /* | |
| 3128 * Use default messages. | |
| 3129 */ | |
| 3130 if (type != NULL) { | |
| 3131 if (node->type == XML_ATTRIBUTE_NODE) | |
| 3132 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of "); | |
| 3133 else | |
| 3134 msg = xmlStrcat(msg, BAD_CAST "The character content is not a " | |
| 3135 "valid value of "); | |
| 3136 if (! xmlSchemaIsGlobalItem(type)) | |
| 3137 msg = xmlStrcat(msg, BAD_CAST "the local "); | |
| 3138 else | |
| 3139 msg = xmlStrcat(msg, BAD_CAST "the "); | |
| 3140 | |
| 3141 if (WXS_IS_ATOMIC(type)) | |
| 3142 msg = xmlStrcat(msg, BAD_CAST "atomic type"); | |
| 3143 else if (WXS_IS_LIST(type)) | |
| 3144 msg = xmlStrcat(msg, BAD_CAST "list type"); | |
| 3145 else if (WXS_IS_UNION(type)) | |
| 3146 msg = xmlStrcat(msg, BAD_CAST "union type"); | |
| 3147 | |
| 3148 if (xmlSchemaIsGlobalItem(type)) { | |
| 3149 xmlChar *str = NULL; | |
| 3150 msg = xmlStrcat(msg, BAD_CAST " '"); | |
| 3151 if (type->builtInType != 0) { | |
| 3152 msg = xmlStrcat(msg, BAD_CAST "xs:"); | |
| 3153 str = xmlStrdup(type->name); | |
| 3154 } else { | |
| 3155 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targ
etNamespace, type->name); | |
| 3156 if (!str) | |
| 3157 str = xmlStrdup(qName); | |
| 3158 } | |
| 3159 msg = xmlStrcat(msg, xmlEscapeFormatString(&str)); | |
| 3160 msg = xmlStrcat(msg, BAD_CAST "'."); | |
| 3161 FREE_AND_NULL(str); | |
| 3162 } | |
| 3163 } else { | |
| 3164 if (node->type == XML_ATTRIBUTE_NODE) | |
| 3165 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid."); | |
| 3166 else | |
| 3167 msg = xmlStrcat(msg, BAD_CAST "The character content is not " | |
| 3168 "valid."); | |
| 3169 } | |
| 3170 if (expected) { | |
| 3171 xmlChar *expectedEscaped = xmlCharStrdup(expected); | |
| 3172 msg = xmlStrcat(msg, BAD_CAST " Expected is '"); | |
| 3173 msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped)); | |
| 3174 FREE_AND_NULL(expectedEscaped); | |
| 3175 msg = xmlStrcat(msg, BAD_CAST "'.\n"); | |
| 3176 } else | |
| 3177 msg = xmlStrcat(msg, BAD_CAST "\n"); | |
| 3178 if (node->type == XML_ATTRIBUTE_NODE) | |
| 3179 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL); | |
| 3180 else | |
| 3181 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL); | |
| 3182 } else { | |
| 3183 msg = xmlStrcat(msg, BAD_CAST message); | |
| 3184 msg = xmlStrcat(msg, BAD_CAST ".\n"); | |
| 3185 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL, | |
| 3186 (const char*) msg, str1, str2, NULL, NULL, NULL); | |
| 3187 } | |
| 3188 /* Cleanup. */ | |
| 3189 FREE_AND_NULL(msg) | |
| 3190 } | |
| 3191 | |
| 3192 /** | |
| 3193 * xmlSchemaPContentErr: | |
| 3194 * @ctxt: the schema parser context | |
| 3195 * @error: the error code | |
| 3196 * @onwerDes: the designation of the holder of the content | |
| 3197 * @ownerItem: the owner item of the holder of the content | |
| 3198 * @ownerElem: the node of the holder of the content | |
| 3199 * @child: the invalid child node | |
| 3200 * @message: the optional error message | |
| 3201 * @content: the optional string describing the correct content | |
| 3202 * | |
| 3203 * Reports an error concerning the content of a schema element. | |
| 3204 */ | |
| 3205 static void | |
| 3206 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt, | |
| 3207 xmlParserErrors error, | |
| 3208 xmlSchemaBasicItemPtr ownerItem, | |
| 3209 xmlNodePtr ownerElem, | |
| 3210 xmlNodePtr child, | |
| 3211 const char *message, | |
| 3212 const char *content) | |
| 3213 { | |
| 3214 xmlChar *des = NULL; | |
| 3215 | |
| 3216 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem); | |
| 3217 if (message != NULL) | |
| 3218 xmlSchemaPErr2(ctxt, ownerElem, child, error, | |
| 3219 "%s: %s.\n", | |
| 3220 BAD_CAST des, BAD_CAST message); | |
| 3221 else { | |
| 3222 if (content != NULL) { | |
| 3223 xmlSchemaPErr2(ctxt, ownerElem, child, error, | |
| 3224 "%s: The content is not valid. Expected is %s.\n", | |
| 3225 BAD_CAST des, BAD_CAST content); | |
| 3226 } else { | |
| 3227 xmlSchemaPErr2(ctxt, ownerElem, child, error, | |
| 3228 "%s: The content is not valid.\n", | |
| 3229 BAD_CAST des, NULL); | |
| 3230 } | |
| 3231 } | |
| 3232 FREE_AND_NULL(des) | |
| 3233 } | |
| 3234 | |
| 3235 /************************************************************************ | |
| 3236 * * | |
| 3237 * Streamable error functions * | |
| 3238 * * | |
| 3239 ************************************************************************/ | |
| 3240 | |
| 3241 | |
| 3242 | |
| 3243 | |
| 3244 /************************************************************************ | |
| 3245 * * | |
| 3246 * Validation helper functions * | |
| 3247 * * | |
| 3248 ************************************************************************/ | |
| 3249 | |
| 3250 | |
| 3251 /************************************************************************ | |
| 3252 * * | |
| 3253 * Allocation functions * | |
| 3254 * * | |
| 3255 ************************************************************************/ | |
| 3256 | |
| 3257 /** | |
| 3258 * xmlSchemaNewSchemaForParserCtxt: | |
| 3259 * @ctxt: a schema validation context | |
| 3260 * | |
| 3261 * Allocate a new Schema structure. | |
| 3262 * | |
| 3263 * Returns the newly allocated structure or NULL in case or error | |
| 3264 */ | |
| 3265 static xmlSchemaPtr | |
| 3266 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt) | |
| 3267 { | |
| 3268 xmlSchemaPtr ret; | |
| 3269 | |
| 3270 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema)); | |
| 3271 if (ret == NULL) { | |
| 3272 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL); | |
| 3273 return (NULL); | |
| 3274 } | |
| 3275 memset(ret, 0, sizeof(xmlSchema)); | |
| 3276 ret->dict = ctxt->dict; | |
| 3277 xmlDictReference(ret->dict); | |
| 3278 | |
| 3279 return (ret); | |
| 3280 } | |
| 3281 | |
| 3282 /** | |
| 3283 * xmlSchemaNewFacet: | |
| 3284 * | |
| 3285 * Allocate a new Facet structure. | |
| 3286 * | |
| 3287 * Returns the newly allocated structure or NULL in case or error | |
| 3288 */ | |
| 3289 xmlSchemaFacetPtr | |
| 3290 xmlSchemaNewFacet(void) | |
| 3291 { | |
| 3292 xmlSchemaFacetPtr ret; | |
| 3293 | |
| 3294 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet)); | |
| 3295 if (ret == NULL) { | |
| 3296 return (NULL); | |
| 3297 } | |
| 3298 memset(ret, 0, sizeof(xmlSchemaFacet)); | |
| 3299 | |
| 3300 return (ret); | |
| 3301 } | |
| 3302 | |
| 3303 /** | |
| 3304 * xmlSchemaNewAnnot: | |
| 3305 * @ctxt: a schema validation context | |
| 3306 * @node: a node | |
| 3307 * | |
| 3308 * Allocate a new annotation structure. | |
| 3309 * | |
| 3310 * Returns the newly allocated structure or NULL in case or error | |
| 3311 */ | |
| 3312 static xmlSchemaAnnotPtr | |
| 3313 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) | |
| 3314 { | |
| 3315 xmlSchemaAnnotPtr ret; | |
| 3316 | |
| 3317 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot)); | |
| 3318 if (ret == NULL) { | |
| 3319 xmlSchemaPErrMemory(ctxt, "allocating annotation", node); | |
| 3320 return (NULL); | |
| 3321 } | |
| 3322 memset(ret, 0, sizeof(xmlSchemaAnnot)); | |
| 3323 ret->content = node; | |
| 3324 return (ret); | |
| 3325 } | |
| 3326 | |
| 3327 static xmlSchemaItemListPtr | |
| 3328 xmlSchemaItemListCreate(void) | |
| 3329 { | |
| 3330 xmlSchemaItemListPtr ret; | |
| 3331 | |
| 3332 ret = xmlMalloc(sizeof(xmlSchemaItemList)); | |
| 3333 if (ret == NULL) { | |
| 3334 xmlSchemaPErrMemory(NULL, | |
| 3335 "allocating an item list structure", NULL); | |
| 3336 return (NULL); | |
| 3337 } | |
| 3338 memset(ret, 0, sizeof(xmlSchemaItemList)); | |
| 3339 return (ret); | |
| 3340 } | |
| 3341 | |
| 3342 static void | |
| 3343 xmlSchemaItemListClear(xmlSchemaItemListPtr list) | |
| 3344 { | |
| 3345 if (list->items != NULL) { | |
| 3346 xmlFree(list->items); | |
| 3347 list->items = NULL; | |
| 3348 } | |
| 3349 list->nbItems = 0; | |
| 3350 list->sizeItems = 0; | |
| 3351 } | |
| 3352 | |
| 3353 static int | |
| 3354 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item) | |
| 3355 { | |
| 3356 if (list->items == NULL) { | |
| 3357 list->items = (void **) xmlMalloc( | |
| 3358 20 * sizeof(void *)); | |
| 3359 if (list->items == NULL) { | |
| 3360 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); | |
| 3361 return(-1); | |
| 3362 } | |
| 3363 list->sizeItems = 20; | |
| 3364 } else if (list->sizeItems <= list->nbItems) { | |
| 3365 list->sizeItems *= 2; | |
| 3366 list->items = (void **) xmlRealloc(list->items, | |
| 3367 list->sizeItems * sizeof(void *)); | |
| 3368 if (list->items == NULL) { | |
| 3369 xmlSchemaPErrMemory(NULL, "growing item list", NULL); | |
| 3370 list->sizeItems = 0; | |
| 3371 return(-1); | |
| 3372 } | |
| 3373 } | |
| 3374 list->items[list->nbItems++] = item; | |
| 3375 return(0); | |
| 3376 } | |
| 3377 | |
| 3378 static int | |
| 3379 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list, | |
| 3380 int initialSize, | |
| 3381 void *item) | |
| 3382 { | |
| 3383 if (list->items == NULL) { | |
| 3384 if (initialSize <= 0) | |
| 3385 initialSize = 1; | |
| 3386 list->items = (void **) xmlMalloc( | |
| 3387 initialSize * sizeof(void *)); | |
| 3388 if (list->items == NULL) { | |
| 3389 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); | |
| 3390 return(-1); | |
| 3391 } | |
| 3392 list->sizeItems = initialSize; | |
| 3393 } else if (list->sizeItems <= list->nbItems) { | |
| 3394 list->sizeItems *= 2; | |
| 3395 list->items = (void **) xmlRealloc(list->items, | |
| 3396 list->sizeItems * sizeof(void *)); | |
| 3397 if (list->items == NULL) { | |
| 3398 xmlSchemaPErrMemory(NULL, "growing item list", NULL); | |
| 3399 list->sizeItems = 0; | |
| 3400 return(-1); | |
| 3401 } | |
| 3402 } | |
| 3403 list->items[list->nbItems++] = item; | |
| 3404 return(0); | |
| 3405 } | |
| 3406 | |
| 3407 static int | |
| 3408 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx) | |
| 3409 { | |
| 3410 if (list->items == NULL) { | |
| 3411 list->items = (void **) xmlMalloc( | |
| 3412 20 * sizeof(void *)); | |
| 3413 if (list->items == NULL) { | |
| 3414 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); | |
| 3415 return(-1); | |
| 3416 } | |
| 3417 list->sizeItems = 20; | |
| 3418 } else if (list->sizeItems <= list->nbItems) { | |
| 3419 list->sizeItems *= 2; | |
| 3420 list->items = (void **) xmlRealloc(list->items, | |
| 3421 list->sizeItems * sizeof(void *)); | |
| 3422 if (list->items == NULL) { | |
| 3423 xmlSchemaPErrMemory(NULL, "growing item list", NULL); | |
| 3424 list->sizeItems = 0; | |
| 3425 return(-1); | |
| 3426 } | |
| 3427 } | |
| 3428 /* | |
| 3429 * Just append if the index is greater/equal than the item count. | |
| 3430 */ | |
| 3431 if (idx >= list->nbItems) { | |
| 3432 list->items[list->nbItems++] = item; | |
| 3433 } else { | |
| 3434 int i; | |
| 3435 for (i = list->nbItems; i > idx; i--) | |
| 3436 list->items[i] = list->items[i-1]; | |
| 3437 list->items[idx] = item; | |
| 3438 list->nbItems++; | |
| 3439 } | |
| 3440 return(0); | |
| 3441 } | |
| 3442 | |
| 3443 #if 0 /* enable if ever needed */ | |
| 3444 static int | |
| 3445 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list, | |
| 3446 int initialSize, | |
| 3447 void *item, | |
| 3448 int idx) | |
| 3449 { | |
| 3450 if (list->items == NULL) { | |
| 3451 if (initialSize <= 0) | |
| 3452 initialSize = 1; | |
| 3453 list->items = (void **) xmlMalloc( | |
| 3454 initialSize * sizeof(void *)); | |
| 3455 if (list->items == NULL) { | |
| 3456 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); | |
| 3457 return(-1); | |
| 3458 } | |
| 3459 list->sizeItems = initialSize; | |
| 3460 } else if (list->sizeItems <= list->nbItems) { | |
| 3461 list->sizeItems *= 2; | |
| 3462 list->items = (void **) xmlRealloc(list->items, | |
| 3463 list->sizeItems * sizeof(void *)); | |
| 3464 if (list->items == NULL) { | |
| 3465 xmlSchemaPErrMemory(NULL, "growing item list", NULL); | |
| 3466 list->sizeItems = 0; | |
| 3467 return(-1); | |
| 3468 } | |
| 3469 } | |
| 3470 /* | |
| 3471 * Just append if the index is greater/equal than the item count. | |
| 3472 */ | |
| 3473 if (idx >= list->nbItems) { | |
| 3474 list->items[list->nbItems++] = item; | |
| 3475 } else { | |
| 3476 int i; | |
| 3477 for (i = list->nbItems; i > idx; i--) | |
| 3478 list->items[i] = list->items[i-1]; | |
| 3479 list->items[idx] = item; | |
| 3480 list->nbItems++; | |
| 3481 } | |
| 3482 return(0); | |
| 3483 } | |
| 3484 #endif | |
| 3485 | |
| 3486 static int | |
| 3487 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx) | |
| 3488 { | |
| 3489 int i; | |
| 3490 if ((list->items == NULL) || (idx >= list->nbItems)) { | |
| 3491 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, " | |
| 3492 "index error.\n"); | |
| 3493 return(-1); | |
| 3494 } | |
| 3495 | |
| 3496 if (list->nbItems == 1) { | |
| 3497 /* TODO: Really free the list? */ | |
| 3498 xmlFree(list->items); | |
| 3499 list->items = NULL; | |
| 3500 list->nbItems = 0; | |
| 3501 list->sizeItems = 0; | |
| 3502 } else if (list->nbItems -1 == idx) { | |
| 3503 list->nbItems--; | |
| 3504 } else { | |
| 3505 for (i = idx; i < list->nbItems -1; i++) | |
| 3506 list->items[i] = list->items[i+1]; | |
| 3507 list->nbItems--; | |
| 3508 } | |
| 3509 return(0); | |
| 3510 } | |
| 3511 | |
| 3512 /** | |
| 3513 * xmlSchemaItemListFree: | |
| 3514 * @annot: a schema type structure | |
| 3515 * | |
| 3516 * Deallocate a annotation structure | |
| 3517 */ | |
| 3518 static void | |
| 3519 xmlSchemaItemListFree(xmlSchemaItemListPtr list) | |
| 3520 { | |
| 3521 if (list == NULL) | |
| 3522 return; | |
| 3523 if (list->items != NULL) | |
| 3524 xmlFree(list->items); | |
| 3525 xmlFree(list); | |
| 3526 } | |
| 3527 | |
| 3528 static void | |
| 3529 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket) | |
| 3530 { | |
| 3531 if (bucket == NULL) | |
| 3532 return; | |
| 3533 if (bucket->globals != NULL) { | |
| 3534 xmlSchemaComponentListFree(bucket->globals); | |
| 3535 xmlSchemaItemListFree(bucket->globals); | |
| 3536 } | |
| 3537 if (bucket->locals != NULL) { | |
| 3538 xmlSchemaComponentListFree(bucket->locals); | |
| 3539 xmlSchemaItemListFree(bucket->locals); | |
| 3540 } | |
| 3541 if (bucket->relations != NULL) { | |
| 3542 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations; | |
| 3543 do { | |
| 3544 prev = cur; | |
| 3545 cur = cur->next; | |
| 3546 xmlFree(prev); | |
| 3547 } while (cur != NULL); | |
| 3548 } | |
| 3549 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) { | |
| 3550 xmlFreeDoc(bucket->doc); | |
| 3551 } | |
| 3552 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) { | |
| 3553 if (WXS_IMPBUCKET(bucket)->schema != NULL) | |
| 3554 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema); | |
| 3555 } | |
| 3556 xmlFree(bucket); | |
| 3557 } | |
| 3558 | |
| 3559 static xmlSchemaBucketPtr | |
| 3560 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt, | |
| 3561 int type, const xmlChar *targetNamespace) | |
| 3562 { | |
| 3563 xmlSchemaBucketPtr ret; | |
| 3564 int size; | |
| 3565 xmlSchemaPtr mainSchema; | |
| 3566 | |
| 3567 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) { | |
| 3568 PERROR_INT("xmlSchemaBucketCreate", | |
| 3569 "no main schema on constructor"); | |
| 3570 return(NULL); | |
| 3571 } | |
| 3572 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema; | |
| 3573 /* Create the schema bucket. */ | |
| 3574 if (WXS_IS_BUCKET_INCREDEF(type)) | |
| 3575 size = sizeof(xmlSchemaInclude); | |
| 3576 else | |
| 3577 size = sizeof(xmlSchemaImport); | |
| 3578 ret = (xmlSchemaBucketPtr) xmlMalloc(size); | |
| 3579 if (ret == NULL) { | |
| 3580 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL); | |
| 3581 return(NULL); | |
| 3582 } | |
| 3583 memset(ret, 0, size); | |
| 3584 ret->targetNamespace = targetNamespace; | |
| 3585 ret->type = type; | |
| 3586 ret->globals = xmlSchemaItemListCreate(); | |
| 3587 if (ret->globals == NULL) { | |
| 3588 xmlFree(ret); | |
| 3589 return(NULL); | |
| 3590 } | |
| 3591 ret->locals = xmlSchemaItemListCreate(); | |
| 3592 if (ret->locals == NULL) { | |
| 3593 xmlFree(ret); | |
| 3594 return(NULL); | |
| 3595 } | |
| 3596 /* | |
| 3597 * The following will assure that only the first bucket is marked as | |
| 3598 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema. | |
| 3599 * For each following import buckets an xmlSchema will be created. | |
| 3600 * An xmlSchema will be created for every distinct targetNamespace. | |
| 3601 * We assign the targetNamespace to the schemata here. | |
| 3602 */ | |
| 3603 if (! WXS_HAS_BUCKETS(pctxt)) { | |
| 3604 if (WXS_IS_BUCKET_INCREDEF(type)) { | |
| 3605 PERROR_INT("xmlSchemaBucketCreate", | |
| 3606 "first bucket but it's an include or redefine"); | |
| 3607 xmlSchemaBucketFree(ret); | |
| 3608 return(NULL); | |
| 3609 } | |
| 3610 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */ | |
| 3611 ret->type = XML_SCHEMA_SCHEMA_MAIN; | |
| 3612 /* Point to the *main* schema. */ | |
| 3613 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret; | |
| 3614 WXS_IMPBUCKET(ret)->schema = mainSchema; | |
| 3615 /* | |
| 3616 * Ensure that the main schema gets a targetNamespace. | |
| 3617 */ | |
| 3618 mainSchema->targetNamespace = targetNamespace; | |
| 3619 } else { | |
| 3620 if (type == XML_SCHEMA_SCHEMA_MAIN) { | |
| 3621 PERROR_INT("xmlSchemaBucketCreate", | |
| 3622 "main bucket but it's not the first one"); | |
| 3623 xmlSchemaBucketFree(ret); | |
| 3624 return(NULL); | |
| 3625 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) { | |
| 3626 /* | |
| 3627 * Create a schema for imports and assign the | |
| 3628 * targetNamespace. | |
| 3629 */ | |
| 3630 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt); | |
| 3631 if (WXS_IMPBUCKET(ret)->schema == NULL) { | |
| 3632 xmlSchemaBucketFree(ret); | |
| 3633 return(NULL); | |
| 3634 } | |
| 3635 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace; | |
| 3636 } | |
| 3637 } | |
| 3638 if (WXS_IS_BUCKET_IMPMAIN(type)) { | |
| 3639 int res; | |
| 3640 /* | |
| 3641 * Imports go into the "schemasImports" slot of the main *schema*. | |
| 3642 * Note that we create an import entry for the main schema as well; i.e., | |
| 3643 * even if there's only one schema, we'll get an import. | |
| 3644 */ | |
| 3645 if (mainSchema->schemasImports == NULL) { | |
| 3646 mainSchema->schemasImports = xmlHashCreateDict(5, | |
| 3647 WXS_CONSTRUCTOR(pctxt)->dict); | |
| 3648 if (mainSchema->schemasImports == NULL) { | |
| 3649 xmlSchemaBucketFree(ret); | |
| 3650 return(NULL); | |
| 3651 } | |
| 3652 } | |
| 3653 if (targetNamespace == NULL) | |
| 3654 res = xmlHashAddEntry(mainSchema->schemasImports, | |
| 3655 XML_SCHEMAS_NO_NAMESPACE, ret); | |
| 3656 else | |
| 3657 res = xmlHashAddEntry(mainSchema->schemasImports, | |
| 3658 targetNamespace, ret); | |
| 3659 if (res != 0) { | |
| 3660 PERROR_INT("xmlSchemaBucketCreate", | |
| 3661 "failed to add the schema bucket to the hash"); | |
| 3662 xmlSchemaBucketFree(ret); | |
| 3663 return(NULL); | |
| 3664 } | |
| 3665 } else { | |
| 3666 /* Set the @ownerImport of an include bucket. */ | |
| 3667 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type)) | |
| 3668 WXS_INCBUCKET(ret)->ownerImport = | |
| 3669 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket); | |
| 3670 else | |
| 3671 WXS_INCBUCKET(ret)->ownerImport = | |
| 3672 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport; | |
| 3673 | |
| 3674 /* Includes got into the "includes" slot of the *main* schema. */ | |
| 3675 if (mainSchema->includes == NULL) { | |
| 3676 mainSchema->includes = xmlSchemaItemListCreate(); | |
| 3677 if (mainSchema->includes == NULL) { | |
| 3678 xmlSchemaBucketFree(ret); | |
| 3679 return(NULL); | |
| 3680 } | |
| 3681 } | |
| 3682 xmlSchemaItemListAdd(mainSchema->includes, ret); | |
| 3683 } | |
| 3684 /* | |
| 3685 * Add to list of all buckets; this is used for lookup | |
| 3686 * during schema construction time only. | |
| 3687 */ | |
| 3688 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1) | |
| 3689 return(NULL); | |
| 3690 return(ret); | |
| 3691 } | |
| 3692 | |
| 3693 static int | |
| 3694 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item) | |
| 3695 { | |
| 3696 if (*list == NULL) { | |
| 3697 *list = xmlSchemaItemListCreate(); | |
| 3698 if (*list == NULL) | |
| 3699 return(-1); | |
| 3700 } | |
| 3701 xmlSchemaItemListAddSize(*list, initialSize, item); | |
| 3702 return(0); | |
| 3703 } | |
| 3704 | |
| 3705 /** | |
| 3706 * xmlSchemaFreeAnnot: | |
| 3707 * @annot: a schema type structure | |
| 3708 * | |
| 3709 * Deallocate a annotation structure | |
| 3710 */ | |
| 3711 static void | |
| 3712 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot) | |
| 3713 { | |
| 3714 if (annot == NULL) | |
| 3715 return; | |
| 3716 if (annot->next == NULL) { | |
| 3717 xmlFree(annot); | |
| 3718 } else { | |
| 3719 xmlSchemaAnnotPtr prev; | |
| 3720 | |
| 3721 do { | |
| 3722 prev = annot; | |
| 3723 annot = annot->next; | |
| 3724 xmlFree(prev); | |
| 3725 } while (annot != NULL); | |
| 3726 } | |
| 3727 } | |
| 3728 | |
| 3729 /** | |
| 3730 * xmlSchemaFreeNotation: | |
| 3731 * @schema: a schema notation structure | |
| 3732 * | |
| 3733 * Deallocate a Schema Notation structure. | |
| 3734 */ | |
| 3735 static void | |
| 3736 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota) | |
| 3737 { | |
| 3738 if (nota == NULL) | |
| 3739 return; | |
| 3740 xmlFree(nota); | |
| 3741 } | |
| 3742 | |
| 3743 /** | |
| 3744 * xmlSchemaFreeAttribute: | |
| 3745 * @attr: an attribute declaration | |
| 3746 * | |
| 3747 * Deallocates an attribute declaration structure. | |
| 3748 */ | |
| 3749 static void | |
| 3750 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr) | |
| 3751 { | |
| 3752 if (attr == NULL) | |
| 3753 return; | |
| 3754 if (attr->annot != NULL) | |
| 3755 xmlSchemaFreeAnnot(attr->annot); | |
| 3756 if (attr->defVal != NULL) | |
| 3757 xmlSchemaFreeValue(attr->defVal); | |
| 3758 xmlFree(attr); | |
| 3759 } | |
| 3760 | |
| 3761 /** | |
| 3762 * xmlSchemaFreeAttributeUse: | |
| 3763 * @use: an attribute use | |
| 3764 * | |
| 3765 * Deallocates an attribute use structure. | |
| 3766 */ | |
| 3767 static void | |
| 3768 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use) | |
| 3769 { | |
| 3770 if (use == NULL) | |
| 3771 return; | |
| 3772 if (use->annot != NULL) | |
| 3773 xmlSchemaFreeAnnot(use->annot); | |
| 3774 if (use->defVal != NULL) | |
| 3775 xmlSchemaFreeValue(use->defVal); | |
| 3776 xmlFree(use); | |
| 3777 } | |
| 3778 | |
| 3779 /** | |
| 3780 * xmlSchemaFreeAttributeUseProhib: | |
| 3781 * @prohib: an attribute use prohibition | |
| 3782 * | |
| 3783 * Deallocates an attribute use structure. | |
| 3784 */ | |
| 3785 static void | |
| 3786 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib) | |
| 3787 { | |
| 3788 if (prohib == NULL) | |
| 3789 return; | |
| 3790 xmlFree(prohib); | |
| 3791 } | |
| 3792 | |
| 3793 /** | |
| 3794 * xmlSchemaFreeWildcardNsSet: | |
| 3795 * set: a schema wildcard namespace | |
| 3796 * | |
| 3797 * Deallocates a list of wildcard constraint structures. | |
| 3798 */ | |
| 3799 static void | |
| 3800 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set) | |
| 3801 { | |
| 3802 xmlSchemaWildcardNsPtr next; | |
| 3803 | |
| 3804 while (set != NULL) { | |
| 3805 next = set->next; | |
| 3806 xmlFree(set); | |
| 3807 set = next; | |
| 3808 } | |
| 3809 } | |
| 3810 | |
| 3811 /** | |
| 3812 * xmlSchemaFreeWildcard: | |
| 3813 * @wildcard: a wildcard structure | |
| 3814 * | |
| 3815 * Deallocates a wildcard structure. | |
| 3816 */ | |
| 3817 void | |
| 3818 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard) | |
| 3819 { | |
| 3820 if (wildcard == NULL) | |
| 3821 return; | |
| 3822 if (wildcard->annot != NULL) | |
| 3823 xmlSchemaFreeAnnot(wildcard->annot); | |
| 3824 if (wildcard->nsSet != NULL) | |
| 3825 xmlSchemaFreeWildcardNsSet(wildcard->nsSet); | |
| 3826 if (wildcard->negNsSet != NULL) | |
| 3827 xmlFree(wildcard->negNsSet); | |
| 3828 xmlFree(wildcard); | |
| 3829 } | |
| 3830 | |
| 3831 /** | |
| 3832 * xmlSchemaFreeAttributeGroup: | |
| 3833 * @schema: a schema attribute group structure | |
| 3834 * | |
| 3835 * Deallocate a Schema Attribute Group structure. | |
| 3836 */ | |
| 3837 static void | |
| 3838 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr) | |
| 3839 { | |
| 3840 if (attrGr == NULL) | |
| 3841 return; | |
| 3842 if (attrGr->annot != NULL) | |
| 3843 xmlSchemaFreeAnnot(attrGr->annot); | |
| 3844 if (attrGr->attrUses != NULL) | |
| 3845 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses); | |
| 3846 xmlFree(attrGr); | |
| 3847 } | |
| 3848 | |
| 3849 /** | |
| 3850 * xmlSchemaFreeQNameRef: | |
| 3851 * @item: a QName reference structure | |
| 3852 * | |
| 3853 * Deallocatea a QName reference structure. | |
| 3854 */ | |
| 3855 static void | |
| 3856 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item) | |
| 3857 { | |
| 3858 xmlFree(item); | |
| 3859 } | |
| 3860 | |
| 3861 /** | |
| 3862 * xmlSchemaFreeTypeLinkList: | |
| 3863 * @alink: a type link | |
| 3864 * | |
| 3865 * Deallocate a list of types. | |
| 3866 */ | |
| 3867 static void | |
| 3868 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link) | |
| 3869 { | |
| 3870 xmlSchemaTypeLinkPtr next; | |
| 3871 | |
| 3872 while (link != NULL) { | |
| 3873 next = link->next; | |
| 3874 xmlFree(link); | |
| 3875 link = next; | |
| 3876 } | |
| 3877 } | |
| 3878 | |
| 3879 static void | |
| 3880 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto) | |
| 3881 { | |
| 3882 xmlSchemaIDCStateObjPtr next; | |
| 3883 while (sto != NULL) { | |
| 3884 next = sto->next; | |
| 3885 if (sto->history != NULL) | |
| 3886 xmlFree(sto->history); | |
| 3887 if (sto->xpathCtxt != NULL) | |
| 3888 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt); | |
| 3889 xmlFree(sto); | |
| 3890 sto = next; | |
| 3891 } | |
| 3892 } | |
| 3893 | |
| 3894 /** | |
| 3895 * xmlSchemaFreeIDC: | |
| 3896 * @idc: a identity-constraint definition | |
| 3897 * | |
| 3898 * Deallocates an identity-constraint definition. | |
| 3899 */ | |
| 3900 static void | |
| 3901 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef) | |
| 3902 { | |
| 3903 xmlSchemaIDCSelectPtr cur, prev; | |
| 3904 | |
| 3905 if (idcDef == NULL) | |
| 3906 return; | |
| 3907 if (idcDef->annot != NULL) | |
| 3908 xmlSchemaFreeAnnot(idcDef->annot); | |
| 3909 /* Selector */ | |
| 3910 if (idcDef->selector != NULL) { | |
| 3911 if (idcDef->selector->xpathComp != NULL) | |
| 3912 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp); | |
| 3913 xmlFree(idcDef->selector); | |
| 3914 } | |
| 3915 /* Fields */ | |
| 3916 if (idcDef->fields != NULL) { | |
| 3917 cur = idcDef->fields; | |
| 3918 do { | |
| 3919 prev = cur; | |
| 3920 cur = cur->next; | |
| 3921 if (prev->xpathComp != NULL) | |
| 3922 xmlFreePattern((xmlPatternPtr) prev->xpathComp); | |
| 3923 xmlFree(prev); | |
| 3924 } while (cur != NULL); | |
| 3925 } | |
| 3926 xmlFree(idcDef); | |
| 3927 } | |
| 3928 | |
| 3929 /** | |
| 3930 * xmlSchemaFreeElement: | |
| 3931 * @schema: a schema element structure | |
| 3932 * | |
| 3933 * Deallocate a Schema Element structure. | |
| 3934 */ | |
| 3935 static void | |
| 3936 xmlSchemaFreeElement(xmlSchemaElementPtr elem) | |
| 3937 { | |
| 3938 if (elem == NULL) | |
| 3939 return; | |
| 3940 if (elem->annot != NULL) | |
| 3941 xmlSchemaFreeAnnot(elem->annot); | |
| 3942 if (elem->contModel != NULL) | |
| 3943 xmlRegFreeRegexp(elem->contModel); | |
| 3944 if (elem->defVal != NULL) | |
| 3945 xmlSchemaFreeValue(elem->defVal); | |
| 3946 xmlFree(elem); | |
| 3947 } | |
| 3948 | |
| 3949 /** | |
| 3950 * xmlSchemaFreeFacet: | |
| 3951 * @facet: a schema facet structure | |
| 3952 * | |
| 3953 * Deallocate a Schema Facet structure. | |
| 3954 */ | |
| 3955 void | |
| 3956 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet) | |
| 3957 { | |
| 3958 if (facet == NULL) | |
| 3959 return; | |
| 3960 if (facet->val != NULL) | |
| 3961 xmlSchemaFreeValue(facet->val); | |
| 3962 if (facet->regexp != NULL) | |
| 3963 xmlRegFreeRegexp(facet->regexp); | |
| 3964 if (facet->annot != NULL) | |
| 3965 xmlSchemaFreeAnnot(facet->annot); | |
| 3966 xmlFree(facet); | |
| 3967 } | |
| 3968 | |
| 3969 /** | |
| 3970 * xmlSchemaFreeType: | |
| 3971 * @type: a schema type structure | |
| 3972 * | |
| 3973 * Deallocate a Schema Type structure. | |
| 3974 */ | |
| 3975 void | |
| 3976 xmlSchemaFreeType(xmlSchemaTypePtr type) | |
| 3977 { | |
| 3978 if (type == NULL) | |
| 3979 return; | |
| 3980 if (type->annot != NULL) | |
| 3981 xmlSchemaFreeAnnot(type->annot); | |
| 3982 if (type->facets != NULL) { | |
| 3983 xmlSchemaFacetPtr facet, next; | |
| 3984 | |
| 3985 facet = type->facets; | |
| 3986 while (facet != NULL) { | |
| 3987 next = facet->next; | |
| 3988 xmlSchemaFreeFacet(facet); | |
| 3989 facet = next; | |
| 3990 } | |
| 3991 } | |
| 3992 if (type->attrUses != NULL) | |
| 3993 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses); | |
| 3994 if (type->memberTypes != NULL) | |
| 3995 xmlSchemaFreeTypeLinkList(type->memberTypes); | |
| 3996 if (type->facetSet != NULL) { | |
| 3997 xmlSchemaFacetLinkPtr next, link; | |
| 3998 | |
| 3999 link = type->facetSet; | |
| 4000 do { | |
| 4001 next = link->next; | |
| 4002 xmlFree(link); | |
| 4003 link = next; | |
| 4004 } while (link != NULL); | |
| 4005 } | |
| 4006 if (type->contModel != NULL) | |
| 4007 xmlRegFreeRegexp(type->contModel); | |
| 4008 xmlFree(type); | |
| 4009 } | |
| 4010 | |
| 4011 /** | |
| 4012 * xmlSchemaFreeModelGroupDef: | |
| 4013 * @item: a schema model group definition | |
| 4014 * | |
| 4015 * Deallocates a schema model group definition. | |
| 4016 */ | |
| 4017 static void | |
| 4018 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item) | |
| 4019 { | |
| 4020 if (item->annot != NULL) | |
| 4021 xmlSchemaFreeAnnot(item->annot); | |
| 4022 xmlFree(item); | |
| 4023 } | |
| 4024 | |
| 4025 /** | |
| 4026 * xmlSchemaFreeModelGroup: | |
| 4027 * @item: a schema model group | |
| 4028 * | |
| 4029 * Deallocates a schema model group structure. | |
| 4030 */ | |
| 4031 static void | |
| 4032 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item) | |
| 4033 { | |
| 4034 if (item->annot != NULL) | |
| 4035 xmlSchemaFreeAnnot(item->annot); | |
| 4036 xmlFree(item); | |
| 4037 } | |
| 4038 | |
| 4039 static void | |
| 4040 xmlSchemaComponentListFree(xmlSchemaItemListPtr list) | |
| 4041 { | |
| 4042 if ((list == NULL) || (list->nbItems == 0)) | |
| 4043 return; | |
| 4044 { | |
| 4045 xmlSchemaTreeItemPtr item; | |
| 4046 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items; | |
| 4047 int i; | |
| 4048 | |
| 4049 for (i = 0; i < list->nbItems; i++) { | |
| 4050 item = items[i]; | |
| 4051 if (item == NULL) | |
| 4052 continue; | |
| 4053 switch (item->type) { | |
| 4054 case XML_SCHEMA_TYPE_SIMPLE: | |
| 4055 case XML_SCHEMA_TYPE_COMPLEX: | |
| 4056 xmlSchemaFreeType((xmlSchemaTypePtr) item); | |
| 4057 break; | |
| 4058 case XML_SCHEMA_TYPE_ATTRIBUTE: | |
| 4059 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item); | |
| 4060 break; | |
| 4061 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: | |
| 4062 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item); | |
| 4063 break; | |
| 4064 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB: | |
| 4065 xmlSchemaFreeAttributeUseProhib( | |
| 4066 (xmlSchemaAttributeUseProhibPtr) item); | |
| 4067 break; | |
| 4068 case XML_SCHEMA_TYPE_ELEMENT: | |
| 4069 xmlSchemaFreeElement((xmlSchemaElementPtr) item); | |
| 4070 break; | |
| 4071 case XML_SCHEMA_TYPE_PARTICLE: | |
| 4072 if (item->annot != NULL) | |
| 4073 xmlSchemaFreeAnnot(item->annot); | |
| 4074 xmlFree(item); | |
| 4075 break; | |
| 4076 case XML_SCHEMA_TYPE_SEQUENCE: | |
| 4077 case XML_SCHEMA_TYPE_CHOICE: | |
| 4078 case XML_SCHEMA_TYPE_ALL: | |
| 4079 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item); | |
| 4080 break; | |
| 4081 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | |
| 4082 xmlSchemaFreeAttributeGroup( | |
| 4083 (xmlSchemaAttributeGroupPtr) item); | |
| 4084 break; | |
| 4085 case XML_SCHEMA_TYPE_GROUP: | |
| 4086 xmlSchemaFreeModelGroupDef( | |
| 4087 (xmlSchemaModelGroupDefPtr) item); | |
| 4088 break; | |
| 4089 case XML_SCHEMA_TYPE_ANY: | |
| 4090 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: | |
| 4091 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item); | |
| 4092 break; | |
| 4093 case XML_SCHEMA_TYPE_IDC_KEY: | |
| 4094 case XML_SCHEMA_TYPE_IDC_UNIQUE: | |
| 4095 case XML_SCHEMA_TYPE_IDC_KEYREF: | |
| 4096 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item); | |
| 4097 break; | |
| 4098 case XML_SCHEMA_TYPE_NOTATION: | |
| 4099 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item); | |
| 4100 break; | |
| 4101 case XML_SCHEMA_EXTRA_QNAMEREF: | |
| 4102 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item); | |
| 4103 break; | |
| 4104 default: { | |
| 4105 /* TODO: This should never be hit. */ | |
| 4106 xmlSchemaPSimpleInternalErr(NULL, | |
| 4107 "Internal error: xmlSchemaComponentListFree, " | |
| 4108 "unexpected component type '%s'\n", | |
| 4109 (const xmlChar *) WXS_ITEM_TYPE_NAME(item)); | |
| 4110 } | |
| 4111 break; | |
| 4112 } | |
| 4113 } | |
| 4114 list->nbItems = 0; | |
| 4115 } | |
| 4116 } | |
| 4117 | |
| 4118 /** | |
| 4119 * xmlSchemaFree: | |
| 4120 * @schema: a schema structure | |
| 4121 * | |
| 4122 * Deallocate a Schema structure. | |
| 4123 */ | |
| 4124 void | |
| 4125 xmlSchemaFree(xmlSchemaPtr schema) | |
| 4126 { | |
| 4127 if (schema == NULL) | |
| 4128 return; | |
| 4129 /* @volatiles is not used anymore :-/ */ | |
| 4130 if (schema->volatiles != NULL) | |
| 4131 TODO | |
| 4132 /* | |
| 4133 * Note that those slots are not responsible for freeing | |
| 4134 * schema components anymore; this will now be done by | |
| 4135 * the schema buckets. | |
| 4136 */ | |
| 4137 if (schema->notaDecl != NULL) | |
| 4138 xmlHashFree(schema->notaDecl, NULL); | |
| 4139 if (schema->attrDecl != NULL) | |
| 4140 xmlHashFree(schema->attrDecl, NULL); | |
| 4141 if (schema->attrgrpDecl != NULL) | |
| 4142 xmlHashFree(schema->attrgrpDecl, NULL); | |
| 4143 if (schema->elemDecl != NULL) | |
| 4144 xmlHashFree(schema->elemDecl, NULL); | |
| 4145 if (schema->typeDecl != NULL) | |
| 4146 xmlHashFree(schema->typeDecl, NULL); | |
| 4147 if (schema->groupDecl != NULL) | |
| 4148 xmlHashFree(schema->groupDecl, NULL); | |
| 4149 if (schema->idcDef != NULL) | |
| 4150 xmlHashFree(schema->idcDef, NULL); | |
| 4151 | |
| 4152 if (schema->schemasImports != NULL) | |
| 4153 xmlHashFree(schema->schemasImports, | |
| 4154 (xmlHashDeallocator) xmlSchemaBucketFree); | |
| 4155 if (schema->includes != NULL) { | |
| 4156 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes; | |
| 4157 int i; | |
| 4158 for (i = 0; i < list->nbItems; i++) { | |
| 4159 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]); | |
| 4160 } | |
| 4161 xmlSchemaItemListFree(list); | |
| 4162 } | |
| 4163 if (schema->annot != NULL) | |
| 4164 xmlSchemaFreeAnnot(schema->annot); | |
| 4165 /* Never free the doc here, since this will be done by the buckets. */ | |
| 4166 | |
| 4167 xmlDictFree(schema->dict); | |
| 4168 xmlFree(schema); | |
| 4169 } | |
| 4170 | |
| 4171 /************************************************************************ | |
| 4172 * * | |
| 4173 * Debug functions * | |
| 4174 * * | |
| 4175 ************************************************************************/ | |
| 4176 | |
| 4177 #ifdef LIBXML_OUTPUT_ENABLED | |
| 4178 | |
| 4179 static void | |
| 4180 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */ | |
| 4181 | |
| 4182 /** | |
| 4183 * xmlSchemaElementDump: | |
| 4184 * @elem: an element | |
| 4185 * @output: the file output | |
| 4186 * | |
| 4187 * Dump the element | |
| 4188 */ | |
| 4189 static void | |
| 4190 xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output, | |
| 4191 const xmlChar * name ATTRIBUTE_UNUSED, | |
| 4192 const xmlChar * namespace ATTRIBUTE_UNUSED, | |
| 4193 const xmlChar * context ATTRIBUTE_UNUSED) | |
| 4194 { | |
| 4195 if (elem == NULL) | |
| 4196 return; | |
| 4197 | |
| 4198 | |
| 4199 fprintf(output, "Element"); | |
| 4200 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL) | |
| 4201 fprintf(output, " (global)"); | |
| 4202 fprintf(output, ": '%s' ", elem->name); | |
| 4203 if (namespace != NULL) | |
| 4204 fprintf(output, "ns '%s'", namespace); | |
| 4205 fprintf(output, "\n"); | |
| 4206 #if 0 | |
| 4207 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) { | |
| 4208 fprintf(output, " min %d ", elem->minOccurs); | |
| 4209 if (elem->maxOccurs >= UNBOUNDED) | |
| 4210 fprintf(output, "max: unbounded\n"); | |
| 4211 else if (elem->maxOccurs != 1) | |
| 4212 fprintf(output, "max: %d\n", elem->maxOccurs); | |
| 4213 else | |
| 4214 fprintf(output, "\n"); | |
| 4215 } | |
| 4216 #endif | |
| 4217 /* | |
| 4218 * Misc other properties. | |
| 4219 */ | |
| 4220 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) || | |
| 4221 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) || | |
| 4222 (elem->flags & XML_SCHEMAS_ELEM_FIXED) || | |
| 4223 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) { | |
| 4224 fprintf(output, " props: "); | |
| 4225 if (elem->flags & XML_SCHEMAS_ELEM_FIXED) | |
| 4226 fprintf(output, "[fixed] "); | |
| 4227 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) | |
| 4228 fprintf(output, "[default] "); | |
| 4229 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) | |
| 4230 fprintf(output, "[abstract] "); | |
| 4231 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE) | |
| 4232 fprintf(output, "[nillable] "); | |
| 4233 fprintf(output, "\n"); | |
| 4234 } | |
| 4235 /* | |
| 4236 * Default/fixed value. | |
| 4237 */ | |
| 4238 if (elem->value != NULL) | |
| 4239 fprintf(output, " value: '%s'\n", elem->value); | |
| 4240 /* | |
| 4241 * Type. | |
| 4242 */ | |
| 4243 if (elem->namedType != NULL) { | |
| 4244 fprintf(output, " type: '%s' ", elem->namedType); | |
| 4245 if (elem->namedTypeNs != NULL) | |
| 4246 fprintf(output, "ns '%s'\n", elem->namedTypeNs); | |
| 4247 else | |
| 4248 fprintf(output, "\n"); | |
| 4249 } else if (elem->subtypes != NULL) { | |
| 4250 /* | |
| 4251 * Dump local types. | |
| 4252 */ | |
| 4253 xmlSchemaTypeDump(elem->subtypes, output); | |
| 4254 } | |
| 4255 /* | |
| 4256 * Substitution group. | |
| 4257 */ | |
| 4258 if (elem->substGroup != NULL) { | |
| 4259 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup); | |
| 4260 if (elem->substGroupNs != NULL) | |
| 4261 fprintf(output, "ns '%s'\n", elem->substGroupNs); | |
| 4262 else | |
| 4263 fprintf(output, "\n"); | |
| 4264 } | |
| 4265 } | |
| 4266 | |
| 4267 /** | |
| 4268 * xmlSchemaAnnotDump: | |
| 4269 * @output: the file output | |
| 4270 * @annot: a annotation | |
| 4271 * | |
| 4272 * Dump the annotation | |
| 4273 */ | |
| 4274 static void | |
| 4275 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot) | |
| 4276 { | |
| 4277 xmlChar *content; | |
| 4278 | |
| 4279 if (annot == NULL) | |
| 4280 return; | |
| 4281 | |
| 4282 content = xmlNodeGetContent(annot->content); | |
| 4283 if (content != NULL) { | |
| 4284 fprintf(output, " Annot: %s\n", content); | |
| 4285 xmlFree(content); | |
| 4286 } else | |
| 4287 fprintf(output, " Annot: empty\n"); | |
| 4288 } | |
| 4289 | |
| 4290 /** | |
| 4291 * xmlSchemaContentModelDump: | |
| 4292 * @particle: the schema particle | |
| 4293 * @output: the file output | |
| 4294 * @depth: the depth used for intentation | |
| 4295 * | |
| 4296 * Dump a SchemaType structure | |
| 4297 */ | |
| 4298 static void | |
| 4299 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int dept
h) | |
| 4300 { | |
| 4301 xmlChar *str = NULL; | |
| 4302 xmlSchemaTreeItemPtr term; | |
| 4303 char shift[100]; | |
| 4304 int i; | |
| 4305 | |
| 4306 if (particle == NULL) | |
| 4307 return; | |
| 4308 for (i = 0;((i < depth) && (i < 25));i++) | |
| 4309 shift[2 * i] = shift[2 * i + 1] = ' '; | |
| 4310 shift[2 * i] = shift[2 * i + 1] = 0; | |
| 4311 fprintf(output, "%s", shift); | |
| 4312 if (particle->children == NULL) { | |
| 4313 fprintf(output, "MISSING particle term\n"); | |
| 4314 return; | |
| 4315 } | |
| 4316 term = particle->children; | |
| 4317 if (term == NULL) { | |
| 4318 fprintf(output, "(NULL)"); | |
| 4319 } else { | |
| 4320 switch (term->type) { | |
| 4321 case XML_SCHEMA_TYPE_ELEMENT: | |
| 4322 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str, | |
| 4323 ((xmlSchemaElementPtr)term)->targetNamespace, | |
| 4324 ((xmlSchemaElementPtr)term)->name)); | |
| 4325 FREE_AND_NULL(str); | |
| 4326 break; | |
| 4327 case XML_SCHEMA_TYPE_SEQUENCE: | |
| 4328 fprintf(output, "SEQUENCE"); | |
| 4329 break; | |
| 4330 case XML_SCHEMA_TYPE_CHOICE: | |
| 4331 fprintf(output, "CHOICE"); | |
| 4332 break; | |
| 4333 case XML_SCHEMA_TYPE_ALL: | |
| 4334 fprintf(output, "ALL"); | |
| 4335 break; | |
| 4336 case XML_SCHEMA_TYPE_ANY: | |
| 4337 fprintf(output, "ANY"); | |
| 4338 break; | |
| 4339 default: | |
| 4340 fprintf(output, "UNKNOWN\n"); | |
| 4341 return; | |
| 4342 } | |
| 4343 } | |
| 4344 if (particle->minOccurs != 1) | |
| 4345 fprintf(output, " min: %d", particle->minOccurs); | |
| 4346 if (particle->maxOccurs >= UNBOUNDED) | |
| 4347 fprintf(output, " max: unbounded"); | |
| 4348 else if (particle->maxOccurs != 1) | |
| 4349 fprintf(output, " max: %d", particle->maxOccurs); | |
| 4350 fprintf(output, "\n"); | |
| 4351 if (term && | |
| 4352 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) || | |
| 4353 (term->type == XML_SCHEMA_TYPE_CHOICE) || | |
| 4354 (term->type == XML_SCHEMA_TYPE_ALL)) && | |
| 4355 (term->children != NULL)) { | |
| 4356 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children, | |
| 4357 output, depth +1); | |
| 4358 } | |
| 4359 if (particle->next != NULL) | |
| 4360 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next, | |
| 4361 output, depth); | |
| 4362 } | |
| 4363 | |
| 4364 /** | |
| 4365 * xmlSchemaAttrUsesDump: | |
| 4366 * @uses: attribute uses list | |
| 4367 * @output: the file output | |
| 4368 * | |
| 4369 * Dumps a list of attribute use components. | |
| 4370 */ | |
| 4371 static void | |
| 4372 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output) | |
| 4373 { | |
| 4374 xmlSchemaAttributeUsePtr use; | |
| 4375 xmlSchemaAttributeUseProhibPtr prohib; | |
| 4376 xmlSchemaQNameRefPtr ref; | |
| 4377 const xmlChar *name, *tns; | |
| 4378 xmlChar *str = NULL; | |
| 4379 int i; | |
| 4380 | |
| 4381 if ((uses == NULL) || (uses->nbItems == 0)) | |
| 4382 return; | |
| 4383 | |
| 4384 fprintf(output, " attributes:\n"); | |
| 4385 for (i = 0; i < uses->nbItems; i++) { | |
| 4386 use = uses->items[i]; | |
| 4387 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) { | |
| 4388 fprintf(output, " [prohibition] "); | |
| 4389 prohib = (xmlSchemaAttributeUseProhibPtr) use; | |
| 4390 name = prohib->name; | |
| 4391 tns = prohib->targetNamespace; | |
| 4392 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) { | |
| 4393 fprintf(output, " [reference] "); | |
| 4394 ref = (xmlSchemaQNameRefPtr) use; | |
| 4395 name = ref->name; | |
| 4396 tns = ref->targetNamespace; | |
| 4397 } else { | |
| 4398 fprintf(output, " [use] "); | |
| 4399 name = WXS_ATTRUSE_DECL_NAME(use); | |
| 4400 tns = WXS_ATTRUSE_DECL_TNS(use); | |
| 4401 } | |
| 4402 fprintf(output, "'%s'\n", | |
| 4403 (const char *) xmlSchemaFormatQName(&str, tns, name)); | |
| 4404 FREE_AND_NULL(str); | |
| 4405 } | |
| 4406 } | |
| 4407 | |
| 4408 /** | |
| 4409 * xmlSchemaTypeDump: | |
| 4410 * @output: the file output | |
| 4411 * @type: a type structure | |
| 4412 * | |
| 4413 * Dump a SchemaType structure | |
| 4414 */ | |
| 4415 static void | |
| 4416 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output) | |
| 4417 { | |
| 4418 if (type == NULL) { | |
| 4419 fprintf(output, "Type: NULL\n"); | |
| 4420 return; | |
| 4421 } | |
| 4422 fprintf(output, "Type: "); | |
| 4423 if (type->name != NULL) | |
| 4424 fprintf(output, "'%s' ", type->name); | |
| 4425 else | |
| 4426 fprintf(output, "(no name) "); | |
| 4427 if (type->targetNamespace != NULL) | |
| 4428 fprintf(output, "ns '%s' ", type->targetNamespace); | |
| 4429 switch (type->type) { | |
| 4430 case XML_SCHEMA_TYPE_BASIC: | |
| 4431 fprintf(output, "[basic] "); | |
| 4432 break; | |
| 4433 case XML_SCHEMA_TYPE_SIMPLE: | |
| 4434 fprintf(output, "[simple] "); | |
| 4435 break; | |
| 4436 case XML_SCHEMA_TYPE_COMPLEX: | |
| 4437 fprintf(output, "[complex] "); | |
| 4438 break; | |
| 4439 case XML_SCHEMA_TYPE_SEQUENCE: | |
| 4440 fprintf(output, "[sequence] "); | |
| 4441 break; | |
| 4442 case XML_SCHEMA_TYPE_CHOICE: | |
| 4443 fprintf(output, "[choice] "); | |
| 4444 break; | |
| 4445 case XML_SCHEMA_TYPE_ALL: | |
| 4446 fprintf(output, "[all] "); | |
| 4447 break; | |
| 4448 case XML_SCHEMA_TYPE_UR: | |
| 4449 fprintf(output, "[ur] "); | |
| 4450 break; | |
| 4451 case XML_SCHEMA_TYPE_RESTRICTION: | |
| 4452 fprintf(output, "[restriction] "); | |
| 4453 break; | |
| 4454 case XML_SCHEMA_TYPE_EXTENSION: | |
| 4455 fprintf(output, "[extension] "); | |
| 4456 break; | |
| 4457 default: | |
| 4458 fprintf(output, "[unknown type %d] ", type->type); | |
| 4459 break; | |
| 4460 } | |
| 4461 fprintf(output, "content: "); | |
| 4462 switch (type->contentType) { | |
| 4463 case XML_SCHEMA_CONTENT_UNKNOWN: | |
| 4464 fprintf(output, "[unknown] "); | |
| 4465 break; | |
| 4466 case XML_SCHEMA_CONTENT_EMPTY: | |
| 4467 fprintf(output, "[empty] "); | |
| 4468 break; | |
| 4469 case XML_SCHEMA_CONTENT_ELEMENTS: | |
| 4470 fprintf(output, "[element] "); | |
| 4471 break; | |
| 4472 case XML_SCHEMA_CONTENT_MIXED: | |
| 4473 fprintf(output, "[mixed] "); | |
| 4474 break; | |
| 4475 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS: | |
| 4476 /* not used. */ | |
| 4477 break; | |
| 4478 case XML_SCHEMA_CONTENT_BASIC: | |
| 4479 fprintf(output, "[basic] "); | |
| 4480 break; | |
| 4481 case XML_SCHEMA_CONTENT_SIMPLE: | |
| 4482 fprintf(output, "[simple] "); | |
| 4483 break; | |
| 4484 case XML_SCHEMA_CONTENT_ANY: | |
| 4485 fprintf(output, "[any] "); | |
| 4486 break; | |
| 4487 } | |
| 4488 fprintf(output, "\n"); | |
| 4489 if (type->base != NULL) { | |
| 4490 fprintf(output, " base type: '%s'", type->base); | |
| 4491 if (type->baseNs != NULL) | |
| 4492 fprintf(output, " ns '%s'\n", type->baseNs); | |
| 4493 else | |
| 4494 fprintf(output, "\n"); | |
| 4495 } | |
| 4496 if (type->attrUses != NULL) | |
| 4497 xmlSchemaAttrUsesDump(type->attrUses, output); | |
| 4498 if (type->annot != NULL) | |
| 4499 xmlSchemaAnnotDump(output, type->annot); | |
| 4500 #ifdef DUMP_CONTENT_MODEL | |
| 4501 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) && | |
| 4502 (type->subtypes != NULL)) { | |
| 4503 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes, | |
| 4504 output, 1); | |
| 4505 } | |
| 4506 #endif | |
| 4507 } | |
| 4508 | |
| 4509 /** | |
| 4510 * xmlSchemaDump: | |
| 4511 * @output: the file output | |
| 4512 * @schema: a schema structure | |
| 4513 * | |
| 4514 * Dump a Schema structure. | |
| 4515 */ | |
| 4516 void | |
| 4517 xmlSchemaDump(FILE * output, xmlSchemaPtr schema) | |
| 4518 { | |
| 4519 if (output == NULL) | |
| 4520 return; | |
| 4521 if (schema == NULL) { | |
| 4522 fprintf(output, "Schemas: NULL\n"); | |
| 4523 return; | |
| 4524 } | |
| 4525 fprintf(output, "Schemas: "); | |
| 4526 if (schema->name != NULL) | |
| 4527 fprintf(output, "%s, ", schema->name); | |
| 4528 else | |
| 4529 fprintf(output, "no name, "); | |
| 4530 if (schema->targetNamespace != NULL) | |
| 4531 fprintf(output, "%s", (const char *) schema->targetNamespace); | |
| 4532 else | |
| 4533 fprintf(output, "no target namespace"); | |
| 4534 fprintf(output, "\n"); | |
| 4535 if (schema->annot != NULL) | |
| 4536 xmlSchemaAnnotDump(output, schema->annot); | |
| 4537 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump, | |
| 4538 output); | |
| 4539 xmlHashScanFull(schema->elemDecl, | |
| 4540 (xmlHashScannerFull) xmlSchemaElementDump, output); | |
| 4541 } | |
| 4542 | |
| 4543 #ifdef DEBUG_IDC_NODE_TABLE | |
| 4544 /** | |
| 4545 * xmlSchemaDebugDumpIDCTable: | |
| 4546 * @vctxt: the WXS validation context | |
| 4547 * | |
| 4548 * Displays the current IDC table for debug purposes. | |
| 4549 */ | |
| 4550 static void | |
| 4551 xmlSchemaDebugDumpIDCTable(FILE * output, | |
| 4552 const xmlChar *namespaceName, | |
| 4553 const xmlChar *localName, | |
| 4554 xmlSchemaPSVIIDCBindingPtr bind) | |
| 4555 { | |
| 4556 xmlChar *str = NULL; | |
| 4557 const xmlChar *value; | |
| 4558 xmlSchemaPSVIIDCNodePtr tab; | |
| 4559 xmlSchemaPSVIIDCKeyPtr key; | |
| 4560 int i, j, res; | |
| 4561 | |
| 4562 fprintf(output, "IDC: TABLES on '%s'\n", | |
| 4563 xmlSchemaFormatQName(&str, namespaceName, localName)); | |
| 4564 FREE_AND_NULL(str) | |
| 4565 | |
| 4566 if (bind == NULL) | |
| 4567 return; | |
| 4568 do { | |
| 4569 fprintf(output, "IDC: BINDING '%s' (%d)\n", | |
| 4570 xmlSchemaGetComponentQName(&str, | |
| 4571 bind->definition), bind->nbNodes); | |
| 4572 FREE_AND_NULL(str) | |
| 4573 for (i = 0; i < bind->nbNodes; i++) { | |
| 4574 tab = bind->nodeTable[i]; | |
| 4575 fprintf(output, " ( "); | |
| 4576 for (j = 0; j < bind->definition->nbFields; j++) { | |
| 4577 key = tab->keys[j]; | |
| 4578 if ((key != NULL) && (key->val != NULL)) { | |
| 4579 res = xmlSchemaGetCanonValue(key->val, &value); | |
| 4580 if (res >= 0) | |
| 4581 fprintf(output, "'%s' ", value); | |
| 4582 else | |
| 4583 fprintf(output, "CANON-VALUE-FAILED "); | |
| 4584 if (res == 0) | |
| 4585 FREE_AND_NULL(value) | |
| 4586 } else if (key != NULL) | |
| 4587 fprintf(output, "(no val), "); | |
| 4588 else | |
| 4589 fprintf(output, "(key missing), "); | |
| 4590 } | |
| 4591 fprintf(output, ")\n"); | |
| 4592 } | |
| 4593 if (bind->dupls && bind->dupls->nbItems) { | |
| 4594 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems); | |
| 4595 for (i = 0; i < bind->dupls->nbItems; i++) { | |
| 4596 tab = bind->dupls->items[i]; | |
| 4597 fprintf(output, " ( "); | |
| 4598 for (j = 0; j < bind->definition->nbFields; j++) { | |
| 4599 key = tab->keys[j]; | |
| 4600 if ((key != NULL) && (key->val != NULL)) { | |
| 4601 res = xmlSchemaGetCanonValue(key->val, &value); | |
| 4602 if (res >= 0) | |
| 4603 fprintf(output, "'%s' ", value); | |
| 4604 else | |
| 4605 fprintf(output, "CANON-VALUE-FAILED "); | |
| 4606 if (res == 0) | |
| 4607 FREE_AND_NULL(value) | |
| 4608 } else if (key != NULL) | |
| 4609 fprintf(output, "(no val), "); | |
| 4610 else | |
| 4611 fprintf(output, "(key missing), "); | |
| 4612 } | |
| 4613 fprintf(output, ")\n"); | |
| 4614 } | |
| 4615 } | |
| 4616 bind = bind->next; | |
| 4617 } while (bind != NULL); | |
| 4618 } | |
| 4619 #endif /* DEBUG_IDC */ | |
| 4620 #endif /* LIBXML_OUTPUT_ENABLED */ | |
| 4621 | |
| 4622 /************************************************************************ | |
| 4623 * * | |
| 4624 * Utilities * | |
| 4625 * * | |
| 4626 ************************************************************************/ | |
| 4627 | |
| 4628 /** | |
| 4629 * xmlSchemaGetPropNode: | |
| 4630 * @node: the element node | |
| 4631 * @name: the name of the attribute | |
| 4632 * | |
| 4633 * Seeks an attribute with a name of @name in | |
| 4634 * no namespace. | |
| 4635 * | |
| 4636 * Returns the attribute or NULL if not present. | |
| 4637 */ | |
| 4638 static xmlAttrPtr | |
| 4639 xmlSchemaGetPropNode(xmlNodePtr node, const char *name) | |
| 4640 { | |
| 4641 xmlAttrPtr prop; | |
| 4642 | |
| 4643 if ((node == NULL) || (name == NULL)) | |
| 4644 return(NULL); | |
| 4645 prop = node->properties; | |
| 4646 while (prop != NULL) { | |
| 4647 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name)) | |
| 4648 return(prop); | |
| 4649 prop = prop->next; | |
| 4650 } | |
| 4651 return (NULL); | |
| 4652 } | |
| 4653 | |
| 4654 /** | |
| 4655 * xmlSchemaGetPropNodeNs: | |
| 4656 * @node: the element node | |
| 4657 * @uri: the uri | |
| 4658 * @name: the name of the attribute | |
| 4659 * | |
| 4660 * Seeks an attribute with a local name of @name and | |
| 4661 * a namespace URI of @uri. | |
| 4662 * | |
| 4663 * Returns the attribute or NULL if not present. | |
| 4664 */ | |
| 4665 static xmlAttrPtr | |
| 4666 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name) | |
| 4667 { | |
| 4668 xmlAttrPtr prop; | |
| 4669 | |
| 4670 if ((node == NULL) || (name == NULL)) | |
| 4671 return(NULL); | |
| 4672 prop = node->properties; | |
| 4673 while (prop != NULL) { | |
| 4674 if ((prop->ns != NULL) && | |
| 4675 xmlStrEqual(prop->name, BAD_CAST name) && | |
| 4676 xmlStrEqual(prop->ns->href, BAD_CAST uri)) | |
| 4677 return(prop); | |
| 4678 prop = prop->next; | |
| 4679 } | |
| 4680 return (NULL); | |
| 4681 } | |
| 4682 | |
| 4683 static const xmlChar * | |
| 4684 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) | |
| 4685 { | |
| 4686 xmlChar *val; | |
| 4687 const xmlChar *ret; | |
| 4688 | |
| 4689 val = xmlNodeGetContent(node); | |
| 4690 if (val == NULL) | |
| 4691 val = xmlStrdup((xmlChar *)""); | |
| 4692 ret = xmlDictLookup(ctxt->dict, val, -1); | |
| 4693 xmlFree(val); | |
| 4694 return(ret); | |
| 4695 } | |
| 4696 | |
| 4697 static const xmlChar * | |
| 4698 xmlSchemaGetNodeContentNoDict(xmlNodePtr node) | |
| 4699 { | |
| 4700 return((const xmlChar*) xmlNodeGetContent(node)); | |
| 4701 } | |
| 4702 | |
| 4703 /** | |
| 4704 * xmlSchemaGetProp: | |
| 4705 * @ctxt: the parser context | |
| 4706 * @node: the node | |
| 4707 * @name: the property name | |
| 4708 * | |
| 4709 * Read a attribute value and internalize the string | |
| 4710 * | |
| 4711 * Returns the string or NULL if not present. | |
| 4712 */ | |
| 4713 static const xmlChar * | |
| 4714 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, | |
| 4715 const char *name) | |
| 4716 { | |
| 4717 xmlChar *val; | |
| 4718 const xmlChar *ret; | |
| 4719 | |
| 4720 val = xmlGetNoNsProp(node, BAD_CAST name); | |
| 4721 if (val == NULL) | |
| 4722 return(NULL); | |
| 4723 ret = xmlDictLookup(ctxt->dict, val, -1); | |
| 4724 xmlFree(val); | |
| 4725 return(ret); | |
| 4726 } | |
| 4727 | |
| 4728 /************************************************************************ | |
| 4729 * * | |
| 4730 * Parsing functions * | |
| 4731 * * | |
| 4732 ************************************************************************/ | |
| 4733 | |
| 4734 #define WXS_FIND_GLOBAL_ITEM(slot) \ | |
| 4735 if (xmlStrEqual(nsName, schema->targetNamespace)) { \ | |
| 4736 ret = xmlHashLookup(schema->slot, name); \ | |
| 4737 if (ret != NULL) goto exit; \ | |
| 4738 } \ | |
| 4739 if (xmlHashSize(schema->schemasImports) > 1) { \ | |
| 4740 xmlSchemaImportPtr import; \ | |
| 4741 if (nsName == NULL) \ | |
| 4742 import = xmlHashLookup(schema->schemasImports, \ | |
| 4743 XML_SCHEMAS_NO_NAMESPACE); \ | |
| 4744 else \ | |
| 4745 import = xmlHashLookup(schema->schemasImports, nsName); \ | |
| 4746 if (import == NULL) \ | |
| 4747 goto exit; \ | |
| 4748 ret = xmlHashLookup(import->schema->slot, name); \ | |
| 4749 } | |
| 4750 | |
| 4751 /** | |
| 4752 * xmlSchemaGetElem: | |
| 4753 * @schema: the schema context | |
| 4754 * @name: the element name | |
| 4755 * @ns: the element namespace | |
| 4756 * | |
| 4757 * Lookup a global element declaration in the schema. | |
| 4758 * | |
| 4759 * Returns the element declaration or NULL if not found. | |
| 4760 */ | |
| 4761 static xmlSchemaElementPtr | |
| 4762 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name, | |
| 4763 const xmlChar * nsName) | |
| 4764 { | |
| 4765 xmlSchemaElementPtr ret = NULL; | |
| 4766 | |
| 4767 if ((name == NULL) || (schema == NULL)) | |
| 4768 return(NULL); | |
| 4769 if (schema != NULL) { | |
| 4770 WXS_FIND_GLOBAL_ITEM(elemDecl) | |
| 4771 } | |
| 4772 exit: | |
| 4773 #ifdef DEBUG | |
| 4774 if (ret == NULL) { | |
| 4775 if (nsName == NULL) | |
| 4776 fprintf(stderr, "Unable to lookup element decl. %s", name); | |
| 4777 else | |
| 4778 fprintf(stderr, "Unable to lookup element decl. %s:%s", name, | |
| 4779 nsName); | |
| 4780 } | |
| 4781 #endif | |
| 4782 return (ret); | |
| 4783 } | |
| 4784 | |
| 4785 /** | |
| 4786 * xmlSchemaGetType: | |
| 4787 * @schema: the main schema | |
| 4788 * @name: the type's name | |
| 4789 * nsName: the type's namespace | |
| 4790 * | |
| 4791 * Lookup a type in the schemas or the predefined types | |
| 4792 * | |
| 4793 * Returns the group definition or NULL if not found. | |
| 4794 */ | |
| 4795 static xmlSchemaTypePtr | |
| 4796 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name, | |
| 4797 const xmlChar * nsName) | |
| 4798 { | |
| 4799 xmlSchemaTypePtr ret = NULL; | |
| 4800 | |
| 4801 if (name == NULL) | |
| 4802 return (NULL); | |
| 4803 /* First try the built-in types. */ | |
| 4804 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) { | |
| 4805 ret = xmlSchemaGetPredefinedType(name, nsName); | |
| 4806 if (ret != NULL) | |
| 4807 goto exit; | |
| 4808 /* | |
| 4809 * Note that we try the parsed schemas as well here | |
| 4810 * since one might have parsed the S4S, which contain more | |
| 4811 * than the built-in types. | |
| 4812 * TODO: Can we optimize this? | |
| 4813 */ | |
| 4814 } | |
| 4815 if (schema != NULL) { | |
| 4816 WXS_FIND_GLOBAL_ITEM(typeDecl) | |
| 4817 } | |
| 4818 exit: | |
| 4819 | |
| 4820 #ifdef DEBUG | |
| 4821 if (ret == NULL) { | |
| 4822 if (nsName == NULL) | |
| 4823 fprintf(stderr, "Unable to lookup type %s", name); | |
| 4824 else | |
| 4825 fprintf(stderr, "Unable to lookup type %s:%s", name, | |
| 4826 nsName); | |
| 4827 } | |
| 4828 #endif | |
| 4829 return (ret); | |
| 4830 } | |
| 4831 | |
| 4832 /** | |
| 4833 * xmlSchemaGetAttributeDecl: | |
| 4834 * @schema: the context of the schema | |
| 4835 * @name: the name of the attribute | |
| 4836 * @ns: the target namespace of the attribute | |
| 4837 * | |
| 4838 * Lookup a an attribute in the schema or imported schemas | |
| 4839 * | |
| 4840 * Returns the attribute declaration or NULL if not found. | |
| 4841 */ | |
| 4842 static xmlSchemaAttributePtr | |
| 4843 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name, | |
| 4844 const xmlChar * nsName) | |
| 4845 { | |
| 4846 xmlSchemaAttributePtr ret = NULL; | |
| 4847 | |
| 4848 if ((name == NULL) || (schema == NULL)) | |
| 4849 return (NULL); | |
| 4850 if (schema != NULL) { | |
| 4851 WXS_FIND_GLOBAL_ITEM(attrDecl) | |
| 4852 } | |
| 4853 exit: | |
| 4854 #ifdef DEBUG | |
| 4855 if (ret == NULL) { | |
| 4856 if (nsName == NULL) | |
| 4857 fprintf(stderr, "Unable to lookup attribute %s", name); | |
| 4858 else | |
| 4859 fprintf(stderr, "Unable to lookup attribute %s:%s", name, | |
| 4860 nsName); | |
| 4861 } | |
| 4862 #endif | |
| 4863 return (ret); | |
| 4864 } | |
| 4865 | |
| 4866 /** | |
| 4867 * xmlSchemaGetAttributeGroup: | |
| 4868 * @schema: the context of the schema | |
| 4869 * @name: the name of the attribute group | |
| 4870 * @ns: the target namespace of the attribute group | |
| 4871 * | |
| 4872 * Lookup a an attribute group in the schema or imported schemas | |
| 4873 * | |
| 4874 * Returns the attribute group definition or NULL if not found. | |
| 4875 */ | |
| 4876 static xmlSchemaAttributeGroupPtr | |
| 4877 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name, | |
| 4878 const xmlChar * nsName) | |
| 4879 { | |
| 4880 xmlSchemaAttributeGroupPtr ret = NULL; | |
| 4881 | |
| 4882 if ((name == NULL) || (schema == NULL)) | |
| 4883 return (NULL); | |
| 4884 if (schema != NULL) { | |
| 4885 WXS_FIND_GLOBAL_ITEM(attrgrpDecl) | |
| 4886 } | |
| 4887 exit: | |
| 4888 /* TODO: | |
| 4889 if ((ret != NULL) && (ret->redef != NULL)) { | |
| 4890 * Return the last redefinition. * | |
| 4891 ret = ret->redef; | |
| 4892 } | |
| 4893 */ | |
| 4894 #ifdef DEBUG | |
| 4895 if (ret == NULL) { | |
| 4896 if (nsName == NULL) | |
| 4897 fprintf(stderr, "Unable to lookup attribute group %s", name); | |
| 4898 else | |
| 4899 fprintf(stderr, "Unable to lookup attribute group %s:%s", name, | |
| 4900 nsName); | |
| 4901 } | |
| 4902 #endif | |
| 4903 return (ret); | |
| 4904 } | |
| 4905 | |
| 4906 /** | |
| 4907 * xmlSchemaGetGroup: | |
| 4908 * @schema: the context of the schema | |
| 4909 * @name: the name of the group | |
| 4910 * @ns: the target namespace of the group | |
| 4911 * | |
| 4912 * Lookup a group in the schema or imported schemas | |
| 4913 * | |
| 4914 * Returns the group definition or NULL if not found. | |
| 4915 */ | |
| 4916 static xmlSchemaModelGroupDefPtr | |
| 4917 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name, | |
| 4918 const xmlChar * nsName) | |
| 4919 { | |
| 4920 xmlSchemaModelGroupDefPtr ret = NULL; | |
| 4921 | |
| 4922 if ((name == NULL) || (schema == NULL)) | |
| 4923 return (NULL); | |
| 4924 if (schema != NULL) { | |
| 4925 WXS_FIND_GLOBAL_ITEM(groupDecl) | |
| 4926 } | |
| 4927 exit: | |
| 4928 | |
| 4929 #ifdef DEBUG | |
| 4930 if (ret == NULL) { | |
| 4931 if (nsName == NULL) | |
| 4932 fprintf(stderr, "Unable to lookup group %s", name); | |
| 4933 else | |
| 4934 fprintf(stderr, "Unable to lookup group %s:%s", name, | |
| 4935 nsName); | |
| 4936 } | |
| 4937 #endif | |
| 4938 return (ret); | |
| 4939 } | |
| 4940 | |
| 4941 static xmlSchemaNotationPtr | |
| 4942 xmlSchemaGetNotation(xmlSchemaPtr schema, | |
| 4943 const xmlChar *name, | |
| 4944 const xmlChar *nsName) | |
| 4945 { | |
| 4946 xmlSchemaNotationPtr ret = NULL; | |
| 4947 | |
| 4948 if ((name == NULL) || (schema == NULL)) | |
| 4949 return (NULL); | |
| 4950 if (schema != NULL) { | |
| 4951 WXS_FIND_GLOBAL_ITEM(notaDecl) | |
| 4952 } | |
| 4953 exit: | |
| 4954 return (ret); | |
| 4955 } | |
| 4956 | |
| 4957 static xmlSchemaIDCPtr | |
| 4958 xmlSchemaGetIDC(xmlSchemaPtr schema, | |
| 4959 const xmlChar *name, | |
| 4960 const xmlChar *nsName) | |
| 4961 { | |
| 4962 xmlSchemaIDCPtr ret = NULL; | |
| 4963 | |
| 4964 if ((name == NULL) || (schema == NULL)) | |
| 4965 return (NULL); | |
| 4966 if (schema != NULL) { | |
| 4967 WXS_FIND_GLOBAL_ITEM(idcDef) | |
| 4968 } | |
| 4969 exit: | |
| 4970 return (ret); | |
| 4971 } | |
| 4972 | |
| 4973 /** | |
| 4974 * xmlSchemaGetNamedComponent: | |
| 4975 * @schema: the schema | |
| 4976 * @name: the name of the group | |
| 4977 * @ns: the target namespace of the group | |
| 4978 * | |
| 4979 * Lookup a group in the schema or imported schemas | |
| 4980 * | |
| 4981 * Returns the group definition or NULL if not found. | |
| 4982 */ | |
| 4983 static xmlSchemaBasicItemPtr | |
| 4984 xmlSchemaGetNamedComponent(xmlSchemaPtr schema, | |
| 4985 xmlSchemaTypeType itemType, | |
| 4986 const xmlChar *name, | |
| 4987 const xmlChar *targetNs) | |
| 4988 { | |
| 4989 switch (itemType) { | |
| 4990 case XML_SCHEMA_TYPE_GROUP: | |
| 4991 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema, | |
| 4992 name, targetNs)); | |
| 4993 case XML_SCHEMA_TYPE_ELEMENT: | |
| 4994 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema, | |
| 4995 name, targetNs)); | |
| 4996 default: | |
| 4997 TODO | |
| 4998 return (NULL); | |
| 4999 } | |
| 5000 } | |
| 5001 | |
| 5002 /************************************************************************ | |
| 5003 * * | |
| 5004 * Parsing functions * | |
| 5005 * * | |
| 5006 ************************************************************************/ | |
| 5007 | |
| 5008 #define IS_BLANK_NODE(n) \ | |
| 5009 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1))) | |
| 5010 | |
| 5011 /** | |
| 5012 * xmlSchemaIsBlank: | |
| 5013 * @str: a string | |
| 5014 * @len: the length of the string or -1 | |
| 5015 * | |
| 5016 * Check if a string is ignorable | |
| 5017 * | |
| 5018 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise | |
| 5019 */ | |
| 5020 static int | |
| 5021 xmlSchemaIsBlank(xmlChar * str, int len) | |
| 5022 { | |
| 5023 if (str == NULL) | |
| 5024 return (1); | |
| 5025 if (len < 0) { | |
| 5026 while (*str != 0) { | |
| 5027 if (!(IS_BLANK_CH(*str))) | |
| 5028 return (0); | |
| 5029 str++; | |
| 5030 } | |
| 5031 } else while ((*str != 0) && (len != 0)) { | |
| 5032 if (!(IS_BLANK_CH(*str))) | |
| 5033 return (0); | |
| 5034 str++; | |
| 5035 len--; | |
| 5036 } | |
| 5037 | |
| 5038 return (1); | |
| 5039 } | |
| 5040 | |
| 5041 #define WXS_COMP_NAME(c, t) ((t) (c))->name | |
| 5042 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace | |
| 5043 /* | |
| 5044 * xmlSchemaFindRedefCompInGraph: | |
| 5045 * ATTENTION TODO: This uses pointer comp. for strings. | |
| 5046 */ | |
| 5047 static xmlSchemaBasicItemPtr | |
| 5048 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket, | |
| 5049 xmlSchemaTypeType type, | |
| 5050 const xmlChar *name, | |
| 5051 const xmlChar *nsName) | |
| 5052 { | |
| 5053 xmlSchemaBasicItemPtr ret; | |
| 5054 int i; | |
| 5055 | |
| 5056 if ((bucket == NULL) || (name == NULL)) | |
| 5057 return(NULL); | |
| 5058 if ((bucket->globals == NULL) || | |
| 5059 (bucket->globals->nbItems == 0)) | |
| 5060 goto subschemas; | |
| 5061 /* | |
| 5062 * Search in global components. | |
| 5063 */ | |
| 5064 for (i = 0; i < bucket->globals->nbItems; i++) { | |
| 5065 ret = bucket->globals->items[i]; | |
| 5066 if (ret->type == type) { | |
| 5067 switch (type) { | |
| 5068 case XML_SCHEMA_TYPE_COMPLEX: | |
| 5069 case XML_SCHEMA_TYPE_SIMPLE: | |
| 5070 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) && | |
| 5071 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) == | |
| 5072 nsName)) | |
| 5073 { | |
| 5074 return(ret); | |
| 5075 } | |
| 5076 break; | |
| 5077 case XML_SCHEMA_TYPE_GROUP: | |
| 5078 if ((WXS_COMP_NAME(ret, | |
| 5079 xmlSchemaModelGroupDefPtr) == name) && | |
| 5080 (WXS_COMP_TNS(ret, | |
| 5081 xmlSchemaModelGroupDefPtr) == nsName)) | |
| 5082 { | |
| 5083 return(ret); | |
| 5084 } | |
| 5085 break; | |
| 5086 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | |
| 5087 if ((WXS_COMP_NAME(ret, | |
| 5088 xmlSchemaAttributeGroupPtr) == name) && | |
| 5089 (WXS_COMP_TNS(ret, | |
| 5090 xmlSchemaAttributeGroupPtr) == nsName)) | |
| 5091 { | |
| 5092 return(ret); | |
| 5093 } | |
| 5094 break; | |
| 5095 default: | |
| 5096 /* Should not be hit. */ | |
| 5097 return(NULL); | |
| 5098 } | |
| 5099 } | |
| 5100 } | |
| 5101 subschemas: | |
| 5102 /* | |
| 5103 * Process imported/included schemas. | |
| 5104 */ | |
| 5105 if (bucket->relations != NULL) { | |
| 5106 xmlSchemaSchemaRelationPtr rel = bucket->relations; | |
| 5107 | |
| 5108 /* | |
| 5109 * TODO: Marking the bucket will not avoid multiple searches | |
| 5110 * in the same schema, but avoids at least circularity. | |
| 5111 */ | |
| 5112 bucket->flags |= XML_SCHEMA_BUCKET_MARKED; | |
| 5113 do { | |
| 5114 if ((rel->bucket != NULL) && | |
| 5115 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) { | |
| 5116 ret = xmlSchemaFindRedefCompInGraph(rel->bucket, | |
| 5117 type, name, nsName); | |
| 5118 if (ret != NULL) | |
| 5119 return(ret); | |
| 5120 } | |
| 5121 rel = rel->next; | |
| 5122 } while (rel != NULL); | |
| 5123 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED; | |
| 5124 } | |
| 5125 return(NULL); | |
| 5126 } | |
| 5127 | |
| 5128 /** | |
| 5129 * xmlSchemaAddNotation: | |
| 5130 * @ctxt: a schema parser context | |
| 5131 * @schema: the schema being built | |
| 5132 * @name: the item name | |
| 5133 * | |
| 5134 * Add an XML schema annotation declaration | |
| 5135 * *WARNING* this interface is highly subject to change | |
| 5136 * | |
| 5137 * Returns the new struture or NULL in case of error | |
| 5138 */ | |
| 5139 static xmlSchemaNotationPtr | |
| 5140 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 5141 const xmlChar *name, const xmlChar *nsName, | |
| 5142 xmlNodePtr node ATTRIBUTE_UNUSED) | |
| 5143 { | |
| 5144 xmlSchemaNotationPtr ret = NULL; | |
| 5145 | |
| 5146 if ((ctxt == NULL) || (schema == NULL) || (name == NULL)) | |
| 5147 return (NULL); | |
| 5148 | |
| 5149 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation)); | |
| 5150 if (ret == NULL) { | |
| 5151 xmlSchemaPErrMemory(ctxt, "add annotation", NULL); | |
| 5152 return (NULL); | |
| 5153 } | |
| 5154 memset(ret, 0, sizeof(xmlSchemaNotation)); | |
| 5155 ret->type = XML_SCHEMA_TYPE_NOTATION; | |
| 5156 ret->name = name; | |
| 5157 ret->targetNamespace = nsName; | |
| 5158 /* TODO: do we need the node to be set? | |
| 5159 * ret->node = node;*/ | |
| 5160 WXS_ADD_GLOBAL(ctxt, ret); | |
| 5161 return (ret); | |
| 5162 } | |
| 5163 | |
| 5164 /** | |
| 5165 * xmlSchemaAddAttribute: | |
| 5166 * @ctxt: a schema parser context | |
| 5167 * @schema: the schema being built | |
| 5168 * @name: the item name | |
| 5169 * @namespace: the namespace | |
| 5170 * | |
| 5171 * Add an XML schema Attrribute declaration | |
| 5172 * *WARNING* this interface is highly subject to change | |
| 5173 * | |
| 5174 * Returns the new struture or NULL in case of error | |
| 5175 */ | |
| 5176 static xmlSchemaAttributePtr | |
| 5177 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 5178 const xmlChar * name, const xmlChar * nsName, | |
| 5179 xmlNodePtr node, int topLevel) | |
| 5180 { | |
| 5181 xmlSchemaAttributePtr ret = NULL; | |
| 5182 | |
| 5183 if ((ctxt == NULL) || (schema == NULL)) | |
| 5184 return (NULL); | |
| 5185 | |
| 5186 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute)); | |
| 5187 if (ret == NULL) { | |
| 5188 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL); | |
| 5189 return (NULL); | |
| 5190 } | |
| 5191 memset(ret, 0, sizeof(xmlSchemaAttribute)); | |
| 5192 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE; | |
| 5193 ret->node = node; | |
| 5194 ret->name = name; | |
| 5195 ret->targetNamespace = nsName; | |
| 5196 | |
| 5197 if (topLevel) | |
| 5198 WXS_ADD_GLOBAL(ctxt, ret); | |
| 5199 else | |
| 5200 WXS_ADD_LOCAL(ctxt, ret); | |
| 5201 WXS_ADD_PENDING(ctxt, ret); | |
| 5202 return (ret); | |
| 5203 } | |
| 5204 | |
| 5205 /** | |
| 5206 * xmlSchemaAddAttributeUse: | |
| 5207 * @ctxt: a schema parser context | |
| 5208 * @schema: the schema being built | |
| 5209 * @name: the item name | |
| 5210 * @namespace: the namespace | |
| 5211 * | |
| 5212 * Add an XML schema Attrribute declaration | |
| 5213 * *WARNING* this interface is highly subject to change | |
| 5214 * | |
| 5215 * Returns the new struture or NULL in case of error | |
| 5216 */ | |
| 5217 static xmlSchemaAttributeUsePtr | |
| 5218 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt, | |
| 5219 xmlNodePtr node) | |
| 5220 { | |
| 5221 xmlSchemaAttributeUsePtr ret = NULL; | |
| 5222 | |
| 5223 if (pctxt == NULL) | |
| 5224 return (NULL); | |
| 5225 | |
| 5226 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse)); | |
| 5227 if (ret == NULL) { | |
| 5228 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL); | |
| 5229 return (NULL); | |
| 5230 } | |
| 5231 memset(ret, 0, sizeof(xmlSchemaAttributeUse)); | |
| 5232 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE; | |
| 5233 ret->node = node; | |
| 5234 | |
| 5235 WXS_ADD_LOCAL(pctxt, ret); | |
| 5236 return (ret); | |
| 5237 } | |
| 5238 | |
| 5239 /* | |
| 5240 * xmlSchemaAddRedef: | |
| 5241 * | |
| 5242 * Adds a redefinition information. This is used at a later stage to: | |
| 5243 * resolve references to the redefined components and to check constraints. | |
| 5244 */ | |
| 5245 static xmlSchemaRedefPtr | |
| 5246 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt, | |
| 5247 xmlSchemaBucketPtr targetBucket, | |
| 5248 void *item, | |
| 5249 const xmlChar *refName, | |
| 5250 const xmlChar *refTargetNs) | |
| 5251 { | |
| 5252 xmlSchemaRedefPtr ret; | |
| 5253 | |
| 5254 ret = (xmlSchemaRedefPtr) | |
| 5255 xmlMalloc(sizeof(xmlSchemaRedef)); | |
| 5256 if (ret == NULL) { | |
| 5257 xmlSchemaPErrMemory(pctxt, | |
| 5258 "allocating redefinition info", NULL); | |
| 5259 return (NULL); | |
| 5260 } | |
| 5261 memset(ret, 0, sizeof(xmlSchemaRedef)); | |
| 5262 ret->item = item; | |
| 5263 ret->targetBucket = targetBucket; | |
| 5264 ret->refName = refName; | |
| 5265 ret->refTargetNs = refTargetNs; | |
| 5266 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL) | |
| 5267 WXS_CONSTRUCTOR(pctxt)->redefs = ret; | |
| 5268 else | |
| 5269 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret; | |
| 5270 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret; | |
| 5271 | |
| 5272 return (ret); | |
| 5273 } | |
| 5274 | |
| 5275 /** | |
| 5276 * xmlSchemaAddAttributeGroupDefinition: | |
| 5277 * @ctxt: a schema parser context | |
| 5278 * @schema: the schema being built | |
| 5279 * @name: the item name | |
| 5280 * @nsName: the target namespace | |
| 5281 * @node: the corresponding node | |
| 5282 * | |
| 5283 * Add an XML schema Attrribute Group definition. | |
| 5284 * | |
| 5285 * Returns the new struture or NULL in case of error | |
| 5286 */ | |
| 5287 static xmlSchemaAttributeGroupPtr | |
| 5288 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt, | |
| 5289 xmlSchemaPtr schema ATTRIBUTE_UNUSED, | |
| 5290 const xmlChar *name, | |
| 5291 const xmlChar *nsName, | |
| 5292 xmlNodePtr node) | |
| 5293 { | |
| 5294 xmlSchemaAttributeGroupPtr ret = NULL; | |
| 5295 | |
| 5296 if ((pctxt == NULL) || (name == NULL)) | |
| 5297 return (NULL); | |
| 5298 | |
| 5299 ret = (xmlSchemaAttributeGroupPtr) | |
| 5300 xmlMalloc(sizeof(xmlSchemaAttributeGroup)); | |
| 5301 if (ret == NULL) { | |
| 5302 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL); | |
| 5303 return (NULL); | |
| 5304 } | |
| 5305 memset(ret, 0, sizeof(xmlSchemaAttributeGroup)); | |
| 5306 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP; | |
| 5307 ret->name = name; | |
| 5308 ret->targetNamespace = nsName; | |
| 5309 ret->node = node; | |
| 5310 | |
| 5311 /* TODO: Remove the flag. */ | |
| 5312 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL; | |
| 5313 if (pctxt->isRedefine) { | |
| 5314 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined, | |
| 5315 ret, name, nsName); | |
| 5316 if (pctxt->redef == NULL) { | |
| 5317 xmlFree(ret); | |
| 5318 return(NULL); | |
| 5319 } | |
| 5320 pctxt->redefCounter = 0; | |
| 5321 } | |
| 5322 WXS_ADD_GLOBAL(pctxt, ret); | |
| 5323 WXS_ADD_PENDING(pctxt, ret); | |
| 5324 return (ret); | |
| 5325 } | |
| 5326 | |
| 5327 /** | |
| 5328 * xmlSchemaAddElement: | |
| 5329 * @ctxt: a schema parser context | |
| 5330 * @schema: the schema being built | |
| 5331 * @name: the type name | |
| 5332 * @namespace: the type namespace | |
| 5333 * | |
| 5334 * Add an XML schema Element declaration | |
| 5335 * *WARNING* this interface is highly subject to change | |
| 5336 * | |
| 5337 * Returns the new struture or NULL in case of error | |
| 5338 */ | |
| 5339 static xmlSchemaElementPtr | |
| 5340 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, | |
| 5341 const xmlChar * name, const xmlChar * nsName, | |
| 5342 xmlNodePtr node, int topLevel) | |
| 5343 { | |
| 5344 xmlSchemaElementPtr ret = NULL; | |
| 5345 | |
| 5346 if ((ctxt == NULL) || (name == NULL)) | |
| 5347 return (NULL); | |
| 5348 | |
| 5349 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement)); | |
| 5350 if (ret == NULL) { | |
| 5351 xmlSchemaPErrMemory(ctxt, "allocating element", NULL); | |
| 5352 return (NULL); | |
| 5353 } | |
| 5354 memset(ret, 0, sizeof(xmlSchemaElement)); | |
| 5355 ret->type = XML_SCHEMA_TYPE_ELEMENT; | |
| 5356 ret->name = name; | |
| 5357 ret->targetNamespace = nsName; | |
| 5358 ret->node = node; | |
| 5359 | |
| 5360 if (topLevel) | |
| 5361 WXS_ADD_GLOBAL(ctxt, ret); | |
| 5362 else | |
| 5363 WXS_ADD_LOCAL(ctxt, ret); | |
| 5364 WXS_ADD_PENDING(ctxt, ret); | |
| 5365 return (ret); | |
| 5366 } | |
| 5367 | |
| 5368 /** | |
| 5369 * xmlSchemaAddType: | |
| 5370 * @ctxt: a schema parser context | |
| 5371 * @schema: the schema being built | |
| 5372 * @name: the item name | |
| 5373 * @namespace: the namespace | |
| 5374 * | |
| 5375 * Add an XML schema item | |
| 5376 * *WARNING* this interface is highly subject to change | |
| 5377 * | |
| 5378 * Returns the new struture or NULL in case of error | |
| 5379 */ | |
| 5380 static xmlSchemaTypePtr | |
| 5381 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 5382 xmlSchemaTypeType type, | |
| 5383 const xmlChar * name, const xmlChar * nsName, | |
| 5384 xmlNodePtr node, int topLevel) | |
| 5385 { | |
| 5386 xmlSchemaTypePtr ret = NULL; | |
| 5387 | |
| 5388 if ((ctxt == NULL) || (schema == NULL)) | |
| 5389 return (NULL); | |
| 5390 | |
| 5391 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType)); | |
| 5392 if (ret == NULL) { | |
| 5393 xmlSchemaPErrMemory(ctxt, "allocating type", NULL); | |
| 5394 return (NULL); | |
| 5395 } | |
| 5396 memset(ret, 0, sizeof(xmlSchemaType)); | |
| 5397 ret->type = type; | |
| 5398 ret->name = name; | |
| 5399 ret->targetNamespace = nsName; | |
| 5400 ret->node = node; | |
| 5401 if (topLevel) { | |
| 5402 if (ctxt->isRedefine) { | |
| 5403 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined, | |
| 5404 ret, name, nsName); | |
| 5405 if (ctxt->redef == NULL) { | |
| 5406 xmlFree(ret); | |
| 5407 return(NULL); | |
| 5408 } | |
| 5409 ctxt->redefCounter = 0; | |
| 5410 } | |
| 5411 WXS_ADD_GLOBAL(ctxt, ret); | |
| 5412 } else | |
| 5413 WXS_ADD_LOCAL(ctxt, ret); | |
| 5414 WXS_ADD_PENDING(ctxt, ret); | |
| 5415 return (ret); | |
| 5416 } | |
| 5417 | |
| 5418 static xmlSchemaQNameRefPtr | |
| 5419 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt, | |
| 5420 xmlSchemaTypeType refType, | |
| 5421 const xmlChar *refName, | |
| 5422 const xmlChar *refNs) | |
| 5423 { | |
| 5424 xmlSchemaQNameRefPtr ret; | |
| 5425 | |
| 5426 ret = (xmlSchemaQNameRefPtr) | |
| 5427 xmlMalloc(sizeof(xmlSchemaQNameRef)); | |
| 5428 if (ret == NULL) { | |
| 5429 xmlSchemaPErrMemory(pctxt, | |
| 5430 "allocating QName reference item", NULL); | |
| 5431 return (NULL); | |
| 5432 } | |
| 5433 ret->node = NULL; | |
| 5434 ret->type = XML_SCHEMA_EXTRA_QNAMEREF; | |
| 5435 ret->name = refName; | |
| 5436 ret->targetNamespace = refNs; | |
| 5437 ret->item = NULL; | |
| 5438 ret->itemType = refType; | |
| 5439 /* | |
| 5440 * Store the reference item in the schema. | |
| 5441 */ | |
| 5442 WXS_ADD_LOCAL(pctxt, ret); | |
| 5443 return (ret); | |
| 5444 } | |
| 5445 | |
| 5446 static xmlSchemaAttributeUseProhibPtr | |
| 5447 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt) | |
| 5448 { | |
| 5449 xmlSchemaAttributeUseProhibPtr ret; | |
| 5450 | |
| 5451 ret = (xmlSchemaAttributeUseProhibPtr) | |
| 5452 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib)); | |
| 5453 if (ret == NULL) { | |
| 5454 xmlSchemaPErrMemory(pctxt, | |
| 5455 "allocating attribute use prohibition", NULL); | |
| 5456 return (NULL); | |
| 5457 } | |
| 5458 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib)); | |
| 5459 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB; | |
| 5460 WXS_ADD_LOCAL(pctxt, ret); | |
| 5461 return (ret); | |
| 5462 } | |
| 5463 | |
| 5464 | |
| 5465 /** | |
| 5466 * xmlSchemaAddModelGroup: | |
| 5467 * @ctxt: a schema parser context | |
| 5468 * @schema: the schema being built | |
| 5469 * @type: the "compositor" type of the model group | |
| 5470 * @node: the node in the schema doc | |
| 5471 * | |
| 5472 * Adds a schema model group | |
| 5473 * *WARNING* this interface is highly subject to change | |
| 5474 * | |
| 5475 * Returns the new struture or NULL in case of error | |
| 5476 */ | |
| 5477 static xmlSchemaModelGroupPtr | |
| 5478 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, | |
| 5479 xmlSchemaPtr schema, | |
| 5480 xmlSchemaTypeType type, | |
| 5481 xmlNodePtr node) | |
| 5482 { | |
| 5483 xmlSchemaModelGroupPtr ret = NULL; | |
| 5484 | |
| 5485 if ((ctxt == NULL) || (schema == NULL)) | |
| 5486 return (NULL); | |
| 5487 | |
| 5488 ret = (xmlSchemaModelGroupPtr) | |
| 5489 xmlMalloc(sizeof(xmlSchemaModelGroup)); | |
| 5490 if (ret == NULL) { | |
| 5491 xmlSchemaPErrMemory(ctxt, "allocating model group component", | |
| 5492 NULL); | |
| 5493 return (NULL); | |
| 5494 } | |
| 5495 memset(ret, 0, sizeof(xmlSchemaModelGroup)); | |
| 5496 ret->type = type; | |
| 5497 ret->node = node; | |
| 5498 WXS_ADD_LOCAL(ctxt, ret); | |
| 5499 if ((type == XML_SCHEMA_TYPE_SEQUENCE) || | |
| 5500 (type == XML_SCHEMA_TYPE_CHOICE)) | |
| 5501 WXS_ADD_PENDING(ctxt, ret); | |
| 5502 return (ret); | |
| 5503 } | |
| 5504 | |
| 5505 | |
| 5506 /** | |
| 5507 * xmlSchemaAddParticle: | |
| 5508 * @ctxt: a schema parser context | |
| 5509 * @schema: the schema being built | |
| 5510 * @node: the corresponding node in the schema doc | |
| 5511 * @min: the minOccurs | |
| 5512 * @max: the maxOccurs | |
| 5513 * | |
| 5514 * Adds an XML schema particle component. | |
| 5515 * *WARNING* this interface is highly subject to change | |
| 5516 * | |
| 5517 * Returns the new struture or NULL in case of error | |
| 5518 */ | |
| 5519 static xmlSchemaParticlePtr | |
| 5520 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, | |
| 5521 xmlNodePtr node, int min, int max) | |
| 5522 { | |
| 5523 xmlSchemaParticlePtr ret = NULL; | |
| 5524 if (ctxt == NULL) | |
| 5525 return (NULL); | |
| 5526 | |
| 5527 #ifdef DEBUG | |
| 5528 fprintf(stderr, "Adding particle component\n"); | |
| 5529 #endif | |
| 5530 ret = (xmlSchemaParticlePtr) | |
| 5531 xmlMalloc(sizeof(xmlSchemaParticle)); | |
| 5532 if (ret == NULL) { | |
| 5533 xmlSchemaPErrMemory(ctxt, "allocating particle component", | |
| 5534 NULL); | |
| 5535 return (NULL); | |
| 5536 } | |
| 5537 ret->type = XML_SCHEMA_TYPE_PARTICLE; | |
| 5538 ret->annot = NULL; | |
| 5539 ret->node = node; | |
| 5540 ret->minOccurs = min; | |
| 5541 ret->maxOccurs = max; | |
| 5542 ret->next = NULL; | |
| 5543 ret->children = NULL; | |
| 5544 | |
| 5545 WXS_ADD_LOCAL(ctxt, ret); | |
| 5546 /* | |
| 5547 * Note that addition to pending components will be done locally | |
| 5548 * to the specific parsing function, since the most particles | |
| 5549 * need not to be fixed up (i.e. the reference to be resolved). | |
| 5550 * REMOVED: WXS_ADD_PENDING(ctxt, ret); | |
| 5551 */ | |
| 5552 return (ret); | |
| 5553 } | |
| 5554 | |
| 5555 /** | |
| 5556 * xmlSchemaAddModelGroupDefinition: | |
| 5557 * @ctxt: a schema validation context | |
| 5558 * @schema: the schema being built | |
| 5559 * @name: the group name | |
| 5560 * | |
| 5561 * Add an XML schema Group definition | |
| 5562 * | |
| 5563 * Returns the new struture or NULL in case of error | |
| 5564 */ | |
| 5565 static xmlSchemaModelGroupDefPtr | |
| 5566 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt, | |
| 5567 xmlSchemaPtr schema, | |
| 5568 const xmlChar *name, | |
| 5569 const xmlChar *nsName, | |
| 5570 xmlNodePtr node) | |
| 5571 { | |
| 5572 xmlSchemaModelGroupDefPtr ret = NULL; | |
| 5573 | |
| 5574 if ((ctxt == NULL) || (schema == NULL) || (name == NULL)) | |
| 5575 return (NULL); | |
| 5576 | |
| 5577 ret = (xmlSchemaModelGroupDefPtr) | |
| 5578 xmlMalloc(sizeof(xmlSchemaModelGroupDef)); | |
| 5579 if (ret == NULL) { | |
| 5580 xmlSchemaPErrMemory(ctxt, "adding group", NULL); | |
| 5581 return (NULL); | |
| 5582 } | |
| 5583 memset(ret, 0, sizeof(xmlSchemaModelGroupDef)); | |
| 5584 ret->name = name; | |
| 5585 ret->type = XML_SCHEMA_TYPE_GROUP; | |
| 5586 ret->node = node; | |
| 5587 ret->targetNamespace = nsName; | |
| 5588 | |
| 5589 if (ctxt->isRedefine) { | |
| 5590 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined, | |
| 5591 ret, name, nsName); | |
| 5592 if (ctxt->redef == NULL) { | |
| 5593 xmlFree(ret); | |
| 5594 return(NULL); | |
| 5595 } | |
| 5596 ctxt->redefCounter = 0; | |
| 5597 } | |
| 5598 WXS_ADD_GLOBAL(ctxt, ret); | |
| 5599 WXS_ADD_PENDING(ctxt, ret); | |
| 5600 return (ret); | |
| 5601 } | |
| 5602 | |
| 5603 /** | |
| 5604 * xmlSchemaNewWildcardNs: | |
| 5605 * @ctxt: a schema validation context | |
| 5606 * | |
| 5607 * Creates a new wildcard namespace constraint. | |
| 5608 * | |
| 5609 * Returns the new struture or NULL in case of error | |
| 5610 */ | |
| 5611 static xmlSchemaWildcardNsPtr | |
| 5612 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt) | |
| 5613 { | |
| 5614 xmlSchemaWildcardNsPtr ret; | |
| 5615 | |
| 5616 ret = (xmlSchemaWildcardNsPtr) | |
| 5617 xmlMalloc(sizeof(xmlSchemaWildcardNs)); | |
| 5618 if (ret == NULL) { | |
| 5619 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL
); | |
| 5620 return (NULL); | |
| 5621 } | |
| 5622 ret->value = NULL; | |
| 5623 ret->next = NULL; | |
| 5624 return (ret); | |
| 5625 } | |
| 5626 | |
| 5627 static xmlSchemaIDCPtr | |
| 5628 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 5629 const xmlChar *name, const xmlChar *nsName, | |
| 5630 int category, xmlNodePtr node) | |
| 5631 { | |
| 5632 xmlSchemaIDCPtr ret = NULL; | |
| 5633 | |
| 5634 if ((ctxt == NULL) || (schema == NULL) || (name == NULL)) | |
| 5635 return (NULL); | |
| 5636 | |
| 5637 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC)); | |
| 5638 if (ret == NULL) { | |
| 5639 xmlSchemaPErrMemory(ctxt, | |
| 5640 "allocating an identity-constraint definition", NULL); | |
| 5641 return (NULL); | |
| 5642 } | |
| 5643 memset(ret, 0, sizeof(xmlSchemaIDC)); | |
| 5644 /* The target namespace of the parent element declaration. */ | |
| 5645 ret->targetNamespace = nsName; | |
| 5646 ret->name = name; | |
| 5647 ret->type = category; | |
| 5648 ret->node = node; | |
| 5649 | |
| 5650 WXS_ADD_GLOBAL(ctxt, ret); | |
| 5651 /* | |
| 5652 * Only keyrefs need to be fixup up. | |
| 5653 */ | |
| 5654 if (category == XML_SCHEMA_TYPE_IDC_KEYREF) | |
| 5655 WXS_ADD_PENDING(ctxt, ret); | |
| 5656 return (ret); | |
| 5657 } | |
| 5658 | |
| 5659 /** | |
| 5660 * xmlSchemaAddWildcard: | |
| 5661 * @ctxt: a schema validation context | |
| 5662 * @schema: a schema | |
| 5663 * | |
| 5664 * Adds a wildcard. | |
| 5665 * It corresponds to a xsd:anyAttribute and xsd:any. | |
| 5666 * | |
| 5667 * Returns the new struture or NULL in case of error | |
| 5668 */ | |
| 5669 static xmlSchemaWildcardPtr | |
| 5670 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 5671 xmlSchemaTypeType type, xmlNodePtr node) | |
| 5672 { | |
| 5673 xmlSchemaWildcardPtr ret = NULL; | |
| 5674 | |
| 5675 if ((ctxt == NULL) || (schema == NULL)) | |
| 5676 return (NULL); | |
| 5677 | |
| 5678 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard)); | |
| 5679 if (ret == NULL) { | |
| 5680 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL); | |
| 5681 return (NULL); | |
| 5682 } | |
| 5683 memset(ret, 0, sizeof(xmlSchemaWildcard)); | |
| 5684 ret->type = type; | |
| 5685 ret->node = node; | |
| 5686 WXS_ADD_LOCAL(ctxt, ret); | |
| 5687 return (ret); | |
| 5688 } | |
| 5689 | |
| 5690 static void | |
| 5691 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group) | |
| 5692 { | |
| 5693 if (group == NULL) | |
| 5694 return; | |
| 5695 if (group->members != NULL) | |
| 5696 xmlSchemaItemListFree(group->members); | |
| 5697 xmlFree(group); | |
| 5698 } | |
| 5699 | |
| 5700 static xmlSchemaSubstGroupPtr | |
| 5701 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt, | |
| 5702 xmlSchemaElementPtr head) | |
| 5703 { | |
| 5704 xmlSchemaSubstGroupPtr ret; | |
| 5705 | |
| 5706 /* Init subst group hash. */ | |
| 5707 if (WXS_SUBST_GROUPS(pctxt) == NULL) { | |
| 5708 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict); | |
| 5709 if (WXS_SUBST_GROUPS(pctxt) == NULL) | |
| 5710 return(NULL); | |
| 5711 } | |
| 5712 /* Create a new substitution group. */ | |
| 5713 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup)); | |
| 5714 if (ret == NULL) { | |
| 5715 xmlSchemaPErrMemory(NULL, | |
| 5716 "allocating a substitution group container", NULL); | |
| 5717 return(NULL); | |
| 5718 } | |
| 5719 memset(ret, 0, sizeof(xmlSchemaSubstGroup)); | |
| 5720 ret->head = head; | |
| 5721 /* Create list of members. */ | |
| 5722 ret->members = xmlSchemaItemListCreate(); | |
| 5723 if (ret->members == NULL) { | |
| 5724 xmlSchemaSubstGroupFree(ret); | |
| 5725 return(NULL); | |
| 5726 } | |
| 5727 /* Add subst group to hash. */ | |
| 5728 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt), | |
| 5729 head->name, head->targetNamespace, ret) != 0) { | |
| 5730 PERROR_INT("xmlSchemaSubstGroupAdd", | |
| 5731 "failed to add a new substitution container"); | |
| 5732 xmlSchemaSubstGroupFree(ret); | |
| 5733 return(NULL); | |
| 5734 } | |
| 5735 return(ret); | |
| 5736 } | |
| 5737 | |
| 5738 static xmlSchemaSubstGroupPtr | |
| 5739 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt, | |
| 5740 xmlSchemaElementPtr head) | |
| 5741 { | |
| 5742 if (WXS_SUBST_GROUPS(pctxt) == NULL) | |
| 5743 return(NULL); | |
| 5744 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt), | |
| 5745 head->name, head->targetNamespace)); | |
| 5746 | |
| 5747 } | |
| 5748 | |
| 5749 /** | |
| 5750 * xmlSchemaAddElementSubstitutionMember: | |
| 5751 * @pctxt: a schema parser context | |
| 5752 * @head: the head of the substitution group | |
| 5753 * @member: the new member of the substitution group | |
| 5754 * | |
| 5755 * Allocate a new annotation structure. | |
| 5756 * | |
| 5757 * Returns the newly allocated structure or NULL in case or error | |
| 5758 */ | |
| 5759 static int | |
| 5760 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt, | |
| 5761 xmlSchemaElementPtr head, | |
| 5762 xmlSchemaElementPtr member) | |
| 5763 { | |
| 5764 xmlSchemaSubstGroupPtr substGroup = NULL; | |
| 5765 | |
| 5766 if ((pctxt == NULL) || (head == NULL) || (member == NULL)) | |
| 5767 return (-1); | |
| 5768 | |
| 5769 substGroup = xmlSchemaSubstGroupGet(pctxt, head); | |
| 5770 if (substGroup == NULL) | |
| 5771 substGroup = xmlSchemaSubstGroupAdd(pctxt, head); | |
| 5772 if (substGroup == NULL) | |
| 5773 return(-1); | |
| 5774 if (xmlSchemaItemListAdd(substGroup->members, member) == -1) | |
| 5775 return(-1); | |
| 5776 return(0); | |
| 5777 } | |
| 5778 | |
| 5779 /************************************************************************ | |
| 5780 * * | |
| 5781 * Utilities for parsing * | |
| 5782 * * | |
| 5783 ************************************************************************/ | |
| 5784 | |
| 5785 /** | |
| 5786 * xmlSchemaPValAttrNodeQNameValue: | |
| 5787 * @ctxt: a schema parser context | |
| 5788 * @schema: the schema context | |
| 5789 * @ownerDes: the designation of the parent element | |
| 5790 * @ownerItem: the parent as a schema object | |
| 5791 * @value: the QName value | |
| 5792 * @local: the resulting local part if found, the attribute value otherwise | |
| 5793 * @uri: the resulting namespace URI if found | |
| 5794 * | |
| 5795 * Extracts the local name and the URI of a QName value and validates it. | |
| 5796 * This one is intended to be used on attribute values that | |
| 5797 * should resolve to schema components. | |
| 5798 * | |
| 5799 * Returns 0, in case the QName is valid, a positive error code | |
| 5800 * if not valid and -1 if an internal error occurs. | |
| 5801 */ | |
| 5802 static int | |
| 5803 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt, | |
| 5804 xmlSchemaPtr schema, | |
| 5805 xmlSchemaBasicItemPtr ownerItem, | |
| 5806 xmlAttrPtr attr, | |
| 5807 const xmlChar *value, | |
| 5808 const xmlChar **uri, | |
| 5809 const xmlChar **local) | |
| 5810 { | |
| 5811 const xmlChar *pref; | |
| 5812 xmlNsPtr ns; | |
| 5813 int len, ret; | |
| 5814 | |
| 5815 *uri = NULL; | |
| 5816 *local = NULL; | |
| 5817 ret = xmlValidateQName(value, 1); | |
| 5818 if (ret > 0) { | |
| 5819 xmlSchemaPSimpleTypeErr(ctxt, | |
| 5820 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 5821 ownerItem, (xmlNodePtr) attr, | |
| 5822 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), | |
| 5823 NULL, value, NULL, NULL, NULL); | |
| 5824 *local = value; | |
| 5825 return (ctxt->err); | |
| 5826 } else if (ret < 0) | |
| 5827 return (-1); | |
| 5828 | |
| 5829 if (!strchr((char *) value, ':')) { | |
| 5830 ns = xmlSearchNs(attr->doc, attr->parent, NULL); | |
| 5831 if (ns) | |
| 5832 *uri = xmlDictLookup(ctxt->dict, ns->href, -1); | |
| 5833 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) { | |
| 5834 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the | |
| 5835 * parser context. */ | |
| 5836 /* | |
| 5837 * This one takes care of included schemas with no | |
| 5838 * target namespace. | |
| 5839 */ | |
| 5840 *uri = ctxt->targetNamespace; | |
| 5841 } | |
| 5842 *local = xmlDictLookup(ctxt->dict, value, -1); | |
| 5843 return (0); | |
| 5844 } | |
| 5845 /* | |
| 5846 * At this point xmlSplitQName3 has to return a local name. | |
| 5847 */ | |
| 5848 *local = xmlSplitQName3(value, &len); | |
| 5849 *local = xmlDictLookup(ctxt->dict, *local, -1); | |
| 5850 pref = xmlDictLookup(ctxt->dict, value, len); | |
| 5851 ns = xmlSearchNs(attr->doc, attr->parent, pref); | |
| 5852 if (ns == NULL) { | |
| 5853 xmlSchemaPSimpleTypeErr(ctxt, | |
| 5854 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 5855 ownerItem, (xmlNodePtr) attr, | |
| 5856 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value, | |
| 5857 "The value '%s' of simple type 'xs:QName' has no " | |
| 5858 "corresponding namespace declaration in scope", value, NULL); | |
| 5859 return (ctxt->err); | |
| 5860 } else { | |
| 5861 *uri = xmlDictLookup(ctxt->dict, ns->href, -1); | |
| 5862 } | |
| 5863 return (0); | |
| 5864 } | |
| 5865 | |
| 5866 /** | |
| 5867 * xmlSchemaPValAttrNodeQName: | |
| 5868 * @ctxt: a schema parser context | |
| 5869 * @schema: the schema context | |
| 5870 * @ownerDes: the designation of the owner element | |
| 5871 * @ownerItem: the owner as a schema object | |
| 5872 * @attr: the attribute node | |
| 5873 * @local: the resulting local part if found, the attribute value otherwise | |
| 5874 * @uri: the resulting namespace URI if found | |
| 5875 * | |
| 5876 * Extracts and validates the QName of an attribute value. | |
| 5877 * This one is intended to be used on attribute values that | |
| 5878 * should resolve to schema components. | |
| 5879 * | |
| 5880 * Returns 0, in case the QName is valid, a positive error code | |
| 5881 * if not valid and -1 if an internal error occurs. | |
| 5882 */ | |
| 5883 static int | |
| 5884 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt, | |
| 5885 xmlSchemaPtr schema, | |
| 5886 xmlSchemaBasicItemPtr ownerItem, | |
| 5887 xmlAttrPtr attr, | |
| 5888 const xmlChar **uri, | |
| 5889 const xmlChar **local) | |
| 5890 { | |
| 5891 const xmlChar *value; | |
| 5892 | |
| 5893 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 5894 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, | |
| 5895 ownerItem, attr, value, uri, local)); | |
| 5896 } | |
| 5897 | |
| 5898 /** | |
| 5899 * xmlSchemaPValAttrQName: | |
| 5900 * @ctxt: a schema parser context | |
| 5901 * @schema: the schema context | |
| 5902 * @ownerDes: the designation of the parent element | |
| 5903 * @ownerItem: the owner as a schema object | |
| 5904 * @ownerElem: the parent node of the attribute | |
| 5905 * @name: the name of the attribute | |
| 5906 * @local: the resulting local part if found, the attribute value otherwise | |
| 5907 * @uri: the resulting namespace URI if found | |
| 5908 * | |
| 5909 * Extracts and validates the QName of an attribute value. | |
| 5910 * | |
| 5911 * Returns 0, in case the QName is valid, a positive error code | |
| 5912 * if not valid and -1 if an internal error occurs. | |
| 5913 */ | |
| 5914 static int | |
| 5915 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt, | |
| 5916 xmlSchemaPtr schema, | |
| 5917 xmlSchemaBasicItemPtr ownerItem, | |
| 5918 xmlNodePtr ownerElem, | |
| 5919 const char *name, | |
| 5920 const xmlChar **uri, | |
| 5921 const xmlChar **local) | |
| 5922 { | |
| 5923 xmlAttrPtr attr; | |
| 5924 | |
| 5925 attr = xmlSchemaGetPropNode(ownerElem, name); | |
| 5926 if (attr == NULL) { | |
| 5927 *local = NULL; | |
| 5928 *uri = NULL; | |
| 5929 return (0); | |
| 5930 } | |
| 5931 return (xmlSchemaPValAttrNodeQName(ctxt, schema, | |
| 5932 ownerItem, attr, uri, local)); | |
| 5933 } | |
| 5934 | |
| 5935 /** | |
| 5936 * xmlSchemaPValAttrID: | |
| 5937 * @ctxt: a schema parser context | |
| 5938 * @schema: the schema context | |
| 5939 * @ownerDes: the designation of the parent element | |
| 5940 * @ownerItem: the owner as a schema object | |
| 5941 * @ownerElem: the parent node of the attribute | |
| 5942 * @name: the name of the attribute | |
| 5943 * | |
| 5944 * Extracts and validates the ID of an attribute value. | |
| 5945 * | |
| 5946 * Returns 0, in case the ID is valid, a positive error code | |
| 5947 * if not valid and -1 if an internal error occurs. | |
| 5948 */ | |
| 5949 static int | |
| 5950 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr) | |
| 5951 { | |
| 5952 int ret; | |
| 5953 const xmlChar *value; | |
| 5954 | |
| 5955 if (attr == NULL) | |
| 5956 return(0); | |
| 5957 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr); | |
| 5958 ret = xmlValidateNCName(value, 1); | |
| 5959 if (ret == 0) { | |
| 5960 /* | |
| 5961 * NOTE: the IDness might have already be declared in the DTD | |
| 5962 */ | |
| 5963 if (attr->atype != XML_ATTRIBUTE_ID) { | |
| 5964 xmlIDPtr res; | |
| 5965 xmlChar *strip; | |
| 5966 | |
| 5967 /* | |
| 5968 * TODO: Use xmlSchemaStrip here; it's not exported at this | |
| 5969 * moment. | |
| 5970 */ | |
| 5971 strip = xmlSchemaCollapseString(value); | |
| 5972 if (strip != NULL) { | |
| 5973 xmlFree((xmlChar *) value); | |
| 5974 value = strip; | |
| 5975 } | |
| 5976 res = xmlAddID(NULL, attr->doc, value, attr); | |
| 5977 if (res == NULL) { | |
| 5978 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; | |
| 5979 xmlSchemaPSimpleTypeErr(ctxt, | |
| 5980 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 5981 NULL, (xmlNodePtr) attr, | |
| 5982 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID), | |
| 5983 NULL, NULL, "Duplicate value '%s' of simple " | |
| 5984 "type 'xs:ID'", value, NULL); | |
| 5985 } else | |
| 5986 attr->atype = XML_ATTRIBUTE_ID; | |
| 5987 } | |
| 5988 } else if (ret > 0) { | |
| 5989 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; | |
| 5990 xmlSchemaPSimpleTypeErr(ctxt, | |
| 5991 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 5992 NULL, (xmlNodePtr) attr, | |
| 5993 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID), | |
| 5994 NULL, NULL, "The value '%s' of simple type 'xs:ID' is " | |
| 5995 "not a valid 'xs:NCName'", | |
| 5996 value, NULL); | |
| 5997 } | |
| 5998 if (value != NULL) | |
| 5999 xmlFree((xmlChar *)value); | |
| 6000 | |
| 6001 return (ret); | |
| 6002 } | |
| 6003 | |
| 6004 static int | |
| 6005 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt, | |
| 6006 xmlNodePtr ownerElem, | |
| 6007 const xmlChar *name) | |
| 6008 { | |
| 6009 xmlAttrPtr attr; | |
| 6010 | |
| 6011 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name); | |
| 6012 if (attr == NULL) | |
| 6013 return(0); | |
| 6014 return(xmlSchemaPValAttrNodeID(ctxt, attr)); | |
| 6015 | |
| 6016 } | |
| 6017 | |
| 6018 /** | |
| 6019 * xmlGetMaxOccurs: | |
| 6020 * @ctxt: a schema validation context | |
| 6021 * @node: a subtree containing XML Schema informations | |
| 6022 * | |
| 6023 * Get the maxOccurs property | |
| 6024 * | |
| 6025 * Returns the default if not found, or the value | |
| 6026 */ | |
| 6027 static int | |
| 6028 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, | |
| 6029 int min, int max, int def, const char *expected) | |
| 6030 { | |
| 6031 const xmlChar *val, *cur; | |
| 6032 int ret = 0; | |
| 6033 xmlAttrPtr attr; | |
| 6034 | |
| 6035 attr = xmlSchemaGetPropNode(node, "maxOccurs"); | |
| 6036 if (attr == NULL) | |
| 6037 return (def); | |
| 6038 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 6039 | |
| 6040 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) { | |
| 6041 if (max != UNBOUNDED) { | |
| 6042 xmlSchemaPSimpleTypeErr(ctxt, | |
| 6043 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 6044 /* XML_SCHEMAP_INVALID_MINOCCURS, */ | |
| 6045 NULL, (xmlNodePtr) attr, NULL, expected, | |
| 6046 val, NULL, NULL, NULL); | |
| 6047 return (def); | |
| 6048 } else | |
| 6049 return (UNBOUNDED); /* encoding it with -1 might be another option
*/ | |
| 6050 } | |
| 6051 | |
| 6052 cur = val; | |
| 6053 while (IS_BLANK_CH(*cur)) | |
| 6054 cur++; | |
| 6055 if (*cur == 0) { | |
| 6056 xmlSchemaPSimpleTypeErr(ctxt, | |
| 6057 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 6058 /* XML_SCHEMAP_INVALID_MINOCCURS, */ | |
| 6059 NULL, (xmlNodePtr) attr, NULL, expected, | |
| 6060 val, NULL, NULL, NULL); | |
| 6061 return (def); | |
| 6062 } | |
| 6063 while ((*cur >= '0') && (*cur <= '9')) { | |
| 6064 ret = ret * 10 + (*cur - '0'); | |
| 6065 cur++; | |
| 6066 } | |
| 6067 while (IS_BLANK_CH(*cur)) | |
| 6068 cur++; | |
| 6069 /* | |
| 6070 * TODO: Restrict the maximal value to Integer. | |
| 6071 */ | |
| 6072 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) { | |
| 6073 xmlSchemaPSimpleTypeErr(ctxt, | |
| 6074 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 6075 /* XML_SCHEMAP_INVALID_MINOCCURS, */ | |
| 6076 NULL, (xmlNodePtr) attr, NULL, expected, | |
| 6077 val, NULL, NULL, NULL); | |
| 6078 return (def); | |
| 6079 } | |
| 6080 return (ret); | |
| 6081 } | |
| 6082 | |
| 6083 /** | |
| 6084 * xmlGetMinOccurs: | |
| 6085 * @ctxt: a schema validation context | |
| 6086 * @node: a subtree containing XML Schema informations | |
| 6087 * | |
| 6088 * Get the minOccurs property | |
| 6089 * | |
| 6090 * Returns the default if not found, or the value | |
| 6091 */ | |
| 6092 static int | |
| 6093 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, | |
| 6094 int min, int max, int def, const char *expected) | |
| 6095 { | |
| 6096 const xmlChar *val, *cur; | |
| 6097 int ret = 0; | |
| 6098 xmlAttrPtr attr; | |
| 6099 | |
| 6100 attr = xmlSchemaGetPropNode(node, "minOccurs"); | |
| 6101 if (attr == NULL) | |
| 6102 return (def); | |
| 6103 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 6104 cur = val; | |
| 6105 while (IS_BLANK_CH(*cur)) | |
| 6106 cur++; | |
| 6107 if (*cur == 0) { | |
| 6108 xmlSchemaPSimpleTypeErr(ctxt, | |
| 6109 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 6110 /* XML_SCHEMAP_INVALID_MINOCCURS, */ | |
| 6111 NULL, (xmlNodePtr) attr, NULL, expected, | |
| 6112 val, NULL, NULL, NULL); | |
| 6113 return (def); | |
| 6114 } | |
| 6115 while ((*cur >= '0') && (*cur <= '9')) { | |
| 6116 ret = ret * 10 + (*cur - '0'); | |
| 6117 cur++; | |
| 6118 } | |
| 6119 while (IS_BLANK_CH(*cur)) | |
| 6120 cur++; | |
| 6121 /* | |
| 6122 * TODO: Restrict the maximal value to Integer. | |
| 6123 */ | |
| 6124 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) { | |
| 6125 xmlSchemaPSimpleTypeErr(ctxt, | |
| 6126 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 6127 /* XML_SCHEMAP_INVALID_MINOCCURS, */ | |
| 6128 NULL, (xmlNodePtr) attr, NULL, expected, | |
| 6129 val, NULL, NULL, NULL); | |
| 6130 return (def); | |
| 6131 } | |
| 6132 return (ret); | |
| 6133 } | |
| 6134 | |
| 6135 /** | |
| 6136 * xmlSchemaPGetBoolNodeValue: | |
| 6137 * @ctxt: a schema validation context | |
| 6138 * @ownerDes: owner designation | |
| 6139 * @ownerItem: the owner as a schema item | |
| 6140 * @node: the node holding the value | |
| 6141 * | |
| 6142 * Converts a boolean string value into 1 or 0. | |
| 6143 * | |
| 6144 * Returns 0 or 1. | |
| 6145 */ | |
| 6146 static int | |
| 6147 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt, | |
| 6148 xmlSchemaBasicItemPtr ownerItem, | |
| 6149 xmlNodePtr node) | |
| 6150 { | |
| 6151 xmlChar *value = NULL; | |
| 6152 int res = 0; | |
| 6153 | |
| 6154 value = xmlNodeGetContent(node); | |
| 6155 /* | |
| 6156 * 3.2.2.1 Lexical representation | |
| 6157 * An instance of a datatype that is defined as `boolean` | |
| 6158 * can have the following legal literals {true, false, 1, 0}. | |
| 6159 */ | |
| 6160 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true")) | |
| 6161 res = 1; | |
| 6162 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false")) | |
| 6163 res = 0; | |
| 6164 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1")) | |
| 6165 res = 1; | |
| 6166 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0")) | |
| 6167 res = 0; | |
| 6168 else { | |
| 6169 xmlSchemaPSimpleTypeErr(ctxt, | |
| 6170 XML_SCHEMAP_INVALID_BOOLEAN, | |
| 6171 ownerItem, node, | |
| 6172 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN), | |
| 6173 NULL, BAD_CAST value, | |
| 6174 NULL, NULL, NULL); | |
| 6175 } | |
| 6176 if (value != NULL) | |
| 6177 xmlFree(value); | |
| 6178 return (res); | |
| 6179 } | |
| 6180 | |
| 6181 /** | |
| 6182 * xmlGetBooleanProp: | |
| 6183 * @ctxt: a schema validation context | |
| 6184 * @node: a subtree containing XML Schema informations | |
| 6185 * @name: the attribute name | |
| 6186 * @def: the default value | |
| 6187 * | |
| 6188 * Evaluate if a boolean property is set | |
| 6189 * | |
| 6190 * Returns the default if not found, 0 if found to be false, | |
| 6191 * 1 if found to be true | |
| 6192 */ | |
| 6193 static int | |
| 6194 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, | |
| 6195 xmlNodePtr node, | |
| 6196 const char *name, int def) | |
| 6197 { | |
| 6198 const xmlChar *val; | |
| 6199 | |
| 6200 val = xmlSchemaGetProp(ctxt, node, name); | |
| 6201 if (val == NULL) | |
| 6202 return (def); | |
| 6203 /* | |
| 6204 * 3.2.2.1 Lexical representation | |
| 6205 * An instance of a datatype that is defined as `boolean` | |
| 6206 * can have the following legal literals {true, false, 1, 0}. | |
| 6207 */ | |
| 6208 if (xmlStrEqual(val, BAD_CAST "true")) | |
| 6209 def = 1; | |
| 6210 else if (xmlStrEqual(val, BAD_CAST "false")) | |
| 6211 def = 0; | |
| 6212 else if (xmlStrEqual(val, BAD_CAST "1")) | |
| 6213 def = 1; | |
| 6214 else if (xmlStrEqual(val, BAD_CAST "0")) | |
| 6215 def = 0; | |
| 6216 else { | |
| 6217 xmlSchemaPSimpleTypeErr(ctxt, | |
| 6218 XML_SCHEMAP_INVALID_BOOLEAN, | |
| 6219 NULL, | |
| 6220 (xmlNodePtr) xmlSchemaGetPropNode(node, name), | |
| 6221 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN), | |
| 6222 NULL, val, NULL, NULL, NULL); | |
| 6223 } | |
| 6224 return (def); | |
| 6225 } | |
| 6226 | |
| 6227 /************************************************************************ | |
| 6228 * * | |
| 6229 * Shema extraction from an Infoset * | |
| 6230 * * | |
| 6231 ************************************************************************/ | |
| 6232 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr | |
| 6233 ctxt, xmlSchemaPtr schema, | |
| 6234 xmlNodePtr node, | |
| 6235 int topLevel); | |
| 6236 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr | |
| 6237 ctxt, | |
| 6238 xmlSchemaPtr schema, | |
| 6239 xmlNodePtr node, | |
| 6240 int topLevel); | |
| 6241 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr | |
| 6242 ctxt, | |
| 6243 xmlSchemaPtr schema, | |
| 6244 xmlNodePtr node, | |
| 6245 xmlSchemaTypeType parentType); | |
| 6246 static xmlSchemaBasicItemPtr | |
| 6247 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt, | |
| 6248 xmlSchemaPtr schema, | |
| 6249 xmlNodePtr node, | |
| 6250 xmlSchemaItemListPtr uses, | |
| 6251 int parentType); | |
| 6252 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, | |
| 6253 xmlSchemaPtr schema, | |
| 6254 xmlNodePtr node); | |
| 6255 static xmlSchemaWildcardPtr | |
| 6256 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, | |
| 6257 xmlSchemaPtr schema, xmlNodePtr node); | |
| 6258 | |
| 6259 /** | |
| 6260 * xmlSchemaPValAttrNodeValue: | |
| 6261 * | |
| 6262 * @ctxt: a schema parser context | |
| 6263 * @ownerDes: the designation of the parent element | |
| 6264 * @ownerItem: the schema object owner if existent | |
| 6265 * @attr: the schema attribute node being validated | |
| 6266 * @value: the value | |
| 6267 * @type: the built-in type to be validated against | |
| 6268 * | |
| 6269 * Validates a value against the given built-in type. | |
| 6270 * This one is intended to be used internally for validation | |
| 6271 * of schema attribute values during parsing of the schema. | |
| 6272 * | |
| 6273 * Returns 0 if the value is valid, a positive error code | |
| 6274 * number otherwise and -1 in case of an internal or API error. | |
| 6275 */ | |
| 6276 static int | |
| 6277 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt, | |
| 6278 xmlSchemaBasicItemPtr ownerItem, | |
| 6279 xmlAttrPtr attr, | |
| 6280 const xmlChar *value, | |
| 6281 xmlSchemaTypePtr type) | |
| 6282 { | |
| 6283 | |
| 6284 int ret = 0; | |
| 6285 | |
| 6286 /* | |
| 6287 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this | |
| 6288 * one is really meant to be used internally, so better not. | |
| 6289 */ | |
| 6290 if ((pctxt == NULL) || (type == NULL) || (attr == NULL)) | |
| 6291 return (-1); | |
| 6292 if (type->type != XML_SCHEMA_TYPE_BASIC) { | |
| 6293 PERROR_INT("xmlSchemaPValAttrNodeValue", | |
| 6294 "the given type is not a built-in type"); | |
| 6295 return (-1); | |
| 6296 } | |
| 6297 switch (type->builtInType) { | |
| 6298 case XML_SCHEMAS_NCNAME: | |
| 6299 case XML_SCHEMAS_QNAME: | |
| 6300 case XML_SCHEMAS_ANYURI: | |
| 6301 case XML_SCHEMAS_TOKEN: | |
| 6302 case XML_SCHEMAS_LANGUAGE: | |
| 6303 ret = xmlSchemaValPredefTypeNode(type, value, NULL, | |
| 6304 (xmlNodePtr) attr); | |
| 6305 break; | |
| 6306 default: { | |
| 6307 PERROR_INT("xmlSchemaPValAttrNodeValue", | |
| 6308 "validation using the given type is not supported while " | |
| 6309 "parsing a schema"); | |
| 6310 return (-1); | |
| 6311 } | |
| 6312 } | |
| 6313 /* | |
| 6314 * TODO: Should we use the S4S error codes instead? | |
| 6315 */ | |
| 6316 if (ret < 0) { | |
| 6317 PERROR_INT("xmlSchemaPValAttrNodeValue", | |
| 6318 "failed to validate a schema attribute value"); | |
| 6319 return (-1); | |
| 6320 } else if (ret > 0) { | |
| 6321 if (WXS_IS_LIST(type)) | |
| 6322 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; | |
| 6323 else | |
| 6324 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; | |
| 6325 xmlSchemaPSimpleTypeErr(pctxt, | |
| 6326 ret, ownerItem, (xmlNodePtr) attr, | |
| 6327 type, NULL, value, NULL, NULL, NULL); | |
| 6328 } | |
| 6329 return (ret); | |
| 6330 } | |
| 6331 | |
| 6332 /** | |
| 6333 * xmlSchemaPValAttrNode: | |
| 6334 * | |
| 6335 * @ctxt: a schema parser context | |
| 6336 * @ownerDes: the designation of the parent element | |
| 6337 * @ownerItem: the schema object owner if existent | |
| 6338 * @attr: the schema attribute node being validated | |
| 6339 * @type: the built-in type to be validated against | |
| 6340 * @value: the resulting value if any | |
| 6341 * | |
| 6342 * Extracts and validates a value against the given built-in type. | |
| 6343 * This one is intended to be used internally for validation | |
| 6344 * of schema attribute values during parsing of the schema. | |
| 6345 * | |
| 6346 * Returns 0 if the value is valid, a positive error code | |
| 6347 * number otherwise and -1 in case of an internal or API error. | |
| 6348 */ | |
| 6349 static int | |
| 6350 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt, | |
| 6351 xmlSchemaBasicItemPtr ownerItem, | |
| 6352 xmlAttrPtr attr, | |
| 6353 xmlSchemaTypePtr type, | |
| 6354 const xmlChar **value) | |
| 6355 { | |
| 6356 const xmlChar *val; | |
| 6357 | |
| 6358 if ((ctxt == NULL) || (type == NULL) || (attr == NULL)) | |
| 6359 return (-1); | |
| 6360 | |
| 6361 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 6362 if (value != NULL) | |
| 6363 *value = val; | |
| 6364 | |
| 6365 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr, | |
| 6366 val, type)); | |
| 6367 } | |
| 6368 | |
| 6369 /** | |
| 6370 * xmlSchemaPValAttr: | |
| 6371 * | |
| 6372 * @ctxt: a schema parser context | |
| 6373 * @node: the element node of the attribute | |
| 6374 * @ownerDes: the designation of the parent element | |
| 6375 * @ownerItem: the schema object owner if existent | |
| 6376 * @ownerElem: the owner element node | |
| 6377 * @name: the name of the schema attribute node | |
| 6378 * @type: the built-in type to be validated against | |
| 6379 * @value: the resulting value if any | |
| 6380 * | |
| 6381 * Extracts and validates a value against the given built-in type. | |
| 6382 * This one is intended to be used internally for validation | |
| 6383 * of schema attribute values during parsing of the schema. | |
| 6384 * | |
| 6385 * Returns 0 if the value is valid, a positive error code | |
| 6386 * number otherwise and -1 in case of an internal or API error. | |
| 6387 */ | |
| 6388 static int | |
| 6389 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt, | |
| 6390 xmlSchemaBasicItemPtr ownerItem, | |
| 6391 xmlNodePtr ownerElem, | |
| 6392 const char *name, | |
| 6393 xmlSchemaTypePtr type, | |
| 6394 const xmlChar **value) | |
| 6395 { | |
| 6396 xmlAttrPtr attr; | |
| 6397 | |
| 6398 if ((ctxt == NULL) || (type == NULL)) { | |
| 6399 if (value != NULL) | |
| 6400 *value = NULL; | |
| 6401 return (-1); | |
| 6402 } | |
| 6403 if (type->type != XML_SCHEMA_TYPE_BASIC) { | |
| 6404 if (value != NULL) | |
| 6405 *value = NULL; | |
| 6406 xmlSchemaPErr(ctxt, ownerElem, | |
| 6407 XML_SCHEMAP_INTERNAL, | |
| 6408 "Internal error: xmlSchemaPValAttr, the given " | |
| 6409 "type '%s' is not a built-in type.\n", | |
| 6410 type->name, NULL); | |
| 6411 return (-1); | |
| 6412 } | |
| 6413 attr = xmlSchemaGetPropNode(ownerElem, name); | |
| 6414 if (attr == NULL) { | |
| 6415 if (value != NULL) | |
| 6416 *value = NULL; | |
| 6417 return (0); | |
| 6418 } | |
| 6419 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr, | |
| 6420 type, value)); | |
| 6421 } | |
| 6422 | |
| 6423 static int | |
| 6424 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt, | |
| 6425 xmlSchemaPtr schema ATTRIBUTE_UNUSED, | |
| 6426 xmlNodePtr node, | |
| 6427 xmlAttrPtr attr, | |
| 6428 const xmlChar *namespaceName) | |
| 6429 { | |
| 6430 /* TODO: Pointer comparison instead? */ | |
| 6431 if (xmlStrEqual(pctxt->targetNamespace, namespaceName)) | |
| 6432 return (0); | |
| 6433 if (xmlStrEqual(xmlSchemaNs, namespaceName)) | |
| 6434 return (0); | |
| 6435 /* | |
| 6436 * Check if the referenced namespace was <import>ed. | |
| 6437 */ | |
| 6438 if (WXS_BUCKET(pctxt)->relations != NULL) { | |
| 6439 xmlSchemaSchemaRelationPtr rel; | |
| 6440 | |
| 6441 rel = WXS_BUCKET(pctxt)->relations; | |
| 6442 do { | |
| 6443 if (WXS_IS_BUCKET_IMPMAIN(rel->type) && | |
| 6444 xmlStrEqual(namespaceName, rel->importNamespace)) | |
| 6445 return (0); | |
| 6446 rel = rel->next; | |
| 6447 } while (rel != NULL); | |
| 6448 } | |
| 6449 /* | |
| 6450 * No matching <import>ed namespace found. | |
| 6451 */ | |
| 6452 { | |
| 6453 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node; | |
| 6454 | |
| 6455 if (namespaceName == NULL) | |
| 6456 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 6457 XML_SCHEMAP_SRC_RESOLVE, n, NULL, | |
| 6458 "References from this schema to components in no " | |
| 6459 "namespace are not allowed, since not indicated by an " | |
| 6460 "import statement", NULL, NULL); | |
| 6461 else | |
| 6462 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 6463 XML_SCHEMAP_SRC_RESOLVE, n, NULL, | |
| 6464 "References from this schema to components in the " | |
| 6465 "namespace '%s' are not allowed, since not indicated by an " | |
| 6466 "import statement", namespaceName, NULL); | |
| 6467 } | |
| 6468 return (XML_SCHEMAP_SRC_RESOLVE); | |
| 6469 } | |
| 6470 | |
| 6471 /** | |
| 6472 * xmlSchemaParseLocalAttributes: | |
| 6473 * @ctxt: a schema validation context | |
| 6474 * @schema: the schema being built | |
| 6475 * @node: a subtree containing XML Schema informations | |
| 6476 * @type: the hosting type where the attributes will be anchored | |
| 6477 * | |
| 6478 * Parses attribute uses and attribute declarations and | |
| 6479 * attribute group references. | |
| 6480 */ | |
| 6481 static int | |
| 6482 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 6483 xmlNodePtr *child, xmlSchemaItemListPtr *list, | |
| 6484 int parentType, int *hasRefs) | |
| 6485 { | |
| 6486 void *item; | |
| 6487 | |
| 6488 while ((IS_SCHEMA((*child), "attribute")) || | |
| 6489 (IS_SCHEMA((*child), "attributeGroup"))) { | |
| 6490 if (IS_SCHEMA((*child), "attribute")) { | |
| 6491 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child, | |
| 6492 *list, parentType); | |
| 6493 } else { | |
| 6494 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child); | |
| 6495 if ((item != NULL) && (hasRefs != NULL)) | |
| 6496 *hasRefs = 1; | |
| 6497 } | |
| 6498 if (item != NULL) { | |
| 6499 if (*list == NULL) { | |
| 6500 /* TODO: Customize grow factor. */ | |
| 6501 *list = xmlSchemaItemListCreate(); | |
| 6502 if (*list == NULL) | |
| 6503 return(-1); | |
| 6504 } | |
| 6505 if (xmlSchemaItemListAddSize(*list, 2, item) == -1) | |
| 6506 return(-1); | |
| 6507 } | |
| 6508 *child = (*child)->next; | |
| 6509 } | |
| 6510 return (0); | |
| 6511 } | |
| 6512 | |
| 6513 /** | |
| 6514 * xmlSchemaParseAnnotation: | |
| 6515 * @ctxt: a schema validation context | |
| 6516 * @schema: the schema being built | |
| 6517 * @node: a subtree containing XML Schema informations | |
| 6518 * | |
| 6519 * parse a XML schema Attrribute declaration | |
| 6520 * *WARNING* this interface is highly subject to change | |
| 6521 * | |
| 6522 * Returns -1 in case of error, 0 if the declaration is improper and | |
| 6523 * 1 in case of success. | |
| 6524 */ | |
| 6525 static xmlSchemaAnnotPtr | |
| 6526 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int neede
d) | |
| 6527 { | |
| 6528 xmlSchemaAnnotPtr ret; | |
| 6529 xmlNodePtr child = NULL; | |
| 6530 xmlAttrPtr attr; | |
| 6531 int barked = 0; | |
| 6532 | |
| 6533 /* | |
| 6534 * INFO: S4S completed. | |
| 6535 */ | |
| 6536 /* | |
| 6537 * id = ID | |
| 6538 * {any attributes with non-schema namespace . . .}> | |
| 6539 * Content: (appinfo | documentation)* | |
| 6540 */ | |
| 6541 if ((ctxt == NULL) || (node == NULL)) | |
| 6542 return (NULL); | |
| 6543 if (needed) | |
| 6544 ret = xmlSchemaNewAnnot(ctxt, node); | |
| 6545 else | |
| 6546 ret = NULL; | |
| 6547 attr = node->properties; | |
| 6548 while (attr != NULL) { | |
| 6549 if (((attr->ns == NULL) && | |
| 6550 (!xmlStrEqual(attr->name, BAD_CAST "id"))) || | |
| 6551 ((attr->ns != NULL) && | |
| 6552 xmlStrEqual(attr->ns->href, xmlSchemaNs))) { | |
| 6553 | |
| 6554 xmlSchemaPIllegalAttrErr(ctxt, | |
| 6555 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 6556 } | |
| 6557 attr = attr->next; | |
| 6558 } | |
| 6559 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 6560 /* | |
| 6561 * And now for the children... | |
| 6562 */ | |
| 6563 child = node->children; | |
| 6564 while (child != NULL) { | |
| 6565 if (IS_SCHEMA(child, "appinfo")) { | |
| 6566 /* TODO: make available the content of "appinfo". */ | |
| 6567 /* | |
| 6568 * source = anyURI | |
| 6569 * {any attributes with non-schema namespace . . .}> | |
| 6570 * Content: ({any})* | |
| 6571 */ | |
| 6572 attr = child->properties; | |
| 6573 while (attr != NULL) { | |
| 6574 if (((attr->ns == NULL) && | |
| 6575 (!xmlStrEqual(attr->name, BAD_CAST "source"))) || | |
| 6576 ((attr->ns != NULL) && | |
| 6577 xmlStrEqual(attr->ns->href, xmlSchemaNs))) { | |
| 6578 | |
| 6579 xmlSchemaPIllegalAttrErr(ctxt, | |
| 6580 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 6581 } | |
| 6582 attr = attr->next; | |
| 6583 } | |
| 6584 xmlSchemaPValAttr(ctxt, NULL, child, "source", | |
| 6585 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL); | |
| 6586 child = child->next; | |
| 6587 } else if (IS_SCHEMA(child, "documentation")) { | |
| 6588 /* TODO: make available the content of "documentation". */ | |
| 6589 /* | |
| 6590 * source = anyURI | |
| 6591 * {any attributes with non-schema namespace . . .}> | |
| 6592 * Content: ({any})* | |
| 6593 */ | |
| 6594 attr = child->properties; | |
| 6595 while (attr != NULL) { | |
| 6596 if (attr->ns == NULL) { | |
| 6597 if (!xmlStrEqual(attr->name, BAD_CAST "source")) { | |
| 6598 xmlSchemaPIllegalAttrErr(ctxt, | |
| 6599 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 6600 } | |
| 6601 } else { | |
| 6602 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) || | |
| 6603 (xmlStrEqual(attr->name, BAD_CAST "lang") && | |
| 6604 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) { | |
| 6605 | |
| 6606 xmlSchemaPIllegalAttrErr(ctxt, | |
| 6607 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 6608 } | |
| 6609 } | |
| 6610 attr = attr->next; | |
| 6611 } | |
| 6612 /* | |
| 6613 * Attribute "xml:lang". | |
| 6614 */ | |
| 6615 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPAC
E, "lang"); | |
| 6616 if (attr != NULL) | |
| 6617 xmlSchemaPValAttrNode(ctxt, NULL, attr, | |
| 6618 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL); | |
| 6619 child = child->next; | |
| 6620 } else { | |
| 6621 if (!barked) | |
| 6622 xmlSchemaPContentErr(ctxt, | |
| 6623 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 6624 NULL, node, child, NULL, "(appinfo | documentation)*"); | |
| 6625 barked = 1; | |
| 6626 child = child->next; | |
| 6627 } | |
| 6628 } | |
| 6629 | |
| 6630 return (ret); | |
| 6631 } | |
| 6632 | |
| 6633 /** | |
| 6634 * xmlSchemaParseFacet: | |
| 6635 * @ctxt: a schema validation context | |
| 6636 * @schema: the schema being built | |
| 6637 * @node: a subtree containing XML Schema informations | |
| 6638 * | |
| 6639 * parse a XML schema Facet declaration | |
| 6640 * *WARNING* this interface is highly subject to change | |
| 6641 * | |
| 6642 * Returns the new type structure or NULL in case of error | |
| 6643 */ | |
| 6644 static xmlSchemaFacetPtr | |
| 6645 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 6646 xmlNodePtr node) | |
| 6647 { | |
| 6648 xmlSchemaFacetPtr facet; | |
| 6649 xmlNodePtr child = NULL; | |
| 6650 const xmlChar *value; | |
| 6651 | |
| 6652 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 6653 return (NULL); | |
| 6654 | |
| 6655 facet = xmlSchemaNewFacet(); | |
| 6656 if (facet == NULL) { | |
| 6657 xmlSchemaPErrMemory(ctxt, "allocating facet", node); | |
| 6658 return (NULL); | |
| 6659 } | |
| 6660 facet->node = node; | |
| 6661 value = xmlSchemaGetProp(ctxt, node, "value"); | |
| 6662 if (value == NULL) { | |
| 6663 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE, | |
| 6664 "Facet %s has no value\n", node->name, NULL); | |
| 6665 xmlSchemaFreeFacet(facet); | |
| 6666 return (NULL); | |
| 6667 } | |
| 6668 if (IS_SCHEMA(node, "minInclusive")) { | |
| 6669 facet->type = XML_SCHEMA_FACET_MININCLUSIVE; | |
| 6670 } else if (IS_SCHEMA(node, "minExclusive")) { | |
| 6671 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE; | |
| 6672 } else if (IS_SCHEMA(node, "maxInclusive")) { | |
| 6673 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE; | |
| 6674 } else if (IS_SCHEMA(node, "maxExclusive")) { | |
| 6675 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE; | |
| 6676 } else if (IS_SCHEMA(node, "totalDigits")) { | |
| 6677 facet->type = XML_SCHEMA_FACET_TOTALDIGITS; | |
| 6678 } else if (IS_SCHEMA(node, "fractionDigits")) { | |
| 6679 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS; | |
| 6680 } else if (IS_SCHEMA(node, "pattern")) { | |
| 6681 facet->type = XML_SCHEMA_FACET_PATTERN; | |
| 6682 } else if (IS_SCHEMA(node, "enumeration")) { | |
| 6683 facet->type = XML_SCHEMA_FACET_ENUMERATION; | |
| 6684 } else if (IS_SCHEMA(node, "whiteSpace")) { | |
| 6685 facet->type = XML_SCHEMA_FACET_WHITESPACE; | |
| 6686 } else if (IS_SCHEMA(node, "length")) { | |
| 6687 facet->type = XML_SCHEMA_FACET_LENGTH; | |
| 6688 } else if (IS_SCHEMA(node, "maxLength")) { | |
| 6689 facet->type = XML_SCHEMA_FACET_MAXLENGTH; | |
| 6690 } else if (IS_SCHEMA(node, "minLength")) { | |
| 6691 facet->type = XML_SCHEMA_FACET_MINLENGTH; | |
| 6692 } else { | |
| 6693 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE, | |
| 6694 "Unknown facet type %s\n", node->name, NULL); | |
| 6695 xmlSchemaFreeFacet(facet); | |
| 6696 return (NULL); | |
| 6697 } | |
| 6698 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 6699 facet->value = value; | |
| 6700 if ((facet->type != XML_SCHEMA_FACET_PATTERN) && | |
| 6701 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) { | |
| 6702 const xmlChar *fixed; | |
| 6703 | |
| 6704 fixed = xmlSchemaGetProp(ctxt, node, "fixed"); | |
| 6705 if (fixed != NULL) { | |
| 6706 if (xmlStrEqual(fixed, BAD_CAST "true")) | |
| 6707 facet->fixed = 1; | |
| 6708 } | |
| 6709 } | |
| 6710 child = node->children; | |
| 6711 | |
| 6712 if (IS_SCHEMA(child, "annotation")) { | |
| 6713 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | |
| 6714 child = child->next; | |
| 6715 } | |
| 6716 if (child != NULL) { | |
| 6717 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD, | |
| 6718 "Facet %s has unexpected child content\n", | |
| 6719 node->name, NULL); | |
| 6720 } | |
| 6721 return (facet); | |
| 6722 } | |
| 6723 | |
| 6724 /** | |
| 6725 * xmlSchemaParseWildcardNs: | |
| 6726 * @ctxt: a schema parser context | |
| 6727 * @wildc: the wildcard, already created | |
| 6728 * @node: a subtree containing XML Schema informations | |
| 6729 * | |
| 6730 * Parses the attribute "processContents" and "namespace" | |
| 6731 * of a xsd:anyAttribute and xsd:any. | |
| 6732 * *WARNING* this interface is highly subject to change | |
| 6733 * | |
| 6734 * Returns 0 if everything goes fine, a positive error code | |
| 6735 * if something is not valid and -1 if an internal error occurs. | |
| 6736 */ | |
| 6737 static int | |
| 6738 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt, | |
| 6739 xmlSchemaPtr schema ATTRIBUTE_UNUSED, | |
| 6740 xmlSchemaWildcardPtr wildc, | |
| 6741 xmlNodePtr node) | |
| 6742 { | |
| 6743 const xmlChar *pc, *ns, *dictnsItem; | |
| 6744 int ret = 0; | |
| 6745 xmlChar *nsItem; | |
| 6746 xmlSchemaWildcardNsPtr tmp, lastNs = NULL; | |
| 6747 xmlAttrPtr attr; | |
| 6748 | |
| 6749 pc = xmlSchemaGetProp(ctxt, node, "processContents"); | |
| 6750 if ((pc == NULL) | |
| 6751 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) { | |
| 6752 wildc->processContents = XML_SCHEMAS_ANY_STRICT; | |
| 6753 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) { | |
| 6754 wildc->processContents = XML_SCHEMAS_ANY_SKIP; | |
| 6755 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) { | |
| 6756 wildc->processContents = XML_SCHEMAS_ANY_LAX; | |
| 6757 } else { | |
| 6758 xmlSchemaPSimpleTypeErr(ctxt, | |
| 6759 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 6760 NULL, node, | |
| 6761 NULL, "(strict | skip | lax)", pc, | |
| 6762 NULL, NULL, NULL); | |
| 6763 wildc->processContents = XML_SCHEMAS_ANY_STRICT; | |
| 6764 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; | |
| 6765 } | |
| 6766 /* | |
| 6767 * Build the namespace constraints. | |
| 6768 */ | |
| 6769 attr = xmlSchemaGetPropNode(node, "namespace"); | |
| 6770 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 6771 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any"))) | |
| 6772 wildc->any = 1; | |
| 6773 else if (xmlStrEqual(ns, BAD_CAST "##other")) { | |
| 6774 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); | |
| 6775 if (wildc->negNsSet == NULL) { | |
| 6776 return (-1); | |
| 6777 } | |
| 6778 wildc->negNsSet->value = ctxt->targetNamespace; | |
| 6779 } else { | |
| 6780 const xmlChar *end, *cur; | |
| 6781 | |
| 6782 cur = ns; | |
| 6783 do { | |
| 6784 while (IS_BLANK_CH(*cur)) | |
| 6785 cur++; | |
| 6786 end = cur; | |
| 6787 while ((*end != 0) && (!(IS_BLANK_CH(*end)))) | |
| 6788 end++; | |
| 6789 if (end == cur) | |
| 6790 break; | |
| 6791 nsItem = xmlStrndup(cur, end - cur); | |
| 6792 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) || | |
| 6793 (xmlStrEqual(nsItem, BAD_CAST "##any"))) { | |
| 6794 xmlSchemaPSimpleTypeErr(ctxt, | |
| 6795 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER, | |
| 6796 NULL, (xmlNodePtr) attr, | |
| 6797 NULL, | |
| 6798 "((##any | ##other) | List of (xs:anyURI | " | |
| 6799 "(##targetNamespace | ##local)))", | |
| 6800 nsItem, NULL, NULL, NULL); | |
| 6801 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER; | |
| 6802 } else { | |
| 6803 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) { | |
| 6804 dictnsItem = ctxt->targetNamespace; | |
| 6805 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) { | |
| 6806 dictnsItem = NULL; | |
| 6807 } else { | |
| 6808 /* | |
| 6809 * Validate the item (anyURI). | |
| 6810 */ | |
| 6811 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr, | |
| 6812 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI)); | |
| 6813 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1); | |
| 6814 } | |
| 6815 /* | |
| 6816 * Avoid dublicate namespaces. | |
| 6817 */ | |
| 6818 tmp = wildc->nsSet; | |
| 6819 while (tmp != NULL) { | |
| 6820 if (dictnsItem == tmp->value) | |
| 6821 break; | |
| 6822 tmp = tmp->next; | |
| 6823 } | |
| 6824 if (tmp == NULL) { | |
| 6825 tmp = xmlSchemaNewWildcardNsConstraint(ctxt); | |
| 6826 if (tmp == NULL) { | |
| 6827 xmlFree(nsItem); | |
| 6828 return (-1); | |
| 6829 } | |
| 6830 tmp->value = dictnsItem; | |
| 6831 tmp->next = NULL; | |
| 6832 if (wildc->nsSet == NULL) | |
| 6833 wildc->nsSet = tmp; | |
| 6834 else if (lastNs != NULL) | |
| 6835 lastNs->next = tmp; | |
| 6836 lastNs = tmp; | |
| 6837 } | |
| 6838 | |
| 6839 } | |
| 6840 xmlFree(nsItem); | |
| 6841 cur = end; | |
| 6842 } while (*cur != 0); | |
| 6843 } | |
| 6844 return (ret); | |
| 6845 } | |
| 6846 | |
| 6847 static int | |
| 6848 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt, | |
| 6849 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED, | |
| 6850 xmlNodePtr node, | |
| 6851 int minOccurs, | |
| 6852 int maxOccurs) { | |
| 6853 | |
| 6854 if ((maxOccurs == 0) && ( minOccurs == 0)) | |
| 6855 return (0); | |
| 6856 if (maxOccurs != UNBOUNDED) { | |
| 6857 /* | |
| 6858 * TODO: Maybe we should better not create the particle, | |
| 6859 * if min/max is invalid, since it could confuse the build of the | |
| 6860 * content model. | |
| 6861 */ | |
| 6862 /* | |
| 6863 * 3.9.6 Schema Component Constraint: Particle Correct | |
| 6864 * | |
| 6865 */ | |
| 6866 if (maxOccurs < 1) { | |
| 6867 /* | |
| 6868 * 2.2 {max occurs} must be greater than or equal to 1. | |
| 6869 */ | |
| 6870 xmlSchemaPCustomAttrErr(ctxt, | |
| 6871 XML_SCHEMAP_P_PROPS_CORRECT_2_2, | |
| 6872 NULL, NULL, | |
| 6873 xmlSchemaGetPropNode(node, "maxOccurs"), | |
| 6874 "The value must be greater than or equal to 1"); | |
| 6875 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2); | |
| 6876 } else if (minOccurs > maxOccurs) { | |
| 6877 /* | |
| 6878 * 2.1 {min occurs} must not be greater than {max occurs}. | |
| 6879 */ | |
| 6880 xmlSchemaPCustomAttrErr(ctxt, | |
| 6881 XML_SCHEMAP_P_PROPS_CORRECT_2_1, | |
| 6882 NULL, NULL, | |
| 6883 xmlSchemaGetPropNode(node, "minOccurs"), | |
| 6884 "The value must not be greater than the value of 'maxOccurs'"); | |
| 6885 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1); | |
| 6886 } | |
| 6887 } | |
| 6888 return (0); | |
| 6889 } | |
| 6890 | |
| 6891 /** | |
| 6892 * xmlSchemaParseAny: | |
| 6893 * @ctxt: a schema validation context | |
| 6894 * @schema: the schema being built | |
| 6895 * @node: a subtree containing XML Schema informations | |
| 6896 * | |
| 6897 * Parsea a XML schema <any> element. A particle and wildcard | |
| 6898 * will be created (except if minOccurs==maxOccurs==0, in this case | |
| 6899 * nothing will be created). | |
| 6900 * *WARNING* this interface is highly subject to change | |
| 6901 * | |
| 6902 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0 | |
| 6903 */ | |
| 6904 static xmlSchemaParticlePtr | |
| 6905 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 6906 xmlNodePtr node) | |
| 6907 { | |
| 6908 xmlSchemaParticlePtr particle; | |
| 6909 xmlNodePtr child = NULL; | |
| 6910 xmlSchemaWildcardPtr wild; | |
| 6911 int min, max; | |
| 6912 xmlAttrPtr attr; | |
| 6913 xmlSchemaAnnotPtr annot = NULL; | |
| 6914 | |
| 6915 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 6916 return (NULL); | |
| 6917 /* | |
| 6918 * Check for illegal attributes. | |
| 6919 */ | |
| 6920 attr = node->properties; | |
| 6921 while (attr != NULL) { | |
| 6922 if (attr->ns == NULL) { | |
| 6923 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 6924 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) && | |
| 6925 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) && | |
| 6926 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) && | |
| 6927 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) { | |
| 6928 xmlSchemaPIllegalAttrErr(ctxt, | |
| 6929 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 6930 } | |
| 6931 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 6932 xmlSchemaPIllegalAttrErr(ctxt, | |
| 6933 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 6934 } | |
| 6935 attr = attr->next; | |
| 6936 } | |
| 6937 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 6938 /* | |
| 6939 * minOccurs/maxOccurs. | |
| 6940 */ | |
| 6941 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, | |
| 6942 "(xs:nonNegativeInteger | unbounded)"); | |
| 6943 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, | |
| 6944 "xs:nonNegativeInteger"); | |
| 6945 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max); | |
| 6946 /* | |
| 6947 * Create & parse the wildcard. | |
| 6948 */ | |
| 6949 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node); | |
| 6950 if (wild == NULL) | |
| 6951 return (NULL); | |
| 6952 xmlSchemaParseWildcardNs(ctxt, schema, wild, node); | |
| 6953 /* | |
| 6954 * And now for the children... | |
| 6955 */ | |
| 6956 child = node->children; | |
| 6957 if (IS_SCHEMA(child, "annotation")) { | |
| 6958 annot = xmlSchemaParseAnnotation(ctxt, child, 1); | |
| 6959 child = child->next; | |
| 6960 } | |
| 6961 if (child != NULL) { | |
| 6962 xmlSchemaPContentErr(ctxt, | |
| 6963 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 6964 NULL, node, child, | |
| 6965 NULL, "(annotation?)"); | |
| 6966 } | |
| 6967 /* | |
| 6968 * No component if minOccurs==maxOccurs==0. | |
| 6969 */ | |
| 6970 if ((min == 0) && (max == 0)) { | |
| 6971 /* Don't free the wildcard, since it's already on the list. */ | |
| 6972 return (NULL); | |
| 6973 } | |
| 6974 /* | |
| 6975 * Create the particle. | |
| 6976 */ | |
| 6977 particle = xmlSchemaAddParticle(ctxt, node, min, max); | |
| 6978 if (particle == NULL) | |
| 6979 return (NULL); | |
| 6980 particle->annot = annot; | |
| 6981 particle->children = (xmlSchemaTreeItemPtr) wild; | |
| 6982 | |
| 6983 return (particle); | |
| 6984 } | |
| 6985 | |
| 6986 /** | |
| 6987 * xmlSchemaParseNotation: | |
| 6988 * @ctxt: a schema validation context | |
| 6989 * @schema: the schema being built | |
| 6990 * @node: a subtree containing XML Schema informations | |
| 6991 * | |
| 6992 * parse a XML schema Notation declaration | |
| 6993 * | |
| 6994 * Returns the new structure or NULL in case of error | |
| 6995 */ | |
| 6996 static xmlSchemaNotationPtr | |
| 6997 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 6998 xmlNodePtr node) | |
| 6999 { | |
| 7000 const xmlChar *name; | |
| 7001 xmlSchemaNotationPtr ret; | |
| 7002 xmlNodePtr child = NULL; | |
| 7003 | |
| 7004 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 7005 return (NULL); | |
| 7006 name = xmlSchemaGetProp(ctxt, node, "name"); | |
| 7007 if (name == NULL) { | |
| 7008 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME, | |
| 7009 "Notation has no name\n", NULL, NULL); | |
| 7010 return (NULL); | |
| 7011 } | |
| 7012 ret = xmlSchemaAddNotation(ctxt, schema, name, | |
| 7013 ctxt->targetNamespace, node); | |
| 7014 if (ret == NULL) | |
| 7015 return (NULL); | |
| 7016 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 7017 | |
| 7018 child = node->children; | |
| 7019 if (IS_SCHEMA(child, "annotation")) { | |
| 7020 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | |
| 7021 child = child->next; | |
| 7022 } | |
| 7023 if (child != NULL) { | |
| 7024 xmlSchemaPContentErr(ctxt, | |
| 7025 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 7026 NULL, node, child, | |
| 7027 NULL, "(annotation?)"); | |
| 7028 } | |
| 7029 | |
| 7030 return (ret); | |
| 7031 } | |
| 7032 | |
| 7033 /** | |
| 7034 * xmlSchemaParseAnyAttribute: | |
| 7035 * @ctxt: a schema validation context | |
| 7036 * @schema: the schema being built | |
| 7037 * @node: a subtree containing XML Schema informations | |
| 7038 * | |
| 7039 * parse a XML schema AnyAttrribute declaration | |
| 7040 * *WARNING* this interface is highly subject to change | |
| 7041 * | |
| 7042 * Returns a wildcard or NULL. | |
| 7043 */ | |
| 7044 static xmlSchemaWildcardPtr | |
| 7045 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, | |
| 7046 xmlSchemaPtr schema, xmlNodePtr node) | |
| 7047 { | |
| 7048 xmlSchemaWildcardPtr ret; | |
| 7049 xmlNodePtr child = NULL; | |
| 7050 xmlAttrPtr attr; | |
| 7051 | |
| 7052 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 7053 return (NULL); | |
| 7054 | |
| 7055 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE, | |
| 7056 node); | |
| 7057 if (ret == NULL) { | |
| 7058 return (NULL); | |
| 7059 } | |
| 7060 /* | |
| 7061 * Check for illegal attributes. | |
| 7062 */ | |
| 7063 attr = node->properties; | |
| 7064 while (attr != NULL) { | |
| 7065 if (attr->ns == NULL) { | |
| 7066 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 7067 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) && | |
| 7068 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) { | |
| 7069 xmlSchemaPIllegalAttrErr(ctxt, | |
| 7070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 7071 } | |
| 7072 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 7073 xmlSchemaPIllegalAttrErr(ctxt, | |
| 7074 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 7075 } | |
| 7076 attr = attr->next; | |
| 7077 } | |
| 7078 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 7079 /* | |
| 7080 * Parse the namespace list. | |
| 7081 */ | |
| 7082 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) | |
| 7083 return (NULL); | |
| 7084 /* | |
| 7085 * And now for the children... | |
| 7086 */ | |
| 7087 child = node->children; | |
| 7088 if (IS_SCHEMA(child, "annotation")) { | |
| 7089 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | |
| 7090 child = child->next; | |
| 7091 } | |
| 7092 if (child != NULL) { | |
| 7093 xmlSchemaPContentErr(ctxt, | |
| 7094 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 7095 NULL, node, child, | |
| 7096 NULL, "(annotation?)"); | |
| 7097 } | |
| 7098 | |
| 7099 return (ret); | |
| 7100 } | |
| 7101 | |
| 7102 | |
| 7103 /** | |
| 7104 * xmlSchemaParseAttribute: | |
| 7105 * @ctxt: a schema validation context | |
| 7106 * @schema: the schema being built | |
| 7107 * @node: a subtree containing XML Schema informations | |
| 7108 * | |
| 7109 * parse a XML schema Attrribute declaration | |
| 7110 * *WARNING* this interface is highly subject to change | |
| 7111 * | |
| 7112 * Returns the attribute declaration. | |
| 7113 */ | |
| 7114 static xmlSchemaBasicItemPtr | |
| 7115 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt, | |
| 7116 xmlSchemaPtr schema, | |
| 7117 xmlNodePtr node, | |
| 7118 xmlSchemaItemListPtr uses, | |
| 7119 int parentType) | |
| 7120 { | |
| 7121 const xmlChar *attrValue, *name = NULL, *ns = NULL; | |
| 7122 xmlSchemaAttributeUsePtr use = NULL; | |
| 7123 xmlNodePtr child = NULL; | |
| 7124 xmlAttrPtr attr; | |
| 7125 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL; | |
| 7126 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL; | |
| 7127 int nberrors, hasForm = 0, defValueType = 0; | |
| 7128 | |
| 7129 #define WXS_ATTR_DEF_VAL_DEFAULT 1 | |
| 7130 #define WXS_ATTR_DEF_VAL_FIXED 2 | |
| 7131 | |
| 7132 /* | |
| 7133 * 3.2.3 Constraints on XML Representations of Attribute Declarations | |
| 7134 */ | |
| 7135 | |
| 7136 if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 7137 return (NULL); | |
| 7138 attr = xmlSchemaGetPropNode(node, "ref"); | |
| 7139 if (attr != NULL) { | |
| 7140 if (xmlSchemaPValAttrNodeQName(pctxt, schema, | |
| 7141 NULL, attr, &tmpNs, &tmpName) != 0) { | |
| 7142 return (NULL); | |
| 7143 } | |
| 7144 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0) | |
| 7145 return(NULL); | |
| 7146 isRef = 1; | |
| 7147 } | |
| 7148 nberrors = pctxt->nberrors; | |
| 7149 /* | |
| 7150 * Check for illegal attributes. | |
| 7151 */ | |
| 7152 attr = node->properties; | |
| 7153 while (attr != NULL) { | |
| 7154 if (attr->ns == NULL) { | |
| 7155 if (isRef) { | |
| 7156 if (xmlStrEqual(attr->name, BAD_CAST "id")) { | |
| 7157 xmlSchemaPValAttrNodeID(pctxt, attr); | |
| 7158 goto attr_next; | |
| 7159 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) { | |
| 7160 goto attr_next; | |
| 7161 } | |
| 7162 } else { | |
| 7163 if (xmlStrEqual(attr->name, BAD_CAST "name")) { | |
| 7164 goto attr_next; | |
| 7165 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) { | |
| 7166 xmlSchemaPValAttrNodeID(pctxt, attr); | |
| 7167 goto attr_next; | |
| 7168 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) { | |
| 7169 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL, | |
| 7170 attr, &tmpNs, &tmpName); | |
| 7171 goto attr_next; | |
| 7172 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) { | |
| 7173 /* | |
| 7174 * Evaluate the target namespace | |
| 7175 */ | |
| 7176 hasForm = 1; | |
| 7177 attrValue = xmlSchemaGetNodeContent(pctxt, | |
| 7178 (xmlNodePtr) attr); | |
| 7179 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) { | |
| 7180 ns = pctxt->targetNamespace; | |
| 7181 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) | |
| 7182 { | |
| 7183 xmlSchemaPSimpleTypeErr(pctxt, | |
| 7184 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 7185 NULL, (xmlNodePtr) attr, | |
| 7186 NULL, "(qualified | unqualified)", | |
| 7187 attrValue, NULL, NULL, NULL); | |
| 7188 } | |
| 7189 goto attr_next; | |
| 7190 } | |
| 7191 } | |
| 7192 if (xmlStrEqual(attr->name, BAD_CAST "use")) { | |
| 7193 | |
| 7194 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); | |
| 7195 /* TODO: Maybe we need to normalize the value beforehand. */ | |
| 7196 if (xmlStrEqual(attrValue, BAD_CAST "optional")) | |
| 7197 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL; | |
| 7198 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited")) | |
| 7199 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED; | |
| 7200 else if (xmlStrEqual(attrValue, BAD_CAST "required")) | |
| 7201 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED; | |
| 7202 else { | |
| 7203 xmlSchemaPSimpleTypeErr(pctxt, | |
| 7204 XML_SCHEMAP_INVALID_ATTR_USE, | |
| 7205 NULL, (xmlNodePtr) attr, | |
| 7206 NULL, "(optional | prohibited | required)", | |
| 7207 attrValue, NULL, NULL, NULL); | |
| 7208 } | |
| 7209 goto attr_next; | |
| 7210 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) { | |
| 7211 /* | |
| 7212 * 3.2.3 : 1 | |
| 7213 * default and fixed must not both be present. | |
| 7214 */ | |
| 7215 if (defValue) { | |
| 7216 xmlSchemaPMutualExclAttrErr(pctxt, | |
| 7217 XML_SCHEMAP_SRC_ATTRIBUTE_1, | |
| 7218 NULL, attr, "default", "fixed"); | |
| 7219 } else { | |
| 7220 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr)
; | |
| 7221 defValueType = WXS_ATTR_DEF_VAL_DEFAULT; | |
| 7222 } | |
| 7223 goto attr_next; | |
| 7224 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) { | |
| 7225 /* | |
| 7226 * 3.2.3 : 1 | |
| 7227 * default and fixed must not both be present. | |
| 7228 */ | |
| 7229 if (defValue) { | |
| 7230 xmlSchemaPMutualExclAttrErr(pctxt, | |
| 7231 XML_SCHEMAP_SRC_ATTRIBUTE_1, | |
| 7232 NULL, attr, "default", "fixed"); | |
| 7233 } else { | |
| 7234 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr)
; | |
| 7235 defValueType = WXS_ATTR_DEF_VAL_FIXED; | |
| 7236 } | |
| 7237 goto attr_next; | |
| 7238 } | |
| 7239 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs)) | |
| 7240 goto attr_next; | |
| 7241 | |
| 7242 xmlSchemaPIllegalAttrErr(pctxt, | |
| 7243 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 7244 | |
| 7245 attr_next: | |
| 7246 attr = attr->next; | |
| 7247 } | |
| 7248 /* | |
| 7249 * 3.2.3 : 2 | |
| 7250 * If default and use are both present, use must have | |
| 7251 * the actual value optional. | |
| 7252 */ | |
| 7253 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) && | |
| 7254 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) { | |
| 7255 xmlSchemaPSimpleTypeErr(pctxt, | |
| 7256 XML_SCHEMAP_SRC_ATTRIBUTE_2, | |
| 7257 NULL, node, NULL, | |
| 7258 "(optional | prohibited | required)", NULL, | |
| 7259 "The value of the attribute 'use' must be 'optional' " | |
| 7260 "if the attribute 'default' is present", | |
| 7261 NULL, NULL); | |
| 7262 } | |
| 7263 /* | |
| 7264 * We want correct attributes. | |
| 7265 */ | |
| 7266 if (nberrors != pctxt->nberrors) | |
| 7267 return(NULL); | |
| 7268 if (! isRef) { | |
| 7269 xmlSchemaAttributePtr attrDecl; | |
| 7270 | |
| 7271 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */ | |
| 7272 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR)) | |
| 7273 ns = pctxt->targetNamespace; | |
| 7274 /* | |
| 7275 * 3.2.6 Schema Component Constraint: xsi: Not Allowed | |
| 7276 * TODO: Move this to the component layer. | |
| 7277 */ | |
| 7278 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) { | |
| 7279 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 7280 XML_SCHEMAP_NO_XSI, | |
| 7281 node, NULL, | |
| 7282 "The target namespace must not match '%s'", | |
| 7283 xmlSchemaInstanceNs, NULL); | |
| 7284 } | |
| 7285 attr = xmlSchemaGetPropNode(node, "name"); | |
| 7286 if (attr == NULL) { | |
| 7287 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 7288 NULL, node, "name", NULL); | |
| 7289 return (NULL); | |
| 7290 } | |
| 7291 if (xmlSchemaPValAttrNode(pctxt, NULL, attr, | |
| 7292 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { | |
| 7293 return (NULL); | |
| 7294 } | |
| 7295 /* | |
| 7296 * 3.2.6 Schema Component Constraint: xmlns Not Allowed | |
| 7297 * TODO: Move this to the component layer. | |
| 7298 */ | |
| 7299 if (xmlStrEqual(name, BAD_CAST "xmlns")) { | |
| 7300 xmlSchemaPSimpleTypeErr(pctxt, | |
| 7301 XML_SCHEMAP_NO_XMLNS, | |
| 7302 NULL, (xmlNodePtr) attr, | |
| 7303 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL, | |
| 7304 "The value of the attribute must not match 'xmlns'", | |
| 7305 NULL, NULL); | |
| 7306 return (NULL); | |
| 7307 } | |
| 7308 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) | |
| 7309 goto check_children; | |
| 7310 /* | |
| 7311 * Create the attribute use component. | |
| 7312 */ | |
| 7313 use = xmlSchemaAddAttributeUse(pctxt, node); | |
| 7314 if (use == NULL) | |
| 7315 return(NULL); | |
| 7316 use->occurs = occurs; | |
| 7317 /* | |
| 7318 * Create the attribute declaration. | |
| 7319 */ | |
| 7320 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0); | |
| 7321 if (attrDecl == NULL) | |
| 7322 return (NULL); | |
| 7323 if (tmpName != NULL) { | |
| 7324 attrDecl->typeName = tmpName; | |
| 7325 attrDecl->typeNs = tmpNs; | |
| 7326 } | |
| 7327 use->attrDecl = attrDecl; | |
| 7328 /* | |
| 7329 * Value constraint. | |
| 7330 */ | |
| 7331 if (defValue != NULL) { | |
| 7332 attrDecl->defValue = defValue; | |
| 7333 if (defValueType == WXS_ATTR_DEF_VAL_FIXED) | |
| 7334 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED; | |
| 7335 } | |
| 7336 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) { | |
| 7337 xmlSchemaQNameRefPtr ref; | |
| 7338 | |
| 7339 /* | |
| 7340 * Create the attribute use component. | |
| 7341 */ | |
| 7342 use = xmlSchemaAddAttributeUse(pctxt, node); | |
| 7343 if (use == NULL) | |
| 7344 return(NULL); | |
| 7345 /* | |
| 7346 * We need to resolve the reference at later stage. | |
| 7347 */ | |
| 7348 WXS_ADD_PENDING(pctxt, use); | |
| 7349 use->occurs = occurs; | |
| 7350 /* | |
| 7351 * Create a QName reference to the attribute declaration. | |
| 7352 */ | |
| 7353 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE, | |
| 7354 tmpName, tmpNs); | |
| 7355 if (ref == NULL) | |
| 7356 return(NULL); | |
| 7357 /* | |
| 7358 * Assign the reference. This will be substituted for the | |
| 7359 * referenced attribute declaration when the QName is resolved. | |
| 7360 */ | |
| 7361 use->attrDecl = WXS_ATTR_CAST ref; | |
| 7362 /* | |
| 7363 * Value constraint. | |
| 7364 */ | |
| 7365 if (defValue != NULL) | |
| 7366 use->defValue = defValue; | |
| 7367 if (defValueType == WXS_ATTR_DEF_VAL_FIXED) | |
| 7368 use->flags |= XML_SCHEMA_ATTR_USE_FIXED; | |
| 7369 } | |
| 7370 | |
| 7371 check_children: | |
| 7372 /* | |
| 7373 * And now for the children... | |
| 7374 */ | |
| 7375 child = node->children; | |
| 7376 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) { | |
| 7377 xmlSchemaAttributeUseProhibPtr prohib; | |
| 7378 | |
| 7379 if (IS_SCHEMA(child, "annotation")) { | |
| 7380 xmlSchemaParseAnnotation(pctxt, child, 0); | |
| 7381 child = child->next; | |
| 7382 } | |
| 7383 if (child != NULL) { | |
| 7384 xmlSchemaPContentErr(pctxt, | |
| 7385 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 7386 NULL, node, child, NULL, | |
| 7387 "(annotation?)"); | |
| 7388 } | |
| 7389 /* | |
| 7390 * Check for pointlessness of attribute prohibitions. | |
| 7391 */ | |
| 7392 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) { | |
| 7393 xmlSchemaCustomWarning(ACTXT_CAST pctxt, | |
| 7394 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, | |
| 7395 node, NULL, | |
| 7396 "Skipping attribute use prohibition, since it is " | |
| 7397 "pointless inside an <attributeGroup>", | |
| 7398 NULL, NULL, NULL); | |
| 7399 return(NULL); | |
| 7400 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) { | |
| 7401 xmlSchemaCustomWarning(ACTXT_CAST pctxt, | |
| 7402 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, | |
| 7403 node, NULL, | |
| 7404 "Skipping attribute use prohibition, since it is " | |
| 7405 "pointless when extending a type", | |
| 7406 NULL, NULL, NULL); | |
| 7407 return(NULL); | |
| 7408 } | |
| 7409 if (! isRef) { | |
| 7410 tmpName = name; | |
| 7411 tmpNs = ns; | |
| 7412 } | |
| 7413 /* | |
| 7414 * Check for duplicate attribute prohibitions. | |
| 7415 */ | |
| 7416 if (uses) { | |
| 7417 int i; | |
| 7418 | |
| 7419 for (i = 0; i < uses->nbItems; i++) { | |
| 7420 use = uses->items[i]; | |
| 7421 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) && | |
| 7422 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) && | |
| 7423 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace)) | |
| 7424 { | |
| 7425 xmlChar *str = NULL; | |
| 7426 | |
| 7427 xmlSchemaCustomWarning(ACTXT_CAST pctxt, | |
| 7428 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, | |
| 7429 node, NULL, | |
| 7430 "Skipping duplicate attribute use prohibition '%s'", | |
| 7431 xmlSchemaFormatQName(&str, tmpNs, tmpName), | |
| 7432 NULL, NULL); | |
| 7433 FREE_AND_NULL(str) | |
| 7434 return(NULL); | |
| 7435 } | |
| 7436 } | |
| 7437 } | |
| 7438 /* | |
| 7439 * Create the attribute prohibition helper component. | |
| 7440 */ | |
| 7441 prohib = xmlSchemaAddAttributeUseProhib(pctxt); | |
| 7442 if (prohib == NULL) | |
| 7443 return(NULL); | |
| 7444 prohib->node = node; | |
| 7445 prohib->name = tmpName; | |
| 7446 prohib->targetNamespace = tmpNs; | |
| 7447 if (isRef) { | |
| 7448 /* | |
| 7449 * We need at least to resolve to the attribute declaration. | |
| 7450 */ | |
| 7451 WXS_ADD_PENDING(pctxt, prohib); | |
| 7452 } | |
| 7453 return(WXS_BASIC_CAST prohib); | |
| 7454 } else { | |
| 7455 if (IS_SCHEMA(child, "annotation")) { | |
| 7456 /* | |
| 7457 * TODO: Should this go into the attr decl? | |
| 7458 */ | |
| 7459 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1); | |
| 7460 child = child->next; | |
| 7461 } | |
| 7462 if (isRef) { | |
| 7463 if (child != NULL) { | |
| 7464 if (IS_SCHEMA(child, "simpleType")) | |
| 7465 /* | |
| 7466 * 3.2.3 : 3.2 | |
| 7467 * If ref is present, then all of <simpleType>, | |
| 7468 * form and type must be absent. | |
| 7469 */ | |
| 7470 xmlSchemaPContentErr(pctxt, | |
| 7471 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, | |
| 7472 NULL, node, child, NULL, | |
| 7473 "(annotation?)"); | |
| 7474 else | |
| 7475 xmlSchemaPContentErr(pctxt, | |
| 7476 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 7477 NULL, node, child, NULL, | |
| 7478 "(annotation?)"); | |
| 7479 } | |
| 7480 } else { | |
| 7481 if (IS_SCHEMA(child, "simpleType")) { | |
| 7482 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) { | |
| 7483 /* | |
| 7484 * 3.2.3 : 4 | |
| 7485 * type and <simpleType> must not both be present. | |
| 7486 */ | |
| 7487 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4, | |
| 7488 NULL, node, child, | |
| 7489 "The attribute 'type' and the <simpleType> child " | |
| 7490 "are mutually exclusive", NULL); | |
| 7491 } else | |
| 7492 WXS_ATTRUSE_TYPEDEF(use) = | |
| 7493 xmlSchemaParseSimpleType(pctxt, schema, child, 0); | |
| 7494 child = child->next; | |
| 7495 } | |
| 7496 if (child != NULL) | |
| 7497 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 7498 NULL, node, child, NULL, | |
| 7499 "(annotation?, simpleType?)"); | |
| 7500 } | |
| 7501 } | |
| 7502 return (WXS_BASIC_CAST use); | |
| 7503 } | |
| 7504 | |
| 7505 | |
| 7506 static xmlSchemaAttributePtr | |
| 7507 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt, | |
| 7508 xmlSchemaPtr schema, | |
| 7509 xmlNodePtr node) | |
| 7510 { | |
| 7511 const xmlChar *attrValue; | |
| 7512 xmlSchemaAttributePtr ret; | |
| 7513 xmlNodePtr child = NULL; | |
| 7514 xmlAttrPtr attr; | |
| 7515 | |
| 7516 /* | |
| 7517 * Note that the w3c spec assumes the schema to be validated with schema | |
| 7518 * for schemas beforehand. | |
| 7519 * | |
| 7520 * 3.2.3 Constraints on XML Representations of Attribute Declarations | |
| 7521 */ | |
| 7522 if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 7523 return (NULL); | |
| 7524 /* | |
| 7525 * 3.2.3 : 3.1 | |
| 7526 * One of ref or name must be present, but not both | |
| 7527 */ | |
| 7528 attr = xmlSchemaGetPropNode(node, "name"); | |
| 7529 if (attr == NULL) { | |
| 7530 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 7531 NULL, node, "name", NULL); | |
| 7532 return (NULL); | |
| 7533 } | |
| 7534 if (xmlSchemaPValAttrNode(pctxt, NULL, attr, | |
| 7535 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) { | |
| 7536 return (NULL); | |
| 7537 } | |
| 7538 /* | |
| 7539 * 3.2.6 Schema Component Constraint: xmlns Not Allowed | |
| 7540 * TODO: Move this to the component layer. | |
| 7541 */ | |
| 7542 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) { | |
| 7543 xmlSchemaPSimpleTypeErr(pctxt, | |
| 7544 XML_SCHEMAP_NO_XMLNS, | |
| 7545 NULL, (xmlNodePtr) attr, | |
| 7546 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL, | |
| 7547 "The value of the attribute must not match 'xmlns'", | |
| 7548 NULL, NULL); | |
| 7549 return (NULL); | |
| 7550 } | |
| 7551 /* | |
| 7552 * 3.2.6 Schema Component Constraint: xsi: Not Allowed | |
| 7553 * TODO: Move this to the component layer. | |
| 7554 * Or better leave it here and add it to the component layer | |
| 7555 * if we have a schema construction API. | |
| 7556 */ | |
| 7557 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) { | |
| 7558 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 7559 XML_SCHEMAP_NO_XSI, node, NULL, | |
| 7560 "The target namespace must not match '%s'", | |
| 7561 xmlSchemaInstanceNs, NULL); | |
| 7562 } | |
| 7563 | |
| 7564 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue, | |
| 7565 pctxt->targetNamespace, node, 1); | |
| 7566 if (ret == NULL) | |
| 7567 return (NULL); | |
| 7568 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL; | |
| 7569 | |
| 7570 /* | |
| 7571 * Check for illegal attributes. | |
| 7572 */ | |
| 7573 attr = node->properties; | |
| 7574 while (attr != NULL) { | |
| 7575 if (attr->ns == NULL) { | |
| 7576 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 7577 (!xmlStrEqual(attr->name, BAD_CAST "default")) && | |
| 7578 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) && | |
| 7579 (!xmlStrEqual(attr->name, BAD_CAST "name")) && | |
| 7580 (!xmlStrEqual(attr->name, BAD_CAST "type"))) | |
| 7581 { | |
| 7582 xmlSchemaPIllegalAttrErr(pctxt, | |
| 7583 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 7584 } | |
| 7585 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 7586 xmlSchemaPIllegalAttrErr(pctxt, | |
| 7587 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 7588 } | |
| 7589 attr = attr->next; | |
| 7590 } | |
| 7591 xmlSchemaPValAttrQName(pctxt, schema, NULL, | |
| 7592 node, "type", &ret->typeNs, &ret->typeName); | |
| 7593 | |
| 7594 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); | |
| 7595 /* | |
| 7596 * Attribute "fixed". | |
| 7597 */ | |
| 7598 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed"); | |
| 7599 if (ret->defValue != NULL) | |
| 7600 ret->flags |= XML_SCHEMAS_ATTR_FIXED; | |
| 7601 /* | |
| 7602 * Attribute "default". | |
| 7603 */ | |
| 7604 attr = xmlSchemaGetPropNode(node, "default"); | |
| 7605 if (attr != NULL) { | |
| 7606 /* | |
| 7607 * 3.2.3 : 1 | |
| 7608 * default and fixed must not both be present. | |
| 7609 */ | |
| 7610 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) { | |
| 7611 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1, | |
| 7612 WXS_BASIC_CAST ret, attr, "default", "fixed"); | |
| 7613 } else | |
| 7614 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); | |
| 7615 } | |
| 7616 /* | |
| 7617 * And now for the children... | |
| 7618 */ | |
| 7619 child = node->children; | |
| 7620 if (IS_SCHEMA(child, "annotation")) { | |
| 7621 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1); | |
| 7622 child = child->next; | |
| 7623 } | |
| 7624 if (IS_SCHEMA(child, "simpleType")) { | |
| 7625 if (ret->typeName != NULL) { | |
| 7626 /* | |
| 7627 * 3.2.3 : 4 | |
| 7628 * type and <simpleType> must not both be present. | |
| 7629 */ | |
| 7630 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4, | |
| 7631 NULL, node, child, | |
| 7632 "The attribute 'type' and the <simpleType> child " | |
| 7633 "are mutually exclusive", NULL); | |
| 7634 } else | |
| 7635 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0); | |
| 7636 child = child->next; | |
| 7637 } | |
| 7638 if (child != NULL) | |
| 7639 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 7640 NULL, node, child, NULL, | |
| 7641 "(annotation?, simpleType?)"); | |
| 7642 | |
| 7643 return (ret); | |
| 7644 } | |
| 7645 | |
| 7646 /** | |
| 7647 * xmlSchemaParseAttributeGroupRef: | |
| 7648 * @ctxt: a schema validation context | |
| 7649 * @schema: the schema being built | |
| 7650 * @node: a subtree containing XML Schema informations | |
| 7651 * | |
| 7652 * Parse an attribute group definition reference. | |
| 7653 * Note that a reference to an attribute group does not | |
| 7654 * correspond to any component at all. | |
| 7655 * *WARNING* this interface is highly subject to change | |
| 7656 * | |
| 7657 * Returns the attribute group or NULL in case of error. | |
| 7658 */ | |
| 7659 static xmlSchemaQNameRefPtr | |
| 7660 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt, | |
| 7661 xmlSchemaPtr schema, | |
| 7662 xmlNodePtr node) | |
| 7663 { | |
| 7664 xmlSchemaQNameRefPtr ret; | |
| 7665 xmlNodePtr child = NULL; | |
| 7666 xmlAttrPtr attr; | |
| 7667 const xmlChar *refNs = NULL, *ref = NULL; | |
| 7668 | |
| 7669 if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 7670 return (NULL); | |
| 7671 | |
| 7672 attr = xmlSchemaGetPropNode(node, "ref"); | |
| 7673 if (attr == NULL) { | |
| 7674 xmlSchemaPMissingAttrErr(pctxt, | |
| 7675 XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 7676 NULL, node, "ref", NULL); | |
| 7677 return (NULL); | |
| 7678 } | |
| 7679 xmlSchemaPValAttrNodeQName(pctxt, schema, | |
| 7680 NULL, attr, &refNs, &ref); | |
| 7681 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0) | |
| 7682 return(NULL); | |
| 7683 | |
| 7684 /* | |
| 7685 * Check for illegal attributes. | |
| 7686 */ | |
| 7687 attr = node->properties; | |
| 7688 while (attr != NULL) { | |
| 7689 if (attr->ns == NULL) { | |
| 7690 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) && | |
| 7691 (!xmlStrEqual(attr->name, BAD_CAST "id"))) | |
| 7692 { | |
| 7693 xmlSchemaPIllegalAttrErr(pctxt, | |
| 7694 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 7695 } | |
| 7696 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 7697 xmlSchemaPIllegalAttrErr(pctxt, | |
| 7698 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 7699 } | |
| 7700 attr = attr->next; | |
| 7701 } | |
| 7702 /* Attribute ID */ | |
| 7703 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); | |
| 7704 | |
| 7705 /* | |
| 7706 * And now for the children... | |
| 7707 */ | |
| 7708 child = node->children; | |
| 7709 if (IS_SCHEMA(child, "annotation")) { | |
| 7710 /* | |
| 7711 * TODO: We do not have a place to store the annotation, do we? | |
| 7712 */ | |
| 7713 xmlSchemaParseAnnotation(pctxt, child, 0); | |
| 7714 child = child->next; | |
| 7715 } | |
| 7716 if (child != NULL) { | |
| 7717 xmlSchemaPContentErr(pctxt, | |
| 7718 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 7719 NULL, node, child, NULL, | |
| 7720 "(annotation?)"); | |
| 7721 } | |
| 7722 | |
| 7723 /* | |
| 7724 * Handle attribute group redefinitions. | |
| 7725 */ | |
| 7726 if (pctxt->isRedefine && pctxt->redef && | |
| 7727 (pctxt->redef->item->type == | |
| 7728 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) && | |
| 7729 (ref == pctxt->redef->refName) && | |
| 7730 (refNs == pctxt->redef->refTargetNs)) | |
| 7731 { | |
| 7732 /* | |
| 7733 * SPEC src-redefine: | |
| 7734 * (7.1) "If it has an <attributeGroup> among its contents | |
| 7735 * the `actual value` of whose ref [attribute] is the same | |
| 7736 * as the `actual value` of its own name attribute plus | |
| 7737 * target namespace, then it must have exactly one such group." | |
| 7738 */ | |
| 7739 if (pctxt->redefCounter != 0) { | |
| 7740 xmlChar *str = NULL; | |
| 7741 | |
| 7742 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 7743 XML_SCHEMAP_SRC_REDEFINE, node, NULL, | |
| 7744 "The redefining attribute group definition " | |
| 7745 "'%s' must not contain more than one " | |
| 7746 "reference to the redefined definition", | |
| 7747 xmlSchemaFormatQName(&str, refNs, ref), NULL); | |
| 7748 FREE_AND_NULL(str); | |
| 7749 return(NULL); | |
| 7750 } | |
| 7751 pctxt->redefCounter++; | |
| 7752 /* | |
| 7753 * URGENT TODO: How to ensure that the reference will not be | |
| 7754 * handled by the normal component resolution mechanism? | |
| 7755 */ | |
| 7756 ret = xmlSchemaNewQNameRef(pctxt, | |
| 7757 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs); | |
| 7758 if (ret == NULL) | |
| 7759 return(NULL); | |
| 7760 ret->node = node; | |
| 7761 pctxt->redef->reference = WXS_BASIC_CAST ret; | |
| 7762 } else { | |
| 7763 /* | |
| 7764 * Create a QName-reference helper component. We will substitute this | |
| 7765 * component for the attribute uses of the referenced attribute group | |
| 7766 * definition. | |
| 7767 */ | |
| 7768 ret = xmlSchemaNewQNameRef(pctxt, | |
| 7769 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs); | |
| 7770 if (ret == NULL) | |
| 7771 return(NULL); | |
| 7772 ret->node = node; | |
| 7773 /* Add to pending items, to be able to resolve the reference. */ | |
| 7774 WXS_ADD_PENDING(pctxt, ret); | |
| 7775 } | |
| 7776 return (ret); | |
| 7777 } | |
| 7778 | |
| 7779 /** | |
| 7780 * xmlSchemaParseAttributeGroupDefinition: | |
| 7781 * @pctxt: a schema validation context | |
| 7782 * @schema: the schema being built | |
| 7783 * @node: a subtree containing XML Schema informations | |
| 7784 * | |
| 7785 * parse a XML schema Attribute Group declaration | |
| 7786 * *WARNING* this interface is highly subject to change | |
| 7787 * | |
| 7788 * Returns the attribute group definition or NULL in case of error. | |
| 7789 */ | |
| 7790 static xmlSchemaAttributeGroupPtr | |
| 7791 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt, | |
| 7792 xmlSchemaPtr schema, | |
| 7793 xmlNodePtr node) | |
| 7794 { | |
| 7795 const xmlChar *name; | |
| 7796 xmlSchemaAttributeGroupPtr ret; | |
| 7797 xmlNodePtr child = NULL; | |
| 7798 xmlAttrPtr attr; | |
| 7799 int hasRefs = 0; | |
| 7800 | |
| 7801 if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 7802 return (NULL); | |
| 7803 | |
| 7804 attr = xmlSchemaGetPropNode(node, "name"); | |
| 7805 if (attr == NULL) { | |
| 7806 xmlSchemaPMissingAttrErr(pctxt, | |
| 7807 XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 7808 NULL, node, "name", NULL); | |
| 7809 return (NULL); | |
| 7810 } | |
| 7811 /* | |
| 7812 * The name is crucial, exit if invalid. | |
| 7813 */ | |
| 7814 if (xmlSchemaPValAttrNode(pctxt, | |
| 7815 NULL, attr, | |
| 7816 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { | |
| 7817 return (NULL); | |
| 7818 } | |
| 7819 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema, | |
| 7820 name, pctxt->targetNamespace, node); | |
| 7821 if (ret == NULL) | |
| 7822 return (NULL); | |
| 7823 /* | |
| 7824 * Check for illegal attributes. | |
| 7825 */ | |
| 7826 attr = node->properties; | |
| 7827 while (attr != NULL) { | |
| 7828 if (attr->ns == NULL) { | |
| 7829 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) && | |
| 7830 (!xmlStrEqual(attr->name, BAD_CAST "id"))) | |
| 7831 { | |
| 7832 xmlSchemaPIllegalAttrErr(pctxt, | |
| 7833 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 7834 } | |
| 7835 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 7836 xmlSchemaPIllegalAttrErr(pctxt, | |
| 7837 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 7838 } | |
| 7839 attr = attr->next; | |
| 7840 } | |
| 7841 /* Attribute ID */ | |
| 7842 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); | |
| 7843 /* | |
| 7844 * And now for the children... | |
| 7845 */ | |
| 7846 child = node->children; | |
| 7847 if (IS_SCHEMA(child, "annotation")) { | |
| 7848 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1); | |
| 7849 child = child->next; | |
| 7850 } | |
| 7851 /* | |
| 7852 * Parse contained attribute decls/refs. | |
| 7853 */ | |
| 7854 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child, | |
| 7855 (xmlSchemaItemListPtr *) &(ret->attrUses), | |
| 7856 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1) | |
| 7857 return(NULL); | |
| 7858 if (hasRefs) | |
| 7859 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS; | |
| 7860 /* | |
| 7861 * Parse the attribute wildcard. | |
| 7862 */ | |
| 7863 if (IS_SCHEMA(child, "anyAttribute")) { | |
| 7864 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt, | |
| 7865 schema, child); | |
| 7866 child = child->next; | |
| 7867 } | |
| 7868 if (child != NULL) { | |
| 7869 xmlSchemaPContentErr(pctxt, | |
| 7870 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 7871 NULL, node, child, NULL, | |
| 7872 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))"); | |
| 7873 } | |
| 7874 return (ret); | |
| 7875 } | |
| 7876 | |
| 7877 /** | |
| 7878 * xmlSchemaPValAttrFormDefault: | |
| 7879 * @value: the value | |
| 7880 * @flags: the flags to be modified | |
| 7881 * @flagQualified: the specific flag for "qualified" | |
| 7882 * | |
| 7883 * Returns 0 if the value is valid, 1 otherwise. | |
| 7884 */ | |
| 7885 static int | |
| 7886 xmlSchemaPValAttrFormDefault(const xmlChar *value, | |
| 7887 int *flags, | |
| 7888 int flagQualified) | |
| 7889 { | |
| 7890 if (xmlStrEqual(value, BAD_CAST "qualified")) { | |
| 7891 if ((*flags & flagQualified) == 0) | |
| 7892 *flags |= flagQualified; | |
| 7893 } else if (!xmlStrEqual(value, BAD_CAST "unqualified")) | |
| 7894 return (1); | |
| 7895 | |
| 7896 return (0); | |
| 7897 } | |
| 7898 | |
| 7899 /** | |
| 7900 * xmlSchemaPValAttrBlockFinal: | |
| 7901 * @value: the value | |
| 7902 * @flags: the flags to be modified | |
| 7903 * @flagAll: the specific flag for "#all" | |
| 7904 * @flagExtension: the specific flag for "extension" | |
| 7905 * @flagRestriction: the specific flag for "restriction" | |
| 7906 * @flagSubstitution: the specific flag for "substitution" | |
| 7907 * @flagList: the specific flag for "list" | |
| 7908 * @flagUnion: the specific flag for "union" | |
| 7909 * | |
| 7910 * Validates the value of the attribute "final" and "block". The value | |
| 7911 * is converted into the specified flag values and returned in @flags. | |
| 7912 * | |
| 7913 * Returns 0 if the value is valid, 1 otherwise. | |
| 7914 */ | |
| 7915 | |
| 7916 static int | |
| 7917 xmlSchemaPValAttrBlockFinal(const xmlChar *value, | |
| 7918 int *flags, | |
| 7919 int flagAll, | |
| 7920 int flagExtension, | |
| 7921 int flagRestriction, | |
| 7922 int flagSubstitution, | |
| 7923 int flagList, | |
| 7924 int flagUnion) | |
| 7925 { | |
| 7926 int ret = 0; | |
| 7927 | |
| 7928 /* | |
| 7929 * TODO: This does not check for dublicate entries. | |
| 7930 */ | |
| 7931 if ((flags == NULL) || (value == NULL)) | |
| 7932 return (-1); | |
| 7933 if (value[0] == 0) | |
| 7934 return (0); | |
| 7935 if (xmlStrEqual(value, BAD_CAST "#all")) { | |
| 7936 if (flagAll != -1) | |
| 7937 *flags |= flagAll; | |
| 7938 else { | |
| 7939 if (flagExtension != -1) | |
| 7940 *flags |= flagExtension; | |
| 7941 if (flagRestriction != -1) | |
| 7942 *flags |= flagRestriction; | |
| 7943 if (flagSubstitution != -1) | |
| 7944 *flags |= flagSubstitution; | |
| 7945 if (flagList != -1) | |
| 7946 *flags |= flagList; | |
| 7947 if (flagUnion != -1) | |
| 7948 *flags |= flagUnion; | |
| 7949 } | |
| 7950 } else { | |
| 7951 const xmlChar *end, *cur = value; | |
| 7952 xmlChar *item; | |
| 7953 | |
| 7954 do { | |
| 7955 while (IS_BLANK_CH(*cur)) | |
| 7956 cur++; | |
| 7957 end = cur; | |
| 7958 while ((*end != 0) && (!(IS_BLANK_CH(*end)))) | |
| 7959 end++; | |
| 7960 if (end == cur) | |
| 7961 break; | |
| 7962 item = xmlStrndup(cur, end - cur); | |
| 7963 if (xmlStrEqual(item, BAD_CAST "extension")) { | |
| 7964 if (flagExtension != -1) { | |
| 7965 if ((*flags & flagExtension) == 0) | |
| 7966 *flags |= flagExtension; | |
| 7967 } else | |
| 7968 ret = 1; | |
| 7969 } else if (xmlStrEqual(item, BAD_CAST "restriction")) { | |
| 7970 if (flagRestriction != -1) { | |
| 7971 if ((*flags & flagRestriction) == 0) | |
| 7972 *flags |= flagRestriction; | |
| 7973 } else | |
| 7974 ret = 1; | |
| 7975 } else if (xmlStrEqual(item, BAD_CAST "substitution")) { | |
| 7976 if (flagSubstitution != -1) { | |
| 7977 if ((*flags & flagSubstitution) == 0) | |
| 7978 *flags |= flagSubstitution; | |
| 7979 } else | |
| 7980 ret = 1; | |
| 7981 } else if (xmlStrEqual(item, BAD_CAST "list")) { | |
| 7982 if (flagList != -1) { | |
| 7983 if ((*flags & flagList) == 0) | |
| 7984 *flags |= flagList; | |
| 7985 } else | |
| 7986 ret = 1; | |
| 7987 } else if (xmlStrEqual(item, BAD_CAST "union")) { | |
| 7988 if (flagUnion != -1) { | |
| 7989 if ((*flags & flagUnion) == 0) | |
| 7990 *flags |= flagUnion; | |
| 7991 } else | |
| 7992 ret = 1; | |
| 7993 } else | |
| 7994 ret = 1; | |
| 7995 if (item != NULL) | |
| 7996 xmlFree(item); | |
| 7997 cur = end; | |
| 7998 } while ((ret == 0) && (*cur != 0)); | |
| 7999 } | |
| 8000 | |
| 8001 return (ret); | |
| 8002 } | |
| 8003 | |
| 8004 static int | |
| 8005 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt, | |
| 8006 xmlSchemaIDCPtr idc, | |
| 8007 xmlSchemaIDCSelectPtr selector, | |
| 8008 xmlAttrPtr attr, | |
| 8009 int isField) | |
| 8010 { | |
| 8011 xmlNodePtr node; | |
| 8012 | |
| 8013 /* | |
| 8014 * c-selector-xpath: | |
| 8015 * Schema Component Constraint: Selector Value OK | |
| 8016 * | |
| 8017 * TODO: 1 The {selector} must be a valid XPath expression, as defined | |
| 8018 * in [XPath]. | |
| 8019 */ | |
| 8020 if (selector == NULL) { | |
| 8021 xmlSchemaPErr(ctxt, idc->node, | |
| 8022 XML_SCHEMAP_INTERNAL, | |
| 8023 "Internal error: xmlSchemaCheckCSelectorXPath, " | |
| 8024 "the selector is not specified.\n", NULL, NULL); | |
| 8025 return (-1); | |
| 8026 } | |
| 8027 if (attr == NULL) | |
| 8028 node = idc->node; | |
| 8029 else | |
| 8030 node = (xmlNodePtr) attr; | |
| 8031 if (selector->xpath == NULL) { | |
| 8032 xmlSchemaPCustomErr(ctxt, | |
| 8033 /* TODO: Adjust error code. */ | |
| 8034 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 8035 NULL, node, | |
| 8036 "The XPath expression of the selector is not valid", NULL); | |
| 8037 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE); | |
| 8038 } else { | |
| 8039 const xmlChar **nsArray = NULL; | |
| 8040 xmlNsPtr *nsList = NULL; | |
| 8041 /* | |
| 8042 * Compile the XPath expression. | |
| 8043 */ | |
| 8044 /* | |
| 8045 * TODO: We need the array of in-scope namespaces for compilation. | |
| 8046 * TODO: Call xmlPatterncompile with different options for selector/ | |
| 8047 * field. | |
| 8048 */ | |
| 8049 if (attr == NULL) | |
| 8050 nsList = NULL; | |
| 8051 else | |
| 8052 nsList = xmlGetNsList(attr->doc, attr->parent); | |
| 8053 /* | |
| 8054 * Build an array of prefixes and namespaces. | |
| 8055 */ | |
| 8056 if (nsList != NULL) { | |
| 8057 int i, count = 0; | |
| 8058 | |
| 8059 for (i = 0; nsList[i] != NULL; i++) | |
| 8060 count++; | |
| 8061 | |
| 8062 nsArray = (const xmlChar **) xmlMalloc( | |
| 8063 (count * 2 + 1) * sizeof(const xmlChar *)); | |
| 8064 if (nsArray == NULL) { | |
| 8065 xmlSchemaPErrMemory(ctxt, "allocating a namespace array", | |
| 8066 NULL); | |
| 8067 xmlFree(nsList); | |
| 8068 return (-1); | |
| 8069 } | |
| 8070 for (i = 0; i < count; i++) { | |
| 8071 nsArray[2 * i] = nsList[i]->href; | |
| 8072 nsArray[2 * i + 1] = nsList[i]->prefix; | |
| 8073 } | |
| 8074 nsArray[count * 2] = NULL; | |
| 8075 xmlFree(nsList); | |
| 8076 } | |
| 8077 /* | |
| 8078 * TODO: Differentiate between "selector" and "field". | |
| 8079 */ | |
| 8080 if (isField) | |
| 8081 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath, | |
| 8082 NULL, XML_PATTERN_XSFIELD, nsArray); | |
| 8083 else | |
| 8084 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath, | |
| 8085 NULL, XML_PATTERN_XSSEL, nsArray); | |
| 8086 if (nsArray != NULL) | |
| 8087 xmlFree((xmlChar **) nsArray); | |
| 8088 | |
| 8089 if (selector->xpathComp == NULL) { | |
| 8090 xmlSchemaPCustomErr(ctxt, | |
| 8091 /* TODO: Adjust error code? */ | |
| 8092 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 8093 NULL, node, | |
| 8094 "The XPath expression '%s' could not be " | |
| 8095 "compiled", selector->xpath); | |
| 8096 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE); | |
| 8097 } | |
| 8098 } | |
| 8099 return (0); | |
| 8100 } | |
| 8101 | |
| 8102 #define ADD_ANNOTATION(annot) \ | |
| 8103 xmlSchemaAnnotPtr cur = item->annot; \ | |
| 8104 if (item->annot == NULL) { \ | |
| 8105 item->annot = annot; \ | |
| 8106 return (annot); \ | |
| 8107 } \ | |
| 8108 cur = item->annot; \ | |
| 8109 if (cur->next != NULL) { \ | |
| 8110 cur = cur->next; \ | |
| 8111 } \ | |
| 8112 cur->next = annot; | |
| 8113 | |
| 8114 /** | |
| 8115 * xmlSchemaAssignAnnotation: | |
| 8116 * @item: the schema component | |
| 8117 * @annot: the annotation | |
| 8118 * | |
| 8119 * Adds the annotation to the given schema component. | |
| 8120 * | |
| 8121 * Returns the given annotaion. | |
| 8122 */ | |
| 8123 static xmlSchemaAnnotPtr | |
| 8124 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem, | |
| 8125 xmlSchemaAnnotPtr annot) | |
| 8126 { | |
| 8127 if ((annItem == NULL) || (annot == NULL)) | |
| 8128 return (NULL); | |
| 8129 switch (annItem->type) { | |
| 8130 case XML_SCHEMA_TYPE_ELEMENT: { | |
| 8131 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem; | |
| 8132 ADD_ANNOTATION(annot) | |
| 8133 } | |
| 8134 break; | |
| 8135 case XML_SCHEMA_TYPE_ATTRIBUTE: { | |
| 8136 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem; | |
| 8137 ADD_ANNOTATION(annot) | |
| 8138 } | |
| 8139 break; | |
| 8140 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: | |
| 8141 case XML_SCHEMA_TYPE_ANY: { | |
| 8142 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem; | |
| 8143 ADD_ANNOTATION(annot) | |
| 8144 } | |
| 8145 break; | |
| 8146 case XML_SCHEMA_TYPE_PARTICLE: | |
| 8147 case XML_SCHEMA_TYPE_IDC_KEY: | |
| 8148 case XML_SCHEMA_TYPE_IDC_KEYREF: | |
| 8149 case XML_SCHEMA_TYPE_IDC_UNIQUE: { | |
| 8150 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem; | |
| 8151 ADD_ANNOTATION(annot) | |
| 8152 } | |
| 8153 break; | |
| 8154 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: { | |
| 8155 xmlSchemaAttributeGroupPtr item = | |
| 8156 (xmlSchemaAttributeGroupPtr) annItem; | |
| 8157 ADD_ANNOTATION(annot) | |
| 8158 } | |
| 8159 break; | |
| 8160 case XML_SCHEMA_TYPE_NOTATION: { | |
| 8161 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem; | |
| 8162 ADD_ANNOTATION(annot) | |
| 8163 } | |
| 8164 break; | |
| 8165 case XML_SCHEMA_FACET_MININCLUSIVE: | |
| 8166 case XML_SCHEMA_FACET_MINEXCLUSIVE: | |
| 8167 case XML_SCHEMA_FACET_MAXINCLUSIVE: | |
| 8168 case XML_SCHEMA_FACET_MAXEXCLUSIVE: | |
| 8169 case XML_SCHEMA_FACET_TOTALDIGITS: | |
| 8170 case XML_SCHEMA_FACET_FRACTIONDIGITS: | |
| 8171 case XML_SCHEMA_FACET_PATTERN: | |
| 8172 case XML_SCHEMA_FACET_ENUMERATION: | |
| 8173 case XML_SCHEMA_FACET_WHITESPACE: | |
| 8174 case XML_SCHEMA_FACET_LENGTH: | |
| 8175 case XML_SCHEMA_FACET_MAXLENGTH: | |
| 8176 case XML_SCHEMA_FACET_MINLENGTH: { | |
| 8177 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem; | |
| 8178 ADD_ANNOTATION(annot) | |
| 8179 } | |
| 8180 break; | |
| 8181 case XML_SCHEMA_TYPE_SIMPLE: | |
| 8182 case XML_SCHEMA_TYPE_COMPLEX: { | |
| 8183 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem; | |
| 8184 ADD_ANNOTATION(annot) | |
| 8185 } | |
| 8186 break; | |
| 8187 case XML_SCHEMA_TYPE_GROUP: { | |
| 8188 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) ann
Item; | |
| 8189 ADD_ANNOTATION(annot) | |
| 8190 } | |
| 8191 break; | |
| 8192 case XML_SCHEMA_TYPE_SEQUENCE: | |
| 8193 case XML_SCHEMA_TYPE_CHOICE: | |
| 8194 case XML_SCHEMA_TYPE_ALL: { | |
| 8195 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem; | |
| 8196 ADD_ANNOTATION(annot) | |
| 8197 } | |
| 8198 break; | |
| 8199 default: | |
| 8200 xmlSchemaPCustomErr(NULL, | |
| 8201 XML_SCHEMAP_INTERNAL, | |
| 8202 NULL, NULL, | |
| 8203 "Internal error: xmlSchemaAddAnnotation, " | |
| 8204 "The item is not a annotated schema component", NULL); | |
| 8205 break; | |
| 8206 } | |
| 8207 return (annot); | |
| 8208 } | |
| 8209 | |
| 8210 /** | |
| 8211 * xmlSchemaParseIDCSelectorAndField: | |
| 8212 * @ctxt: a schema validation context | |
| 8213 * @schema: the schema being built | |
| 8214 * @node: a subtree containing XML Schema informations | |
| 8215 * | |
| 8216 * Parses a XML Schema identity-contraint definition's | |
| 8217 * <selector> and <field> elements. | |
| 8218 * | |
| 8219 * Returns the parsed identity-constraint definition. | |
| 8220 */ | |
| 8221 static xmlSchemaIDCSelectPtr | |
| 8222 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt, | |
| 8223 xmlSchemaIDCPtr idc, | |
| 8224 xmlNodePtr node, | |
| 8225 int isField) | |
| 8226 { | |
| 8227 xmlSchemaIDCSelectPtr item; | |
| 8228 xmlNodePtr child = NULL; | |
| 8229 xmlAttrPtr attr; | |
| 8230 | |
| 8231 /* | |
| 8232 * Check for illegal attributes. | |
| 8233 */ | |
| 8234 attr = node->properties; | |
| 8235 while (attr != NULL) { | |
| 8236 if (attr->ns == NULL) { | |
| 8237 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 8238 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) { | |
| 8239 xmlSchemaPIllegalAttrErr(ctxt, | |
| 8240 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 8241 } | |
| 8242 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 8243 xmlSchemaPIllegalAttrErr(ctxt, | |
| 8244 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 8245 } | |
| 8246 attr = attr->next; | |
| 8247 } | |
| 8248 /* | |
| 8249 * Create the item. | |
| 8250 */ | |
| 8251 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect)); | |
| 8252 if (item == NULL) { | |
| 8253 xmlSchemaPErrMemory(ctxt, | |
| 8254 "allocating a 'selector' of an identity-constraint definition", | |
| 8255 NULL); | |
| 8256 return (NULL); | |
| 8257 } | |
| 8258 memset(item, 0, sizeof(xmlSchemaIDCSelect)); | |
| 8259 /* | |
| 8260 * Attribute "xpath" (mandatory). | |
| 8261 */ | |
| 8262 attr = xmlSchemaGetPropNode(node, "xpath"); | |
| 8263 if (attr == NULL) { | |
| 8264 xmlSchemaPMissingAttrErr(ctxt, | |
| 8265 XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 8266 NULL, node, | |
| 8267 "name", NULL); | |
| 8268 } else { | |
| 8269 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 8270 /* | |
| 8271 * URGENT TODO: "field"s have an other syntax than "selector"s. | |
| 8272 */ | |
| 8273 | |
| 8274 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr, | |
| 8275 isField) == -1) { | |
| 8276 xmlSchemaPErr(ctxt, | |
| 8277 (xmlNodePtr) attr, | |
| 8278 XML_SCHEMAP_INTERNAL, | |
| 8279 "Internal error: xmlSchemaParseIDCSelectorAndField, " | |
| 8280 "validating the XPath expression of a IDC selector.\n", | |
| 8281 NULL, NULL); | |
| 8282 } | |
| 8283 | |
| 8284 } | |
| 8285 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 8286 /* | |
| 8287 * And now for the children... | |
| 8288 */ | |
| 8289 child = node->children; | |
| 8290 if (IS_SCHEMA(child, "annotation")) { | |
| 8291 /* | |
| 8292 * Add the annotation to the parent IDC. | |
| 8293 */ | |
| 8294 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc, | |
| 8295 xmlSchemaParseAnnotation(ctxt, child, 1)); | |
| 8296 child = child->next; | |
| 8297 } | |
| 8298 if (child != NULL) { | |
| 8299 xmlSchemaPContentErr(ctxt, | |
| 8300 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 8301 NULL, node, child, | |
| 8302 NULL, "(annotation?)"); | |
| 8303 } | |
| 8304 | |
| 8305 return (item); | |
| 8306 } | |
| 8307 | |
| 8308 /** | |
| 8309 * xmlSchemaParseIDC: | |
| 8310 * @ctxt: a schema validation context | |
| 8311 * @schema: the schema being built | |
| 8312 * @node: a subtree containing XML Schema informations | |
| 8313 * | |
| 8314 * Parses a XML Schema identity-contraint definition. | |
| 8315 * | |
| 8316 * Returns the parsed identity-constraint definition. | |
| 8317 */ | |
| 8318 static xmlSchemaIDCPtr | |
| 8319 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt, | |
| 8320 xmlSchemaPtr schema, | |
| 8321 xmlNodePtr node, | |
| 8322 xmlSchemaTypeType idcCategory, | |
| 8323 const xmlChar *targetNamespace) | |
| 8324 { | |
| 8325 xmlSchemaIDCPtr item = NULL; | |
| 8326 xmlNodePtr child = NULL; | |
| 8327 xmlAttrPtr attr; | |
| 8328 const xmlChar *name = NULL; | |
| 8329 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL; | |
| 8330 | |
| 8331 /* | |
| 8332 * Check for illegal attributes. | |
| 8333 */ | |
| 8334 attr = node->properties; | |
| 8335 while (attr != NULL) { | |
| 8336 if (attr->ns == NULL) { | |
| 8337 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 8338 (!xmlStrEqual(attr->name, BAD_CAST "name")) && | |
| 8339 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) || | |
| 8340 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) { | |
| 8341 xmlSchemaPIllegalAttrErr(ctxt, | |
| 8342 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 8343 } | |
| 8344 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 8345 xmlSchemaPIllegalAttrErr(ctxt, | |
| 8346 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 8347 } | |
| 8348 attr = attr->next; | |
| 8349 } | |
| 8350 /* | |
| 8351 * Attribute "name" (mandatory). | |
| 8352 */ | |
| 8353 attr = xmlSchemaGetPropNode(node, "name"); | |
| 8354 if (attr == NULL) { | |
| 8355 xmlSchemaPMissingAttrErr(ctxt, | |
| 8356 XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 8357 NULL, node, | |
| 8358 "name", NULL); | |
| 8359 return (NULL); | |
| 8360 } else if (xmlSchemaPValAttrNode(ctxt, | |
| 8361 NULL, attr, | |
| 8362 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { | |
| 8363 return (NULL); | |
| 8364 } | |
| 8365 /* Create the component. */ | |
| 8366 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace, | |
| 8367 idcCategory, node); | |
| 8368 if (item == NULL) | |
| 8369 return(NULL); | |
| 8370 | |
| 8371 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 8372 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) { | |
| 8373 /* | |
| 8374 * Attribute "refer" (mandatory). | |
| 8375 */ | |
| 8376 attr = xmlSchemaGetPropNode(node, "refer"); | |
| 8377 if (attr == NULL) { | |
| 8378 xmlSchemaPMissingAttrErr(ctxt, | |
| 8379 XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 8380 NULL, node, | |
| 8381 "refer", NULL); | |
| 8382 } else { | |
| 8383 /* | |
| 8384 * Create a reference item. | |
| 8385 */ | |
| 8386 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY, | |
| 8387 NULL, NULL); | |
| 8388 if (item->ref == NULL) | |
| 8389 return (NULL); | |
| 8390 xmlSchemaPValAttrNodeQName(ctxt, schema, | |
| 8391 NULL, attr, | |
| 8392 &(item->ref->targetNamespace), | |
| 8393 &(item->ref->name)); | |
| 8394 xmlSchemaCheckReference(ctxt, schema, node, attr, | |
| 8395 item->ref->targetNamespace); | |
| 8396 } | |
| 8397 } | |
| 8398 /* | |
| 8399 * And now for the children... | |
| 8400 */ | |
| 8401 child = node->children; | |
| 8402 if (IS_SCHEMA(child, "annotation")) { | |
| 8403 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | |
| 8404 child = child->next; | |
| 8405 } | |
| 8406 if (child == NULL) { | |
| 8407 xmlSchemaPContentErr(ctxt, | |
| 8408 XML_SCHEMAP_S4S_ELEM_MISSING, | |
| 8409 NULL, node, child, | |
| 8410 "A child element is missing", | |
| 8411 "(annotation?, (selector, field+))"); | |
| 8412 } | |
| 8413 /* | |
| 8414 * Child element <selector>. | |
| 8415 */ | |
| 8416 if (IS_SCHEMA(child, "selector")) { | |
| 8417 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, | |
| 8418 item, child, 0); | |
| 8419 child = child->next; | |
| 8420 /* | |
| 8421 * Child elements <field>. | |
| 8422 */ | |
| 8423 if (IS_SCHEMA(child, "field")) { | |
| 8424 do { | |
| 8425 field = xmlSchemaParseIDCSelectorAndField(ctxt, | |
| 8426 item, child, 1); | |
| 8427 if (field != NULL) { | |
| 8428 field->index = item->nbFields; | |
| 8429 item->nbFields++; | |
| 8430 if (lastField != NULL) | |
| 8431 lastField->next = field; | |
| 8432 else | |
| 8433 item->fields = field; | |
| 8434 lastField = field; | |
| 8435 } | |
| 8436 child = child->next; | |
| 8437 } while (IS_SCHEMA(child, "field")); | |
| 8438 } else { | |
| 8439 xmlSchemaPContentErr(ctxt, | |
| 8440 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 8441 NULL, node, child, | |
| 8442 NULL, "(annotation?, (selector, field+))"); | |
| 8443 } | |
| 8444 } | |
| 8445 if (child != NULL) { | |
| 8446 xmlSchemaPContentErr(ctxt, | |
| 8447 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 8448 NULL, node, child, | |
| 8449 NULL, "(annotation?, (selector, field+))"); | |
| 8450 } | |
| 8451 | |
| 8452 return (item); | |
| 8453 } | |
| 8454 | |
| 8455 /** | |
| 8456 * xmlSchemaParseElement: | |
| 8457 * @ctxt: a schema validation context | |
| 8458 * @schema: the schema being built | |
| 8459 * @node: a subtree containing XML Schema informations | |
| 8460 * @topLevel: indicates if this is global declaration | |
| 8461 * | |
| 8462 * Parses a XML schema element declaration. | |
| 8463 * *WARNING* this interface is highly subject to change | |
| 8464 * | |
| 8465 * Returns the element declaration or a particle; NULL in case | |
| 8466 * of an error or if the particle has minOccurs==maxOccurs==0. | |
| 8467 */ | |
| 8468 static xmlSchemaBasicItemPtr | |
| 8469 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 8470 xmlNodePtr node, int *isElemRef, int topLevel) | |
| 8471 { | |
| 8472 xmlSchemaElementPtr decl = NULL; | |
| 8473 xmlSchemaParticlePtr particle = NULL; | |
| 8474 xmlSchemaAnnotPtr annot = NULL; | |
| 8475 xmlNodePtr child = NULL; | |
| 8476 xmlAttrPtr attr, nameAttr; | |
| 8477 int min, max, isRef = 0; | |
| 8478 xmlChar *des = NULL; | |
| 8479 | |
| 8480 /* 3.3.3 Constraints on XML Representations of Element Declarations */ | |
| 8481 /* TODO: Complete implementation of 3.3.6 */ | |
| 8482 | |
| 8483 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 8484 return (NULL); | |
| 8485 | |
| 8486 if (isElemRef != NULL) | |
| 8487 *isElemRef = 0; | |
| 8488 /* | |
| 8489 * If we get a "ref" attribute on a local <element> we will assume it's | |
| 8490 * a reference - even if there's a "name" attribute; this seems to be more | |
| 8491 * robust. | |
| 8492 */ | |
| 8493 nameAttr = xmlSchemaGetPropNode(node, "name"); | |
| 8494 attr = xmlSchemaGetPropNode(node, "ref"); | |
| 8495 if ((topLevel) || (attr == NULL)) { | |
| 8496 if (nameAttr == NULL) { | |
| 8497 xmlSchemaPMissingAttrErr(ctxt, | |
| 8498 XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 8499 NULL, node, "name", NULL); | |
| 8500 return (NULL); | |
| 8501 } | |
| 8502 } else | |
| 8503 isRef = 1; | |
| 8504 | |
| 8505 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 8506 child = node->children; | |
| 8507 if (IS_SCHEMA(child, "annotation")) { | |
| 8508 annot = xmlSchemaParseAnnotation(ctxt, child, 1); | |
| 8509 child = child->next; | |
| 8510 } | |
| 8511 /* | |
| 8512 * Skip particle part if a global declaration. | |
| 8513 */ | |
| 8514 if (topLevel) | |
| 8515 goto declaration_part; | |
| 8516 /* | |
| 8517 * The particle part ================================================== | |
| 8518 */ | |
| 8519 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger"); | |
| 8520 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger |
unbounded)"); | |
| 8521 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max); | |
| 8522 particle = xmlSchemaAddParticle(ctxt, node, min, max); | |
| 8523 if (particle == NULL) | |
| 8524 goto return_null; | |
| 8525 | |
| 8526 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */ | |
| 8527 | |
| 8528 if (isRef) { | |
| 8529 const xmlChar *refNs = NULL, *ref = NULL; | |
| 8530 xmlSchemaQNameRefPtr refer = NULL; | |
| 8531 /* | |
| 8532 * The reference part ============================================= | |
| 8533 */ | |
| 8534 if (isElemRef != NULL) | |
| 8535 *isElemRef = 1; | |
| 8536 | |
| 8537 xmlSchemaPValAttrNodeQName(ctxt, schema, | |
| 8538 NULL, attr, &refNs, &ref); | |
| 8539 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs); | |
| 8540 /* | |
| 8541 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both" | |
| 8542 */ | |
| 8543 if (nameAttr != NULL) { | |
| 8544 xmlSchemaPMutualExclAttrErr(ctxt, | |
| 8545 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name"); | |
| 8546 } | |
| 8547 /* | |
| 8548 * Check for illegal attributes. | |
| 8549 */ | |
| 8550 attr = node->properties; | |
| 8551 while (attr != NULL) { | |
| 8552 if (attr->ns == NULL) { | |
| 8553 if (xmlStrEqual(attr->name, BAD_CAST "ref") || | |
| 8554 xmlStrEqual(attr->name, BAD_CAST "name") || | |
| 8555 xmlStrEqual(attr->name, BAD_CAST "id") || | |
| 8556 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") || | |
| 8557 xmlStrEqual(attr->name, BAD_CAST "minOccurs")) | |
| 8558 { | |
| 8559 attr = attr->next; | |
| 8560 continue; | |
| 8561 } else { | |
| 8562 /* SPEC (3.3.3 : 2.2) */ | |
| 8563 xmlSchemaPCustomAttrErr(ctxt, | |
| 8564 XML_SCHEMAP_SRC_ELEMENT_2_2, | |
| 8565 NULL, NULL, attr, | |
| 8566 "Only the attributes 'minOccurs', 'maxOccurs' and " | |
| 8567 "'id' are allowed in addition to 'ref'"); | |
| 8568 break; | |
| 8569 } | |
| 8570 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 8571 xmlSchemaPIllegalAttrErr(ctxt, | |
| 8572 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 8573 } | |
| 8574 attr = attr->next; | |
| 8575 } | |
| 8576 /* | |
| 8577 * No children except <annotation> expected. | |
| 8578 */ | |
| 8579 if (child != NULL) { | |
| 8580 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 8581 NULL, node, child, NULL, "(annotation?)"); | |
| 8582 } | |
| 8583 if ((min == 0) && (max == 0)) | |
| 8584 goto return_null; | |
| 8585 /* | |
| 8586 * Create the reference item and attach it to the particle. | |
| 8587 */ | |
| 8588 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT, | |
| 8589 ref, refNs); | |
| 8590 if (refer == NULL) | |
| 8591 goto return_null; | |
| 8592 particle->children = (xmlSchemaTreeItemPtr) refer; | |
| 8593 particle->annot = annot; | |
| 8594 /* | |
| 8595 * Add the particle to pending components, since the reference | |
| 8596 * need to be resolved. | |
| 8597 */ | |
| 8598 WXS_ADD_PENDING(ctxt, particle); | |
| 8599 return ((xmlSchemaBasicItemPtr) particle); | |
| 8600 } | |
| 8601 /* | |
| 8602 * The declaration part =============================================== | |
| 8603 */ | |
| 8604 declaration_part: | |
| 8605 { | |
| 8606 const xmlChar *ns = NULL, *fixed, *name, *attrValue; | |
| 8607 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL; | |
| 8608 | |
| 8609 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr, | |
| 8610 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) | |
| 8611 goto return_null; | |
| 8612 /* | |
| 8613 * Evaluate the target namespace. | |
| 8614 */ | |
| 8615 if (topLevel) { | |
| 8616 ns = ctxt->targetNamespace; | |
| 8617 } else { | |
| 8618 attr = xmlSchemaGetPropNode(node, "form"); | |
| 8619 if (attr != NULL) { | |
| 8620 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 8621 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) { | |
| 8622 ns = ctxt->targetNamespace; | |
| 8623 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) { | |
| 8624 xmlSchemaPSimpleTypeErr(ctxt, | |
| 8625 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 8626 NULL, (xmlNodePtr) attr, | |
| 8627 NULL, "(qualified | unqualified)", | |
| 8628 attrValue, NULL, NULL, NULL); | |
| 8629 } | |
| 8630 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM) | |
| 8631 ns = ctxt->targetNamespace; | |
| 8632 } | |
| 8633 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel); | |
| 8634 if (decl == NULL) { | |
| 8635 goto return_null; | |
| 8636 } | |
| 8637 /* | |
| 8638 * Check for illegal attributes. | |
| 8639 */ | |
| 8640 attr = node->properties; | |
| 8641 while (attr != NULL) { | |
| 8642 if (attr->ns == NULL) { | |
| 8643 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) && | |
| 8644 (!xmlStrEqual(attr->name, BAD_CAST "type")) && | |
| 8645 (!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 8646 (!xmlStrEqual(attr->name, BAD_CAST "default")) && | |
| 8647 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) && | |
| 8648 (!xmlStrEqual(attr->name, BAD_CAST "block")) && | |
| 8649 (!xmlStrEqual(attr->name, BAD_CAST "nillable"))) | |
| 8650 { | |
| 8651 if (topLevel == 0) { | |
| 8652 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) && | |
| 8653 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) && | |
| 8654 (!xmlStrEqual(attr->name, BAD_CAST "form"))) | |
| 8655 { | |
| 8656 xmlSchemaPIllegalAttrErr(ctxt, | |
| 8657 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 8658 } | |
| 8659 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) && | |
| 8660 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) && | |
| 8661 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))
) { | |
| 8662 | |
| 8663 xmlSchemaPIllegalAttrErr(ctxt, | |
| 8664 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 8665 } | |
| 8666 } | |
| 8667 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 8668 | |
| 8669 xmlSchemaPIllegalAttrErr(ctxt, | |
| 8670 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 8671 } | |
| 8672 attr = attr->next; | |
| 8673 } | |
| 8674 /* | |
| 8675 * Extract/validate attributes. | |
| 8676 */ | |
| 8677 if (topLevel) { | |
| 8678 /* | |
| 8679 * Process top attributes of global element declarations here. | |
| 8680 */ | |
| 8681 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL; | |
| 8682 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL; | |
| 8683 xmlSchemaPValAttrQName(ctxt, schema, | |
| 8684 NULL, node, "substitutionGroup", | |
| 8685 &(decl->substGroupNs), &(decl->substGroup)); | |
| 8686 if (xmlGetBooleanProp(ctxt, node, "abstract", 0)) | |
| 8687 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT; | |
| 8688 /* | |
| 8689 * Attribute "final". | |
| 8690 */ | |
| 8691 attr = xmlSchemaGetPropNode(node, "final"); | |
| 8692 if (attr == NULL) { | |
| 8693 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) | |
| 8694 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION; | |
| 8695 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) | |
| 8696 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION; | |
| 8697 } else { | |
| 8698 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 8699 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags), | |
| 8700 -1, | |
| 8701 XML_SCHEMAS_ELEM_FINAL_EXTENSION, | |
| 8702 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) { | |
| 8703 xmlSchemaPSimpleTypeErr(ctxt, | |
| 8704 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 8705 NULL, (xmlNodePtr) attr, | |
| 8706 NULL, "(#all | List of (extension | restriction))", | |
| 8707 attrValue, NULL, NULL, NULL); | |
| 8708 } | |
| 8709 } | |
| 8710 } | |
| 8711 /* | |
| 8712 * Attribute "block". | |
| 8713 */ | |
| 8714 attr = xmlSchemaGetPropNode(node, "block"); | |
| 8715 if (attr == NULL) { | |
| 8716 /* | |
| 8717 * Apply default "block" values. | |
| 8718 */ | |
| 8719 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION) | |
| 8720 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION; | |
| 8721 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION) | |
| 8722 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION; | |
| 8723 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION) | |
| 8724 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION; | |
| 8725 } else { | |
| 8726 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 8727 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags), | |
| 8728 -1, | |
| 8729 XML_SCHEMAS_ELEM_BLOCK_EXTENSION, | |
| 8730 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION, | |
| 8731 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) { | |
| 8732 xmlSchemaPSimpleTypeErr(ctxt, | |
| 8733 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 8734 NULL, (xmlNodePtr) attr, | |
| 8735 NULL, "(#all | List of (extension | " | |
| 8736 "restriction | substitution))", attrValue, | |
| 8737 NULL, NULL, NULL); | |
| 8738 } | |
| 8739 } | |
| 8740 if (xmlGetBooleanProp(ctxt, node, "nillable", 0)) | |
| 8741 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE; | |
| 8742 | |
| 8743 attr = xmlSchemaGetPropNode(node, "type"); | |
| 8744 if (attr != NULL) { | |
| 8745 xmlSchemaPValAttrNodeQName(ctxt, schema, | |
| 8746 NULL, attr, | |
| 8747 &(decl->namedTypeNs), &(decl->namedType)); | |
| 8748 xmlSchemaCheckReference(ctxt, schema, node, | |
| 8749 attr, decl->namedTypeNs); | |
| 8750 } | |
| 8751 decl->value = xmlSchemaGetProp(ctxt, node, "default"); | |
| 8752 attr = xmlSchemaGetPropNode(node, "fixed"); | |
| 8753 if (attr != NULL) { | |
| 8754 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 8755 if (decl->value != NULL) { | |
| 8756 /* | |
| 8757 * 3.3.3 : 1 | |
| 8758 * default and fixed must not both be present. | |
| 8759 */ | |
| 8760 xmlSchemaPMutualExclAttrErr(ctxt, | |
| 8761 XML_SCHEMAP_SRC_ELEMENT_1, | |
| 8762 NULL, attr, "default", "fixed"); | |
| 8763 } else { | |
| 8764 decl->flags |= XML_SCHEMAS_ELEM_FIXED; | |
| 8765 decl->value = fixed; | |
| 8766 } | |
| 8767 } | |
| 8768 /* | |
| 8769 * And now for the children... | |
| 8770 */ | |
| 8771 if (IS_SCHEMA(child, "complexType")) { | |
| 8772 /* | |
| 8773 * 3.3.3 : 3 | |
| 8774 * "type" and either <simpleType> or <complexType> are mutually | |
| 8775 * 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 <complexType> child are " | |
| 8782 "mutually exclusive", NULL); | |
| 8783 } else | |
| 8784 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema,
child, 0); | |
| 8785 child = child->next; | |
| 8786 } else if (IS_SCHEMA(child, "simpleType")) { | |
| 8787 /* | |
| 8788 * 3.3.3 : 3 | |
| 8789 * "type" and either <simpleType> or <complexType> are | |
| 8790 * mutually exclusive | |
| 8791 */ | |
| 8792 if (decl->namedType != NULL) { | |
| 8793 xmlSchemaPContentErr(ctxt, | |
| 8794 XML_SCHEMAP_SRC_ELEMENT_3, | |
| 8795 NULL, node, child, | |
| 8796 "The attribute 'type' and the <simpleType> child are " | |
| 8797 "mutually exclusive", NULL); | |
| 8798 } else | |
| 8799 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema,
child, 0); | |
| 8800 child = child->next; | |
| 8801 } | |
| 8802 while ((IS_SCHEMA(child, "unique")) || | |
| 8803 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) { | |
| 8804 if (IS_SCHEMA(child, "unique")) { | |
| 8805 curIDC = xmlSchemaParseIDC(ctxt, schema, child, | |
| 8806 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace); | |
| 8807 } else if (IS_SCHEMA(child, "key")) { | |
| 8808 curIDC = xmlSchemaParseIDC(ctxt, schema, child, | |
| 8809 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace); | |
| 8810 } else if (IS_SCHEMA(child, "keyref")) { | |
| 8811 curIDC = xmlSchemaParseIDC(ctxt, schema, child, | |
| 8812 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace); | |
| 8813 } | |
| 8814 if (lastIDC != NULL) | |
| 8815 lastIDC->next = curIDC; | |
| 8816 else | |
| 8817 decl->idcs = (void *) curIDC; | |
| 8818 lastIDC = curIDC; | |
| 8819 child = child->next; | |
| 8820 } | |
| 8821 if (child != NULL) { | |
| 8822 xmlSchemaPContentErr(ctxt, | |
| 8823 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 8824 NULL, node, child, | |
| 8825 NULL, "(annotation?, ((simpleType | complexType)?, " | |
| 8826 "(unique | key | keyref)*))"); | |
| 8827 } | |
| 8828 decl->annot = annot; | |
| 8829 } | |
| 8830 /* | |
| 8831 * NOTE: Element Declaration Representation OK 4. will be checked at a | |
| 8832 * different layer. | |
| 8833 */ | |
| 8834 FREE_AND_NULL(des) | |
| 8835 if (topLevel) | |
| 8836 return ((xmlSchemaBasicItemPtr) decl); | |
| 8837 else { | |
| 8838 particle->children = (xmlSchemaTreeItemPtr) decl; | |
| 8839 return ((xmlSchemaBasicItemPtr) particle); | |
| 8840 } | |
| 8841 | |
| 8842 return_null: | |
| 8843 FREE_AND_NULL(des); | |
| 8844 if (annot != NULL) { | |
| 8845 if (particle != NULL) | |
| 8846 particle->annot = NULL; | |
| 8847 if (decl != NULL) | |
| 8848 decl->annot = NULL; | |
| 8849 xmlSchemaFreeAnnot(annot); | |
| 8850 } | |
| 8851 return (NULL); | |
| 8852 } | |
| 8853 | |
| 8854 /** | |
| 8855 * xmlSchemaParseUnion: | |
| 8856 * @ctxt: a schema validation context | |
| 8857 * @schema: the schema being built | |
| 8858 * @node: a subtree containing XML Schema informations | |
| 8859 * | |
| 8860 * parse a XML schema Union definition | |
| 8861 * *WARNING* this interface is highly subject to change | |
| 8862 * | |
| 8863 * Returns -1 in case of internal error, 0 in case of success and a positive | |
| 8864 * error code otherwise. | |
| 8865 */ | |
| 8866 static int | |
| 8867 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 8868 xmlNodePtr node) | |
| 8869 { | |
| 8870 xmlSchemaTypePtr type; | |
| 8871 xmlNodePtr child = NULL; | |
| 8872 xmlAttrPtr attr; | |
| 8873 const xmlChar *cur = NULL; | |
| 8874 | |
| 8875 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 8876 return (-1); | |
| 8877 /* Not a component, don't create it. */ | |
| 8878 type = ctxt->ctxtType; | |
| 8879 /* | |
| 8880 * Mark the simple type as being of variety "union". | |
| 8881 */ | |
| 8882 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION; | |
| 8883 /* | |
| 8884 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen, | |
| 8885 * then the `simple ur-type definition`." | |
| 8886 */ | |
| 8887 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE); | |
| 8888 /* | |
| 8889 * Check for illegal attributes. | |
| 8890 */ | |
| 8891 attr = node->properties; | |
| 8892 while (attr != NULL) { | |
| 8893 if (attr->ns == NULL) { | |
| 8894 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 8895 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) { | |
| 8896 xmlSchemaPIllegalAttrErr(ctxt, | |
| 8897 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 8898 } | |
| 8899 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 8900 xmlSchemaPIllegalAttrErr(ctxt, | |
| 8901 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 8902 } | |
| 8903 attr = attr->next; | |
| 8904 } | |
| 8905 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 8906 /* | |
| 8907 * Attribute "memberTypes". This is a list of QNames. | |
| 8908 * TODO: Check the value to contain anything. | |
| 8909 */ | |
| 8910 attr = xmlSchemaGetPropNode(node, "memberTypes"); | |
| 8911 if (attr != NULL) { | |
| 8912 const xmlChar *end; | |
| 8913 xmlChar *tmp; | |
| 8914 const xmlChar *localName, *nsName; | |
| 8915 xmlSchemaTypeLinkPtr link, lastLink = NULL; | |
| 8916 xmlSchemaQNameRefPtr ref; | |
| 8917 | |
| 8918 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 8919 type->base = cur; | |
| 8920 do { | |
| 8921 while (IS_BLANK_CH(*cur)) | |
| 8922 cur++; | |
| 8923 end = cur; | |
| 8924 while ((*end != 0) && (!(IS_BLANK_CH(*end)))) | |
| 8925 end++; | |
| 8926 if (end == cur) | |
| 8927 break; | |
| 8928 tmp = xmlStrndup(cur, end - cur); | |
| 8929 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, | |
| 8930 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) { | |
| 8931 /* | |
| 8932 * Create the member type link. | |
| 8933 */ | |
| 8934 link = (xmlSchemaTypeLinkPtr) | |
| 8935 xmlMalloc(sizeof(xmlSchemaTypeLink)); | |
| 8936 if (link == NULL) { | |
| 8937 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, " | |
| 8938 "allocating a type link", NULL); | |
| 8939 return (-1); | |
| 8940 } | |
| 8941 link->type = NULL; | |
| 8942 link->next = NULL; | |
| 8943 if (lastLink == NULL) | |
| 8944 type->memberTypes = link; | |
| 8945 else | |
| 8946 lastLink->next = link; | |
| 8947 lastLink = link; | |
| 8948 /* | |
| 8949 * Create a reference item. | |
| 8950 */ | |
| 8951 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE, | |
| 8952 localName, nsName); | |
| 8953 if (ref == NULL) { | |
| 8954 FREE_AND_NULL(tmp) | |
| 8955 return (-1); | |
| 8956 } | |
| 8957 /* | |
| 8958 * Assign the reference to the link, it will be resolved | |
| 8959 * later during fixup of the union simple type. | |
| 8960 */ | |
| 8961 link->type = (xmlSchemaTypePtr) ref; | |
| 8962 } | |
| 8963 FREE_AND_NULL(tmp) | |
| 8964 cur = end; | |
| 8965 } while (*cur != 0); | |
| 8966 | |
| 8967 } | |
| 8968 /* | |
| 8969 * And now for the children... | |
| 8970 */ | |
| 8971 child = node->children; | |
| 8972 if (IS_SCHEMA(child, "annotation")) { | |
| 8973 /* | |
| 8974 * Add the annotation to the simple type ancestor. | |
| 8975 */ | |
| 8976 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, | |
| 8977 xmlSchemaParseAnnotation(ctxt, child, 1)); | |
| 8978 child = child->next; | |
| 8979 } | |
| 8980 if (IS_SCHEMA(child, "simpleType")) { | |
| 8981 xmlSchemaTypePtr subtype, last = NULL; | |
| 8982 | |
| 8983 /* | |
| 8984 * Anchor the member types in the "subtypes" field of the | |
| 8985 * simple type. | |
| 8986 */ | |
| 8987 while (IS_SCHEMA(child, "simpleType")) { | |
| 8988 subtype = (xmlSchemaTypePtr) | |
| 8989 xmlSchemaParseSimpleType(ctxt, schema, child, 0); | |
| 8990 if (subtype != NULL) { | |
| 8991 if (last == NULL) { | |
| 8992 type->subtypes = subtype; | |
| 8993 last = subtype; | |
| 8994 } else { | |
| 8995 last->next = subtype; | |
| 8996 last = subtype; | |
| 8997 } | |
| 8998 last->next = NULL; | |
| 8999 } | |
| 9000 child = child->next; | |
| 9001 } | |
| 9002 } | |
| 9003 if (child != NULL) { | |
| 9004 xmlSchemaPContentErr(ctxt, | |
| 9005 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 9006 NULL, node, child, NULL, "(annotation?, simpleType*)"); | |
| 9007 } | |
| 9008 if ((attr == NULL) && (type->subtypes == NULL)) { | |
| 9009 /* | |
| 9010 * src-union-memberTypes-or-simpleTypes | |
| 9011 * Either the memberTypes [attribute] of the <union> element must | |
| 9012 * be non-empty or there must be at least one simpleType [child]. | |
| 9013 */ | |
| 9014 xmlSchemaPCustomErr(ctxt, | |
| 9015 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES, | |
| 9016 NULL, node, | |
| 9017 "Either the attribute 'memberTypes' or " | |
| 9018 "at least one <simpleType> child must be present", NULL); | |
| 9019 } | |
| 9020 return (0); | |
| 9021 } | |
| 9022 | |
| 9023 /** | |
| 9024 * xmlSchemaParseList: | |
| 9025 * @ctxt: a schema validation context | |
| 9026 * @schema: the schema being built | |
| 9027 * @node: a subtree containing XML Schema informations | |
| 9028 * | |
| 9029 * parse a XML schema List definition | |
| 9030 * *WARNING* this interface is highly subject to change | |
| 9031 * | |
| 9032 * Returns -1 in case of error, 0 if the declaration is improper and | |
| 9033 * 1 in case of success. | |
| 9034 */ | |
| 9035 static xmlSchemaTypePtr | |
| 9036 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 9037 xmlNodePtr node) | |
| 9038 { | |
| 9039 xmlSchemaTypePtr type; | |
| 9040 xmlNodePtr child = NULL; | |
| 9041 xmlAttrPtr attr; | |
| 9042 | |
| 9043 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 9044 return (NULL); | |
| 9045 /* Not a component, don't create it. */ | |
| 9046 type = ctxt->ctxtType; | |
| 9047 /* | |
| 9048 * Mark the type as being of variety "list". | |
| 9049 */ | |
| 9050 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST; | |
| 9051 /* | |
| 9052 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen, | |
| 9053 * then the `simple ur-type definition`." | |
| 9054 */ | |
| 9055 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE); | |
| 9056 /* | |
| 9057 * Check for illegal attributes. | |
| 9058 */ | |
| 9059 attr = node->properties; | |
| 9060 while (attr != NULL) { | |
| 9061 if (attr->ns == NULL) { | |
| 9062 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 9063 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) { | |
| 9064 xmlSchemaPIllegalAttrErr(ctxt, | |
| 9065 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 9066 } | |
| 9067 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 9068 xmlSchemaPIllegalAttrErr(ctxt, | |
| 9069 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 9070 } | |
| 9071 attr = attr->next; | |
| 9072 } | |
| 9073 | |
| 9074 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 9075 | |
| 9076 /* | |
| 9077 * Attribute "itemType". NOTE that we will use the "ref" and "refNs" | |
| 9078 * fields for holding the reference to the itemType. | |
| 9079 * | |
| 9080 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove | |
| 9081 * the "ref" fields. | |
| 9082 */ | |
| 9083 xmlSchemaPValAttrQName(ctxt, schema, NULL, | |
| 9084 node, "itemType", &(type->baseNs), &(type->base)); | |
| 9085 /* | |
| 9086 * And now for the children... | |
| 9087 */ | |
| 9088 child = node->children; | |
| 9089 if (IS_SCHEMA(child, "annotation")) { | |
| 9090 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, | |
| 9091 xmlSchemaParseAnnotation(ctxt, child, 1)); | |
| 9092 child = child->next; | |
| 9093 } | |
| 9094 if (IS_SCHEMA(child, "simpleType")) { | |
| 9095 /* | |
| 9096 * src-list-itemType-or-simpleType | |
| 9097 * Either the itemType [attribute] or the <simpleType> [child] of | |
| 9098 * the <list> element must be present, but not both. | |
| 9099 */ | |
| 9100 if (type->base != NULL) { | |
| 9101 xmlSchemaPCustomErr(ctxt, | |
| 9102 XML_SCHEMAP_SRC_SIMPLE_TYPE_1, | |
| 9103 NULL, node, | |
| 9104 "The attribute 'itemType' and the <simpleType> child " | |
| 9105 "are mutually exclusive", NULL); | |
| 9106 } else { | |
| 9107 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0); | |
| 9108 } | |
| 9109 child = child->next; | |
| 9110 } else if (type->base == NULL) { | |
| 9111 xmlSchemaPCustomErr(ctxt, | |
| 9112 XML_SCHEMAP_SRC_SIMPLE_TYPE_1, | |
| 9113 NULL, node, | |
| 9114 "Either the attribute 'itemType' or the <simpleType> child " | |
| 9115 "must be present", NULL); | |
| 9116 } | |
| 9117 if (child != NULL) { | |
| 9118 xmlSchemaPContentErr(ctxt, | |
| 9119 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 9120 NULL, node, child, NULL, "(annotation?, simpleType?)"); | |
| 9121 } | |
| 9122 if ((type->base == NULL) && | |
| 9123 (type->subtypes == NULL) && | |
| 9124 (xmlSchemaGetPropNode(node, "itemType") == NULL)) { | |
| 9125 xmlSchemaPCustomErr(ctxt, | |
| 9126 XML_SCHEMAP_SRC_SIMPLE_TYPE_1, | |
| 9127 NULL, node, | |
| 9128 "Either the attribute 'itemType' or the <simpleType> child " | |
| 9129 "must be present", NULL); | |
| 9130 } | |
| 9131 return (NULL); | |
| 9132 } | |
| 9133 | |
| 9134 /** | |
| 9135 * xmlSchemaParseSimpleType: | |
| 9136 * @ctxt: a schema validation context | |
| 9137 * @schema: the schema being built | |
| 9138 * @node: a subtree containing XML Schema informations | |
| 9139 * | |
| 9140 * parse a XML schema Simple Type definition | |
| 9141 * *WARNING* this interface is highly subject to change | |
| 9142 * | |
| 9143 * Returns -1 in case of error, 0 if the declaration is improper and | |
| 9144 * 1 in case of success. | |
| 9145 */ | |
| 9146 static xmlSchemaTypePtr | |
| 9147 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 9148 xmlNodePtr node, int topLevel) | |
| 9149 { | |
| 9150 xmlSchemaTypePtr type, oldCtxtType; | |
| 9151 xmlNodePtr child = NULL; | |
| 9152 const xmlChar *attrValue = NULL; | |
| 9153 xmlAttrPtr attr; | |
| 9154 int hasRestriction = 0; | |
| 9155 | |
| 9156 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 9157 return (NULL); | |
| 9158 | |
| 9159 if (topLevel) { | |
| 9160 attr = xmlSchemaGetPropNode(node, "name"); | |
| 9161 if (attr == NULL) { | |
| 9162 xmlSchemaPMissingAttrErr(ctxt, | |
| 9163 XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 9164 NULL, node, | |
| 9165 "name", NULL); | |
| 9166 return (NULL); | |
| 9167 } else { | |
| 9168 if (xmlSchemaPValAttrNode(ctxt, | |
| 9169 NULL, attr, | |
| 9170 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) | |
| 9171 return (NULL); | |
| 9172 /* | |
| 9173 * Skip built-in types. | |
| 9174 */ | |
| 9175 if (ctxt->isS4S) { | |
| 9176 xmlSchemaTypePtr biType; | |
| 9177 | |
| 9178 if (ctxt->isRedefine) { | |
| 9179 /* | |
| 9180 * REDEFINE: Disallow redefinition of built-in-types. | |
| 9181 * TODO: It seems that the spec does not say anything | |
| 9182 * about this case. | |
| 9183 */ | |
| 9184 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, | |
| 9185 NULL, node, | |
| 9186 "Redefinition of built-in simple types is not " | |
| 9187 "supported", NULL); | |
| 9188 return(NULL); | |
| 9189 } | |
| 9190 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs); | |
| 9191 if (biType != NULL) | |
| 9192 return (biType); | |
| 9193 } | |
| 9194 } | |
| 9195 } | |
| 9196 /* | |
| 9197 * TargetNamespace: | |
| 9198 * SPEC "The `actual value` of the targetNamespace [attribute] | |
| 9199 * of the <schema> ancestor element information item if present, | |
| 9200 * otherwise `absent`. | |
| 9201 */ | |
| 9202 if (topLevel == 0) { | |
| 9203 #ifdef ENABLE_NAMED_LOCALS | |
| 9204 char buf[40]; | |
| 9205 #endif | |
| 9206 /* | |
| 9207 * Parse as local simple type definition. | |
| 9208 */ | |
| 9209 #ifdef ENABLE_NAMED_LOCALS | |
| 9210 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1); | |
| 9211 type = xmlSchemaAddType(ctxt, schema, | |
| 9212 XML_SCHEMA_TYPE_SIMPLE, | |
| 9213 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1), | |
| 9214 ctxt->targetNamespace, node, 0); | |
| 9215 #else | |
| 9216 type = xmlSchemaAddType(ctxt, schema, | |
| 9217 XML_SCHEMA_TYPE_SIMPLE, | |
| 9218 NULL, ctxt->targetNamespace, node, 0); | |
| 9219 #endif | |
| 9220 if (type == NULL) | |
| 9221 return (NULL); | |
| 9222 type->type = XML_SCHEMA_TYPE_SIMPLE; | |
| 9223 type->contentType = XML_SCHEMA_CONTENT_SIMPLE; | |
| 9224 /* | |
| 9225 * Check for illegal attributes. | |
| 9226 */ | |
| 9227 attr = node->properties; | |
| 9228 while (attr != NULL) { | |
| 9229 if (attr->ns == NULL) { | |
| 9230 if (!xmlStrEqual(attr->name, BAD_CAST "id")) { | |
| 9231 xmlSchemaPIllegalAttrErr(ctxt, | |
| 9232 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 9233 } | |
| 9234 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 9235 xmlSchemaPIllegalAttrErr(ctxt, | |
| 9236 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 9237 } | |
| 9238 attr = attr->next; | |
| 9239 } | |
| 9240 } else { | |
| 9241 /* | |
| 9242 * Parse as global simple type definition. | |
| 9243 * | |
| 9244 * Note that attrValue is the value of the attribute "name" here. | |
| 9245 */ | |
| 9246 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE, | |
| 9247 attrValue, ctxt->targetNamespace, node, 1); | |
| 9248 if (type == NULL) | |
| 9249 return (NULL); | |
| 9250 type->type = XML_SCHEMA_TYPE_SIMPLE; | |
| 9251 type->contentType = XML_SCHEMA_CONTENT_SIMPLE; | |
| 9252 type->flags |= XML_SCHEMAS_TYPE_GLOBAL; | |
| 9253 /* | |
| 9254 * Check for illegal attributes. | |
| 9255 */ | |
| 9256 attr = node->properties; | |
| 9257 while (attr != NULL) { | |
| 9258 if (attr->ns == NULL) { | |
| 9259 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 9260 (!xmlStrEqual(attr->name, BAD_CAST "name")) && | |
| 9261 (!xmlStrEqual(attr->name, BAD_CAST "final"))) { | |
| 9262 xmlSchemaPIllegalAttrErr(ctxt, | |
| 9263 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 9264 } | |
| 9265 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 9266 xmlSchemaPIllegalAttrErr(ctxt, | |
| 9267 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 9268 } | |
| 9269 attr = attr->next; | |
| 9270 } | |
| 9271 /* | |
| 9272 * Attribute "final". | |
| 9273 */ | |
| 9274 attr = xmlSchemaGetPropNode(node, "final"); | |
| 9275 if (attr == NULL) { | |
| 9276 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) | |
| 9277 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION; | |
| 9278 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST) | |
| 9279 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST; | |
| 9280 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION) | |
| 9281 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION; | |
| 9282 } else { | |
| 9283 attrValue = xmlSchemaGetProp(ctxt, node, "final"); | |
| 9284 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags), | |
| 9285 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1, | |
| 9286 XML_SCHEMAS_TYPE_FINAL_LIST, | |
| 9287 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) { | |
| 9288 | |
| 9289 xmlSchemaPSimpleTypeErr(ctxt, | |
| 9290 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 9291 WXS_BASIC_CAST type, (xmlNodePtr) attr, | |
| 9292 NULL, "(#all | List of (list | union | restriction)", | |
| 9293 attrValue, NULL, NULL, NULL); | |
| 9294 } | |
| 9295 } | |
| 9296 } | |
| 9297 type->targetNamespace = ctxt->targetNamespace; | |
| 9298 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 9299 /* | |
| 9300 * And now for the children... | |
| 9301 */ | |
| 9302 oldCtxtType = ctxt->ctxtType; | |
| 9303 | |
| 9304 ctxt->ctxtType = type; | |
| 9305 | |
| 9306 child = node->children; | |
| 9307 if (IS_SCHEMA(child, "annotation")) { | |
| 9308 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | |
| 9309 child = child->next; | |
| 9310 } | |
| 9311 if (child == NULL) { | |
| 9312 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING, | |
| 9313 NULL, node, child, NULL, | |
| 9314 "(annotation?, (restriction | list | union))"); | |
| 9315 } else if (IS_SCHEMA(child, "restriction")) { | |
| 9316 xmlSchemaParseRestriction(ctxt, schema, child, | |
| 9317 XML_SCHEMA_TYPE_SIMPLE); | |
| 9318 hasRestriction = 1; | |
| 9319 child = child->next; | |
| 9320 } else if (IS_SCHEMA(child, "list")) { | |
| 9321 xmlSchemaParseList(ctxt, schema, child); | |
| 9322 child = child->next; | |
| 9323 } else if (IS_SCHEMA(child, "union")) { | |
| 9324 xmlSchemaParseUnion(ctxt, schema, child); | |
| 9325 child = child->next; | |
| 9326 } | |
| 9327 if (child != NULL) { | |
| 9328 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 9329 NULL, node, child, NULL, | |
| 9330 "(annotation?, (restriction | list | union))"); | |
| 9331 } | |
| 9332 /* | |
| 9333 * REDEFINE: SPEC src-redefine (5) | |
| 9334 * "Within the [children], each <simpleType> must have a | |
| 9335 * <restriction> among its [children] ... the `actual value` of whose | |
| 9336 * base [attribute] must be the same as the `actual value` of its own | |
| 9337 * name attribute plus target namespace;" | |
| 9338 */ | |
| 9339 if (topLevel && ctxt->isRedefine && (! hasRestriction)) { | |
| 9340 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, | |
| 9341 NULL, node, "This is a redefinition, thus the " | |
| 9342 "<simpleType> must have a <restriction> child", NULL); | |
| 9343 } | |
| 9344 | |
| 9345 ctxt->ctxtType = oldCtxtType; | |
| 9346 return (type); | |
| 9347 } | |
| 9348 | |
| 9349 /** | |
| 9350 * xmlSchemaParseModelGroupDefRef: | |
| 9351 * @ctxt: the parser context | |
| 9352 * @schema: the schema being built | |
| 9353 * @node: the node | |
| 9354 * | |
| 9355 * Parses a reference to a model group definition. | |
| 9356 * | |
| 9357 * We will return a particle component with a qname-component or | |
| 9358 * NULL in case of an error. | |
| 9359 */ | |
| 9360 static xmlSchemaTreeItemPtr | |
| 9361 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt, | |
| 9362 xmlSchemaPtr schema, | |
| 9363 xmlNodePtr node) | |
| 9364 { | |
| 9365 xmlSchemaParticlePtr item; | |
| 9366 xmlNodePtr child = NULL; | |
| 9367 xmlAttrPtr attr; | |
| 9368 const xmlChar *ref = NULL, *refNs = NULL; | |
| 9369 int min, max; | |
| 9370 | |
| 9371 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 9372 return (NULL); | |
| 9373 | |
| 9374 attr = xmlSchemaGetPropNode(node, "ref"); | |
| 9375 if (attr == NULL) { | |
| 9376 xmlSchemaPMissingAttrErr(ctxt, | |
| 9377 XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 9378 NULL, node, "ref", NULL); | |
| 9379 return (NULL); | |
| 9380 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, | |
| 9381 attr, &refNs, &ref) != 0) { | |
| 9382 return (NULL); | |
| 9383 } | |
| 9384 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs); | |
| 9385 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger"); | |
| 9386 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, | |
| 9387 "(xs:nonNegativeInteger | unbounded)"); | |
| 9388 /* | |
| 9389 * Check for illegal attributes. | |
| 9390 */ | |
| 9391 attr = node->properties; | |
| 9392 while (attr != NULL) { | |
| 9393 if (attr->ns == NULL) { | |
| 9394 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) && | |
| 9395 (!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 9396 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) && | |
| 9397 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) { | |
| 9398 xmlSchemaPIllegalAttrErr(ctxt, | |
| 9399 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 9400 } | |
| 9401 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 9402 xmlSchemaPIllegalAttrErr(ctxt, | |
| 9403 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 9404 } | |
| 9405 attr = attr->next; | |
| 9406 } | |
| 9407 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 9408 item = xmlSchemaAddParticle(ctxt, node, min, max); | |
| 9409 if (item == NULL) | |
| 9410 return (NULL); | |
| 9411 /* | |
| 9412 * Create a qname-reference and set as the term; it will be substituted | |
| 9413 * for the model group after the reference has been resolved. | |
| 9414 */ | |
| 9415 item->children = (xmlSchemaTreeItemPtr) | |
| 9416 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs); | |
| 9417 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max); | |
| 9418 /* | |
| 9419 * And now for the children... | |
| 9420 */ | |
| 9421 child = node->children; | |
| 9422 /* TODO: Is annotation even allowed for a model group reference? */ | |
| 9423 if (IS_SCHEMA(child, "annotation")) { | |
| 9424 /* | |
| 9425 * TODO: What to do exactly with the annotation? | |
| 9426 */ | |
| 9427 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | |
| 9428 child = child->next; | |
| 9429 } | |
| 9430 if (child != NULL) { | |
| 9431 xmlSchemaPContentErr(ctxt, | |
| 9432 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 9433 NULL, node, child, NULL, | |
| 9434 "(annotation?)"); | |
| 9435 } | |
| 9436 /* | |
| 9437 * Corresponds to no component at all if minOccurs==maxOccurs==0. | |
| 9438 */ | |
| 9439 if ((min == 0) && (max == 0)) | |
| 9440 return (NULL); | |
| 9441 | |
| 9442 return ((xmlSchemaTreeItemPtr) item); | |
| 9443 } | |
| 9444 | |
| 9445 /** | |
| 9446 * xmlSchemaParseModelGroupDefinition: | |
| 9447 * @ctxt: a schema validation context | |
| 9448 * @schema: the schema being built | |
| 9449 * @node: a subtree containing XML Schema informations | |
| 9450 * | |
| 9451 * Parses a XML schema model group definition. | |
| 9452 * | |
| 9453 * Note that the contraint src-redefine (6.2) can't be applied until | |
| 9454 * references have been resolved. So we will do this at the | |
| 9455 * component fixup level. | |
| 9456 * | |
| 9457 * *WARNING* this interface is highly subject to change | |
| 9458 * | |
| 9459 * Returns -1 in case of error, 0 if the declaration is improper and | |
| 9460 * 1 in case of success. | |
| 9461 */ | |
| 9462 static xmlSchemaModelGroupDefPtr | |
| 9463 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt, | |
| 9464 xmlSchemaPtr schema, | |
| 9465 xmlNodePtr node) | |
| 9466 { | |
| 9467 xmlSchemaModelGroupDefPtr item; | |
| 9468 xmlNodePtr child = NULL; | |
| 9469 xmlAttrPtr attr; | |
| 9470 const xmlChar *name; | |
| 9471 | |
| 9472 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 9473 return (NULL); | |
| 9474 | |
| 9475 attr = xmlSchemaGetPropNode(node, "name"); | |
| 9476 if (attr == NULL) { | |
| 9477 xmlSchemaPMissingAttrErr(ctxt, | |
| 9478 XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 9479 NULL, node, | |
| 9480 "name", NULL); | |
| 9481 return (NULL); | |
| 9482 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr, | |
| 9483 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { | |
| 9484 return (NULL); | |
| 9485 } | |
| 9486 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name, | |
| 9487 ctxt->targetNamespace, node); | |
| 9488 if (item == NULL) | |
| 9489 return (NULL); | |
| 9490 /* | |
| 9491 * Check for illegal attributes. | |
| 9492 */ | |
| 9493 attr = node->properties; | |
| 9494 while (attr != NULL) { | |
| 9495 if (attr->ns == NULL) { | |
| 9496 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) && | |
| 9497 (!xmlStrEqual(attr->name, BAD_CAST "id"))) { | |
| 9498 xmlSchemaPIllegalAttrErr(ctxt, | |
| 9499 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 9500 } | |
| 9501 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 9502 xmlSchemaPIllegalAttrErr(ctxt, | |
| 9503 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 9504 } | |
| 9505 attr = attr->next; | |
| 9506 } | |
| 9507 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 9508 /* | |
| 9509 * And now for the children... | |
| 9510 */ | |
| 9511 child = node->children; | |
| 9512 if (IS_SCHEMA(child, "annotation")) { | |
| 9513 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | |
| 9514 child = child->next; | |
| 9515 } | |
| 9516 if (IS_SCHEMA(child, "all")) { | |
| 9517 item->children = xmlSchemaParseModelGroup(ctxt, schema, child, | |
| 9518 XML_SCHEMA_TYPE_ALL, 0); | |
| 9519 child = child->next; | |
| 9520 } else if (IS_SCHEMA(child, "choice")) { | |
| 9521 item->children = xmlSchemaParseModelGroup(ctxt, schema, child, | |
| 9522 XML_SCHEMA_TYPE_CHOICE, 0); | |
| 9523 child = child->next; | |
| 9524 } else if (IS_SCHEMA(child, "sequence")) { | |
| 9525 item->children = xmlSchemaParseModelGroup(ctxt, schema, child, | |
| 9526 XML_SCHEMA_TYPE_SEQUENCE, 0); | |
| 9527 child = child->next; | |
| 9528 } | |
| 9529 | |
| 9530 | |
| 9531 | |
| 9532 if (child != NULL) { | |
| 9533 xmlSchemaPContentErr(ctxt, | |
| 9534 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 9535 NULL, node, child, NULL, | |
| 9536 "(annotation?, (all | choice | sequence)?)"); | |
| 9537 } | |
| 9538 return (item); | |
| 9539 } | |
| 9540 | |
| 9541 /** | |
| 9542 * xmlSchemaCleanupDoc: | |
| 9543 * @ctxt: a schema validation context | |
| 9544 * @node: the root of the document. | |
| 9545 * | |
| 9546 * removes unwanted nodes in a schemas document tree | |
| 9547 */ | |
| 9548 static void | |
| 9549 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root) | |
| 9550 { | |
| 9551 xmlNodePtr delete, cur; | |
| 9552 | |
| 9553 if ((ctxt == NULL) || (root == NULL)) return; | |
| 9554 | |
| 9555 /* | |
| 9556 * Remove all the blank text nodes | |
| 9557 */ | |
| 9558 delete = NULL; | |
| 9559 cur = root; | |
| 9560 while (cur != NULL) { | |
| 9561 if (delete != NULL) { | |
| 9562 xmlUnlinkNode(delete); | |
| 9563 xmlFreeNode(delete); | |
| 9564 delete = NULL; | |
| 9565 } | |
| 9566 if (cur->type == XML_TEXT_NODE) { | |
| 9567 if (IS_BLANK_NODE(cur)) { | |
| 9568 if (xmlNodeGetSpacePreserve(cur) != 1) { | |
| 9569 delete = cur; | |
| 9570 } | |
| 9571 } | |
| 9572 } else if ((cur->type != XML_ELEMENT_NODE) && | |
| 9573 (cur->type != XML_CDATA_SECTION_NODE)) { | |
| 9574 delete = cur; | |
| 9575 goto skip_children; | |
| 9576 } | |
| 9577 | |
| 9578 /* | |
| 9579 * Skip to next node | |
| 9580 */ | |
| 9581 if (cur->children != NULL) { | |
| 9582 if ((cur->children->type != XML_ENTITY_DECL) && | |
| 9583 (cur->children->type != XML_ENTITY_REF_NODE) && | |
| 9584 (cur->children->type != XML_ENTITY_NODE)) { | |
| 9585 cur = cur->children; | |
| 9586 continue; | |
| 9587 } | |
| 9588 } | |
| 9589 skip_children: | |
| 9590 if (cur->next != NULL) { | |
| 9591 cur = cur->next; | |
| 9592 continue; | |
| 9593 } | |
| 9594 | |
| 9595 do { | |
| 9596 cur = cur->parent; | |
| 9597 if (cur == NULL) | |
| 9598 break; | |
| 9599 if (cur == root) { | |
| 9600 cur = NULL; | |
| 9601 break; | |
| 9602 } | |
| 9603 if (cur->next != NULL) { | |
| 9604 cur = cur->next; | |
| 9605 break; | |
| 9606 } | |
| 9607 } while (cur != NULL); | |
| 9608 } | |
| 9609 if (delete != NULL) { | |
| 9610 xmlUnlinkNode(delete); | |
| 9611 xmlFreeNode(delete); | |
| 9612 delete = NULL; | |
| 9613 } | |
| 9614 } | |
| 9615 | |
| 9616 | |
| 9617 static void | |
| 9618 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema) | |
| 9619 { | |
| 9620 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM) | |
| 9621 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM; | |
| 9622 | |
| 9623 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) | |
| 9624 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR; | |
| 9625 | |
| 9626 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) | |
| 9627 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION; | |
| 9628 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) | |
| 9629 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION; | |
| 9630 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST) | |
| 9631 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST; | |
| 9632 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION) | |
| 9633 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION; | |
| 9634 | |
| 9635 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION) | |
| 9636 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION; | |
| 9637 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION) | |
| 9638 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION; | |
| 9639 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION) | |
| 9640 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION; | |
| 9641 } | |
| 9642 | |
| 9643 static int | |
| 9644 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt, | |
| 9645 xmlSchemaPtr schema, | |
| 9646 xmlNodePtr node) | |
| 9647 { | |
| 9648 xmlAttrPtr attr; | |
| 9649 const xmlChar *val; | |
| 9650 int res = 0, oldErrs = ctxt->nberrors; | |
| 9651 | |
| 9652 /* | |
| 9653 * Those flags should be moved to the parser context flags, | |
| 9654 * since they are not visible at the component level. I.e. | |
| 9655 * they are used if processing schema *documents* only. | |
| 9656 */ | |
| 9657 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 9658 HFAILURE; | |
| 9659 | |
| 9660 /* | |
| 9661 * Since the version is of type xs:token, we won't bother to | |
| 9662 * check it. | |
| 9663 */ | |
| 9664 /* REMOVED: | |
| 9665 attr = xmlSchemaGetPropNode(node, "version"); | |
| 9666 if (attr != NULL) { | |
| 9667 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr, | |
| 9668 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val); | |
| 9669 HFAILURE; | |
| 9670 } | |
| 9671 */ | |
| 9672 attr = xmlSchemaGetPropNode(node, "targetNamespace"); | |
| 9673 if (attr != NULL) { | |
| 9674 res = xmlSchemaPValAttrNode(ctxt, NULL, attr, | |
| 9675 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL); | |
| 9676 HFAILURE; | |
| 9677 if (res != 0) { | |
| 9678 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; | |
| 9679 goto exit; | |
| 9680 } | |
| 9681 } | |
| 9682 attr = xmlSchemaGetPropNode(node, "elementFormDefault"); | |
| 9683 if (attr != NULL) { | |
| 9684 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 9685 res = xmlSchemaPValAttrFormDefault(val, &schema->flags, | |
| 9686 XML_SCHEMAS_QUALIF_ELEM); | |
| 9687 HFAILURE; | |
| 9688 if (res != 0) { | |
| 9689 xmlSchemaPSimpleTypeErr(ctxt, | |
| 9690 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE, | |
| 9691 NULL, (xmlNodePtr) attr, NULL, | |
| 9692 "(qualified | unqualified)", val, NULL, NULL, NULL); | |
| 9693 } | |
| 9694 } | |
| 9695 attr = xmlSchemaGetPropNode(node, "attributeFormDefault"); | |
| 9696 if (attr != NULL) { | |
| 9697 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 9698 res = xmlSchemaPValAttrFormDefault(val, &schema->flags, | |
| 9699 XML_SCHEMAS_QUALIF_ATTR); | |
| 9700 HFAILURE; | |
| 9701 if (res != 0) { | |
| 9702 xmlSchemaPSimpleTypeErr(ctxt, | |
| 9703 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE, | |
| 9704 NULL, (xmlNodePtr) attr, NULL, | |
| 9705 "(qualified | unqualified)", val, NULL, NULL, NULL); | |
| 9706 } | |
| 9707 } | |
| 9708 attr = xmlSchemaGetPropNode(node, "finalDefault"); | |
| 9709 if (attr != NULL) { | |
| 9710 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 9711 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1, | |
| 9712 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION, | |
| 9713 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION, | |
| 9714 -1, | |
| 9715 XML_SCHEMAS_FINAL_DEFAULT_LIST, | |
| 9716 XML_SCHEMAS_FINAL_DEFAULT_UNION); | |
| 9717 HFAILURE; | |
| 9718 if (res != 0) { | |
| 9719 xmlSchemaPSimpleTypeErr(ctxt, | |
| 9720 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 9721 NULL, (xmlNodePtr) attr, NULL, | |
| 9722 "(#all | List of (extension | restriction | list | union))", | |
| 9723 val, NULL, NULL, NULL); | |
| 9724 } | |
| 9725 } | |
| 9726 attr = xmlSchemaGetPropNode(node, "blockDefault"); | |
| 9727 if (attr != NULL) { | |
| 9728 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | |
| 9729 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1, | |
| 9730 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION, | |
| 9731 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION, | |
| 9732 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1); | |
| 9733 HFAILURE; | |
| 9734 if (res != 0) { | |
| 9735 xmlSchemaPSimpleTypeErr(ctxt, | |
| 9736 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 9737 NULL, (xmlNodePtr) attr, NULL, | |
| 9738 "(#all | List of (extension | restriction | substitution))", | |
| 9739 val, NULL, NULL, NULL); | |
| 9740 } | |
| 9741 } | |
| 9742 | |
| 9743 exit: | |
| 9744 if (oldErrs != ctxt->nberrors) | |
| 9745 res = ctxt->err; | |
| 9746 return(res); | |
| 9747 exit_failure: | |
| 9748 return(-1); | |
| 9749 } | |
| 9750 | |
| 9751 /** | |
| 9752 * xmlSchemaParseSchemaTopLevel: | |
| 9753 * @ctxt: a schema validation context | |
| 9754 * @schema: the schemas | |
| 9755 * @nodes: the list of top level nodes | |
| 9756 * | |
| 9757 * Returns the internal XML Schema structure built from the resource or | |
| 9758 * NULL in case of error | |
| 9759 */ | |
| 9760 static int | |
| 9761 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt, | |
| 9762 xmlSchemaPtr schema, xmlNodePtr nodes) | |
| 9763 { | |
| 9764 xmlNodePtr child; | |
| 9765 xmlSchemaAnnotPtr annot; | |
| 9766 int res = 0, oldErrs, tmpOldErrs; | |
| 9767 | |
| 9768 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL)) | |
| 9769 return(-1); | |
| 9770 | |
| 9771 oldErrs = ctxt->nberrors; | |
| 9772 child = nodes; | |
| 9773 while ((IS_SCHEMA(child, "include")) || | |
| 9774 (IS_SCHEMA(child, "import")) || | |
| 9775 (IS_SCHEMA(child, "redefine")) || | |
| 9776 (IS_SCHEMA(child, "annotation"))) { | |
| 9777 if (IS_SCHEMA(child, "annotation")) { | |
| 9778 annot = xmlSchemaParseAnnotation(ctxt, child, 1); | |
| 9779 if (schema->annot == NULL) | |
| 9780 schema->annot = annot; | |
| 9781 else | |
| 9782 xmlSchemaFreeAnnot(annot); | |
| 9783 } else if (IS_SCHEMA(child, "import")) { | |
| 9784 tmpOldErrs = ctxt->nberrors; | |
| 9785 res = xmlSchemaParseImport(ctxt, schema, child); | |
| 9786 HFAILURE; | |
| 9787 HSTOP(ctxt); | |
| 9788 if (tmpOldErrs != ctxt->nberrors) | |
| 9789 goto exit; | |
| 9790 } else if (IS_SCHEMA(child, "include")) { | |
| 9791 tmpOldErrs = ctxt->nberrors; | |
| 9792 res = xmlSchemaParseInclude(ctxt, schema, child); | |
| 9793 HFAILURE; | |
| 9794 HSTOP(ctxt); | |
| 9795 if (tmpOldErrs != ctxt->nberrors) | |
| 9796 goto exit; | |
| 9797 } else if (IS_SCHEMA(child, "redefine")) { | |
| 9798 tmpOldErrs = ctxt->nberrors; | |
| 9799 res = xmlSchemaParseRedefine(ctxt, schema, child); | |
| 9800 HFAILURE; | |
| 9801 HSTOP(ctxt); | |
| 9802 if (tmpOldErrs != ctxt->nberrors) | |
| 9803 goto exit; | |
| 9804 } | |
| 9805 child = child->next; | |
| 9806 } | |
| 9807 /* | |
| 9808 * URGENT TODO: Change the functions to return int results. | |
| 9809 * We need especially to catch internal errors. | |
| 9810 */ | |
| 9811 while (child != NULL) { | |
| 9812 if (IS_SCHEMA(child, "complexType")) { | |
| 9813 xmlSchemaParseComplexType(ctxt, schema, child, 1); | |
| 9814 child = child->next; | |
| 9815 } else if (IS_SCHEMA(child, "simpleType")) { | |
| 9816 xmlSchemaParseSimpleType(ctxt, schema, child, 1); | |
| 9817 child = child->next; | |
| 9818 } else if (IS_SCHEMA(child, "element")) { | |
| 9819 xmlSchemaParseElement(ctxt, schema, child, NULL, 1); | |
| 9820 child = child->next; | |
| 9821 } else if (IS_SCHEMA(child, "attribute")) { | |
| 9822 xmlSchemaParseGlobalAttribute(ctxt, schema, child); | |
| 9823 child = child->next; | |
| 9824 } else if (IS_SCHEMA(child, "attributeGroup")) { | |
| 9825 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child); | |
| 9826 child = child->next; | |
| 9827 } else if (IS_SCHEMA(child, "group")) { | |
| 9828 xmlSchemaParseModelGroupDefinition(ctxt, schema, child); | |
| 9829 child = child->next; | |
| 9830 } else if (IS_SCHEMA(child, "notation")) { | |
| 9831 xmlSchemaParseNotation(ctxt, schema, child); | |
| 9832 child = child->next; | |
| 9833 } else { | |
| 9834 xmlSchemaPContentErr(ctxt, | |
| 9835 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 9836 NULL, child->parent, child, | |
| 9837 NULL, "((include | import | redefine | annotation)*, " | |
| 9838 "(((simpleType | complexType | group | attributeGroup) " | |
| 9839 "| element | attribute | notation), annotation*)*)"); | |
| 9840 child = child->next; | |
| 9841 } | |
| 9842 while (IS_SCHEMA(child, "annotation")) { | |
| 9843 /* | |
| 9844 * TODO: We should add all annotations. | |
| 9845 */ | |
| 9846 annot = xmlSchemaParseAnnotation(ctxt, child, 1); | |
| 9847 if (schema->annot == NULL) | |
| 9848 schema->annot = annot; | |
| 9849 else | |
| 9850 xmlSchemaFreeAnnot(annot); | |
| 9851 child = child->next; | |
| 9852 } | |
| 9853 } | |
| 9854 exit: | |
| 9855 ctxt->ctxtType = NULL; | |
| 9856 if (oldErrs != ctxt->nberrors) | |
| 9857 res = ctxt->err; | |
| 9858 return(res); | |
| 9859 exit_failure: | |
| 9860 return(-1); | |
| 9861 } | |
| 9862 | |
| 9863 static xmlSchemaSchemaRelationPtr | |
| 9864 xmlSchemaSchemaRelationCreate(void) | |
| 9865 { | |
| 9866 xmlSchemaSchemaRelationPtr ret; | |
| 9867 | |
| 9868 ret = (xmlSchemaSchemaRelationPtr) | |
| 9869 xmlMalloc(sizeof(xmlSchemaSchemaRelation)); | |
| 9870 if (ret == NULL) { | |
| 9871 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL); | |
| 9872 return(NULL); | |
| 9873 } | |
| 9874 memset(ret, 0, sizeof(xmlSchemaSchemaRelation)); | |
| 9875 return(ret); | |
| 9876 } | |
| 9877 | |
| 9878 #if 0 | |
| 9879 static void | |
| 9880 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel) | |
| 9881 { | |
| 9882 xmlFree(rel); | |
| 9883 } | |
| 9884 #endif | |
| 9885 | |
| 9886 static void | |
| 9887 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef) | |
| 9888 { | |
| 9889 xmlSchemaRedefPtr prev; | |
| 9890 | |
| 9891 while (redef != NULL) { | |
| 9892 prev = redef; | |
| 9893 redef = redef->next; | |
| 9894 xmlFree(prev); | |
| 9895 } | |
| 9896 } | |
| 9897 | |
| 9898 static void | |
| 9899 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con) | |
| 9900 { | |
| 9901 /* | |
| 9902 * After the construction context has been freed, there will be | |
| 9903 * no schema graph available any more. Only the schema buckets | |
| 9904 * will stay alive, which are put into the "schemasImports" and | |
| 9905 * "includes" slots of the xmlSchema. | |
| 9906 */ | |
| 9907 if (con->buckets != NULL) | |
| 9908 xmlSchemaItemListFree(con->buckets); | |
| 9909 if (con->pending != NULL) | |
| 9910 xmlSchemaItemListFree(con->pending); | |
| 9911 if (con->substGroups != NULL) | |
| 9912 xmlHashFree(con->substGroups, | |
| 9913 (xmlHashDeallocator) xmlSchemaSubstGroupFree); | |
| 9914 if (con->redefs != NULL) | |
| 9915 xmlSchemaRedefListFree(con->redefs); | |
| 9916 if (con->dict != NULL) | |
| 9917 xmlDictFree(con->dict); | |
| 9918 xmlFree(con); | |
| 9919 } | |
| 9920 | |
| 9921 static xmlSchemaConstructionCtxtPtr | |
| 9922 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict) | |
| 9923 { | |
| 9924 xmlSchemaConstructionCtxtPtr ret; | |
| 9925 | |
| 9926 ret = (xmlSchemaConstructionCtxtPtr) | |
| 9927 xmlMalloc(sizeof(xmlSchemaConstructionCtxt)); | |
| 9928 if (ret == NULL) { | |
| 9929 xmlSchemaPErrMemory(NULL, | |
| 9930 "allocating schema construction context", NULL); | |
| 9931 return (NULL); | |
| 9932 } | |
| 9933 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt)); | |
| 9934 | |
| 9935 ret->buckets = xmlSchemaItemListCreate(); | |
| 9936 if (ret->buckets == NULL) { | |
| 9937 xmlSchemaPErrMemory(NULL, | |
| 9938 "allocating list of schema buckets", NULL); | |
| 9939 xmlFree(ret); | |
| 9940 return (NULL); | |
| 9941 } | |
| 9942 ret->pending = xmlSchemaItemListCreate(); | |
| 9943 if (ret->pending == NULL) { | |
| 9944 xmlSchemaPErrMemory(NULL, | |
| 9945 "allocating list of pending global components", NULL); | |
| 9946 xmlSchemaConstructionCtxtFree(ret); | |
| 9947 return (NULL); | |
| 9948 } | |
| 9949 ret->dict = dict; | |
| 9950 xmlDictReference(dict); | |
| 9951 return(ret); | |
| 9952 } | |
| 9953 | |
| 9954 static xmlSchemaParserCtxtPtr | |
| 9955 xmlSchemaParserCtxtCreate(void) | |
| 9956 { | |
| 9957 xmlSchemaParserCtxtPtr ret; | |
| 9958 | |
| 9959 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt)); | |
| 9960 if (ret == NULL) { | |
| 9961 xmlSchemaPErrMemory(NULL, "allocating schema parser context", | |
| 9962 NULL); | |
| 9963 return (NULL); | |
| 9964 } | |
| 9965 memset(ret, 0, sizeof(xmlSchemaParserCtxt)); | |
| 9966 ret->type = XML_SCHEMA_CTXT_PARSER; | |
| 9967 ret->attrProhibs = xmlSchemaItemListCreate(); | |
| 9968 if (ret->attrProhibs == NULL) { | |
| 9969 xmlFree(ret); | |
| 9970 return(NULL); | |
| 9971 } | |
| 9972 return(ret); | |
| 9973 } | |
| 9974 | |
| 9975 /** | |
| 9976 * xmlSchemaNewParserCtxtUseDict: | |
| 9977 * @URL: the location of the schema | |
| 9978 * @dict: the dictionary to be used | |
| 9979 * | |
| 9980 * Create an XML Schemas parse context for that file/resource expected | |
| 9981 * to contain an XML Schemas file. | |
| 9982 * | |
| 9983 * Returns the parser context or NULL in case of error | |
| 9984 */ | |
| 9985 static xmlSchemaParserCtxtPtr | |
| 9986 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict) | |
| 9987 { | |
| 9988 xmlSchemaParserCtxtPtr ret; | |
| 9989 | |
| 9990 ret = xmlSchemaParserCtxtCreate(); | |
| 9991 if (ret == NULL) | |
| 9992 return (NULL); | |
| 9993 ret->dict = dict; | |
| 9994 xmlDictReference(dict); | |
| 9995 if (URL != NULL) | |
| 9996 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1); | |
| 9997 return (ret); | |
| 9998 } | |
| 9999 | |
| 10000 static int | |
| 10001 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt) | |
| 10002 { | |
| 10003 if (vctxt->pctxt == NULL) { | |
| 10004 if (vctxt->schema != NULL) | |
| 10005 vctxt->pctxt = | |
| 10006 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict); | |
| 10007 else | |
| 10008 vctxt->pctxt = xmlSchemaNewParserCtxt("*"); | |
| 10009 if (vctxt->pctxt == NULL) { | |
| 10010 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt", | |
| 10011 "failed to create a temp. parser context"); | |
| 10012 return (-1); | |
| 10013 } | |
| 10014 /* TODO: Pass user data. */ | |
| 10015 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, | |
| 10016 vctxt->warning, vctxt->errCtxt); | |
| 10017 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror, | |
| 10018 vctxt->errCtxt); | |
| 10019 } | |
| 10020 return (0); | |
| 10021 } | |
| 10022 | |
| 10023 /** | |
| 10024 * xmlSchemaGetSchemaBucket: | |
| 10025 * @pctxt: the schema parser context | |
| 10026 * @schemaLocation: the URI of the schema document | |
| 10027 * | |
| 10028 * Returns a schema bucket if it was already parsed. | |
| 10029 * | |
| 10030 * Returns a schema bucket if it was already parsed from | |
| 10031 * @schemaLocation, NULL otherwise. | |
| 10032 */ | |
| 10033 static xmlSchemaBucketPtr | |
| 10034 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt, | |
| 10035 const xmlChar *schemaLocation) | |
| 10036 { | |
| 10037 xmlSchemaBucketPtr cur; | |
| 10038 xmlSchemaItemListPtr list; | |
| 10039 | |
| 10040 list = pctxt->constructor->buckets; | |
| 10041 if (list->nbItems == 0) | |
| 10042 return(NULL); | |
| 10043 else { | |
| 10044 int i; | |
| 10045 for (i = 0; i < list->nbItems; i++) { | |
| 10046 cur = (xmlSchemaBucketPtr) list->items[i]; | |
| 10047 /* Pointer comparison! */ | |
| 10048 if (cur->schemaLocation == schemaLocation) | |
| 10049 return(cur); | |
| 10050 } | |
| 10051 } | |
| 10052 return(NULL); | |
| 10053 } | |
| 10054 | |
| 10055 static xmlSchemaBucketPtr | |
| 10056 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt, | |
| 10057 const xmlChar *schemaLocation, | |
| 10058 const xmlChar *targetNamespace) | |
| 10059 { | |
| 10060 xmlSchemaBucketPtr cur; | |
| 10061 xmlSchemaItemListPtr list; | |
| 10062 | |
| 10063 list = pctxt->constructor->buckets; | |
| 10064 if (list->nbItems == 0) | |
| 10065 return(NULL); | |
| 10066 else { | |
| 10067 int i; | |
| 10068 for (i = 0; i < list->nbItems; i++) { | |
| 10069 cur = (xmlSchemaBucketPtr) list->items[i]; | |
| 10070 /* Pointer comparison! */ | |
| 10071 if ((cur->origTargetNamespace == NULL) && | |
| 10072 (cur->schemaLocation == schemaLocation) && | |
| 10073 (cur->targetNamespace == targetNamespace)) | |
| 10074 return(cur); | |
| 10075 } | |
| 10076 } | |
| 10077 return(NULL); | |
| 10078 } | |
| 10079 | |
| 10080 | |
| 10081 #define IS_BAD_SCHEMA_DOC(b) \ | |
| 10082 (((b)->doc == NULL) && ((b)->schemaLocation != NULL)) | |
| 10083 | |
| 10084 static xmlSchemaBucketPtr | |
| 10085 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt, | |
| 10086 const xmlChar *targetNamespace, | |
| 10087 int imported) | |
| 10088 { | |
| 10089 xmlSchemaBucketPtr cur; | |
| 10090 xmlSchemaItemListPtr list; | |
| 10091 | |
| 10092 list = pctxt->constructor->buckets; | |
| 10093 if (list->nbItems == 0) | |
| 10094 return(NULL); | |
| 10095 else { | |
| 10096 int i; | |
| 10097 for (i = 0; i < list->nbItems; i++) { | |
| 10098 cur = (xmlSchemaBucketPtr) list->items[i]; | |
| 10099 if ((! IS_BAD_SCHEMA_DOC(cur)) && | |
| 10100 (cur->origTargetNamespace == targetNamespace) && | |
| 10101 ((imported && cur->imported) || | |
| 10102 ((!imported) && (!cur->imported)))) | |
| 10103 return(cur); | |
| 10104 } | |
| 10105 } | |
| 10106 return(NULL); | |
| 10107 } | |
| 10108 | |
| 10109 static int | |
| 10110 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt, | |
| 10111 xmlSchemaPtr schema, | |
| 10112 xmlSchemaBucketPtr bucket) | |
| 10113 { | |
| 10114 int oldFlags; | |
| 10115 xmlDocPtr oldDoc; | |
| 10116 xmlNodePtr node; | |
| 10117 int ret, oldErrs; | |
| 10118 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket; | |
| 10119 | |
| 10120 /* | |
| 10121 * Save old values; reset the *main* schema. | |
| 10122 * URGENT TODO: This is not good; move the per-document information | |
| 10123 * to the parser. Get rid of passing the main schema to the | |
| 10124 * parsing functions. | |
| 10125 */ | |
| 10126 oldFlags = schema->flags; | |
| 10127 oldDoc = schema->doc; | |
| 10128 if (schema->flags != 0) | |
| 10129 xmlSchemaClearSchemaDefaults(schema); | |
| 10130 schema->doc = bucket->doc; | |
| 10131 pctxt->schema = schema; | |
| 10132 /* | |
| 10133 * Keep the current target namespace on the parser *not* on the | |
| 10134 * main schema. | |
| 10135 */ | |
| 10136 pctxt->targetNamespace = bucket->targetNamespace; | |
| 10137 WXS_CONSTRUCTOR(pctxt)->bucket = bucket; | |
| 10138 | |
| 10139 if ((bucket->targetNamespace != NULL) && | |
| 10140 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) { | |
| 10141 /* | |
| 10142 * We are parsing the schema for schemas! | |
| 10143 */ | |
| 10144 pctxt->isS4S = 1; | |
| 10145 } | |
| 10146 /* Mark it as parsed, even if parsing fails. */ | |
| 10147 bucket->parsed++; | |
| 10148 /* Compile the schema doc. */ | |
| 10149 node = xmlDocGetRootElement(bucket->doc); | |
| 10150 ret = xmlSchemaParseSchemaElement(pctxt, schema, node); | |
| 10151 if (ret != 0) | |
| 10152 goto exit; | |
| 10153 /* An empty schema; just get out. */ | |
| 10154 if (node->children == NULL) | |
| 10155 goto exit; | |
| 10156 oldErrs = pctxt->nberrors; | |
| 10157 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children); | |
| 10158 if (ret != 0) | |
| 10159 goto exit; | |
| 10160 /* | |
| 10161 * TODO: Not nice, but I'm not 100% sure we will get always an error | |
| 10162 * as a result of the obove functions; so better rely on pctxt->err | |
| 10163 * as well. | |
| 10164 */ | |
| 10165 if ((ret == 0) && (oldErrs != pctxt->nberrors)) { | |
| 10166 ret = pctxt->err; | |
| 10167 goto exit; | |
| 10168 } | |
| 10169 | |
| 10170 exit: | |
| 10171 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket; | |
| 10172 /* Restore schema values. */ | |
| 10173 schema->doc = oldDoc; | |
| 10174 schema->flags = oldFlags; | |
| 10175 return(ret); | |
| 10176 } | |
| 10177 | |
| 10178 static int | |
| 10179 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt, | |
| 10180 xmlSchemaPtr schema, | |
| 10181 xmlSchemaBucketPtr bucket) | |
| 10182 { | |
| 10183 xmlSchemaParserCtxtPtr newpctxt; | |
| 10184 int res = 0; | |
| 10185 | |
| 10186 if (bucket == NULL) | |
| 10187 return(0); | |
| 10188 if (bucket->parsed) { | |
| 10189 PERROR_INT("xmlSchemaParseNewDoc", | |
| 10190 "reparsing a schema doc"); | |
| 10191 return(-1); | |
| 10192 } | |
| 10193 if (bucket->doc == NULL) { | |
| 10194 PERROR_INT("xmlSchemaParseNewDoc", | |
| 10195 "parsing a schema doc, but there's no doc"); | |
| 10196 return(-1); | |
| 10197 } | |
| 10198 if (pctxt->constructor == NULL) { | |
| 10199 PERROR_INT("xmlSchemaParseNewDoc", | |
| 10200 "no constructor"); | |
| 10201 return(-1); | |
| 10202 } | |
| 10203 /* Create and init the temporary parser context. */ | |
| 10204 newpctxt = xmlSchemaNewParserCtxtUseDict( | |
| 10205 (const char *) bucket->schemaLocation, pctxt->dict); | |
| 10206 if (newpctxt == NULL) | |
| 10207 return(-1); | |
| 10208 newpctxt->constructor = pctxt->constructor; | |
| 10209 /* | |
| 10210 * TODO: Can we avoid that the parser knows about the main schema? | |
| 10211 * It would be better if he knows about the current schema bucket | |
| 10212 * only. | |
| 10213 */ | |
| 10214 newpctxt->schema = schema; | |
| 10215 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning, | |
| 10216 pctxt->errCtxt); | |
| 10217 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror, | |
| 10218 pctxt->errCtxt); | |
| 10219 newpctxt->counter = pctxt->counter; | |
| 10220 | |
| 10221 | |
| 10222 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket); | |
| 10223 | |
| 10224 /* Channel back errors and cleanup the temporary parser context. */ | |
| 10225 if (res != 0) | |
| 10226 pctxt->err = res; | |
| 10227 pctxt->nberrors += newpctxt->nberrors; | |
| 10228 pctxt->counter = newpctxt->counter; | |
| 10229 newpctxt->constructor = NULL; | |
| 10230 /* Free the parser context. */ | |
| 10231 xmlSchemaFreeParserCtxt(newpctxt); | |
| 10232 return(res); | |
| 10233 } | |
| 10234 | |
| 10235 static void | |
| 10236 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket, | |
| 10237 xmlSchemaSchemaRelationPtr rel) | |
| 10238 { | |
| 10239 xmlSchemaSchemaRelationPtr cur = bucket->relations; | |
| 10240 | |
| 10241 if (cur == NULL) { | |
| 10242 bucket->relations = rel; | |
| 10243 return; | |
| 10244 } | |
| 10245 while (cur->next != NULL) | |
| 10246 cur = cur->next; | |
| 10247 cur->next = rel; | |
| 10248 } | |
| 10249 | |
| 10250 | |
| 10251 static const xmlChar * | |
| 10252 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location, | |
| 10253 xmlNodePtr ctxtNode) | |
| 10254 { | |
| 10255 /* | |
| 10256 * Build an absolue location URI. | |
| 10257 */ | |
| 10258 if (location != NULL) { | |
| 10259 if (ctxtNode == NULL) | |
| 10260 return(location); | |
| 10261 else { | |
| 10262 xmlChar *base, *URI; | |
| 10263 const xmlChar *ret = NULL; | |
| 10264 | |
| 10265 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode); | |
| 10266 if (base == NULL) { | |
| 10267 URI = xmlBuildURI(location, ctxtNode->doc->URL); | |
| 10268 } else { | |
| 10269 URI = xmlBuildURI(location, base); | |
| 10270 xmlFree(base); | |
| 10271 } | |
| 10272 if (URI != NULL) { | |
| 10273 ret = xmlDictLookup(dict, URI, -1); | |
| 10274 xmlFree(URI); | |
| 10275 return(ret); | |
| 10276 } | |
| 10277 } | |
| 10278 } | |
| 10279 return(NULL); | |
| 10280 } | |
| 10281 | |
| 10282 | |
| 10283 | |
| 10284 /** | |
| 10285 * xmlSchemaAddSchemaDoc: | |
| 10286 * @pctxt: a schema validation context | |
| 10287 * @schema: the schema being built | |
| 10288 * @node: a subtree containing XML Schema informations | |
| 10289 * | |
| 10290 * Parse an included (and to-be-redefined) XML schema document. | |
| 10291 * | |
| 10292 * Returns 0 on success, a positive error code on errors and | |
| 10293 * -1 in case of an internal or API error. | |
| 10294 */ | |
| 10295 | |
| 10296 static int | |
| 10297 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt, | |
| 10298 int type, /* import or include or redefine */ | |
| 10299 const xmlChar *schemaLocation, | |
| 10300 xmlDocPtr schemaDoc, | |
| 10301 const char *schemaBuffer, | |
| 10302 int schemaBufferLen, | |
| 10303 xmlNodePtr invokingNode, | |
| 10304 const xmlChar *sourceTargetNamespace, | |
| 10305 const xmlChar *importNamespace, | |
| 10306 xmlSchemaBucketPtr *bucket) | |
| 10307 { | |
| 10308 const xmlChar *targetNamespace = NULL; | |
| 10309 xmlSchemaSchemaRelationPtr relation = NULL; | |
| 10310 xmlDocPtr doc = NULL; | |
| 10311 int res = 0, err = 0, located = 0, preserveDoc = 0; | |
| 10312 xmlSchemaBucketPtr bkt = NULL; | |
| 10313 | |
| 10314 if (bucket != NULL) | |
| 10315 *bucket = NULL; | |
| 10316 | |
| 10317 switch (type) { | |
| 10318 case XML_SCHEMA_SCHEMA_IMPORT: | |
| 10319 case XML_SCHEMA_SCHEMA_MAIN: | |
| 10320 err = XML_SCHEMAP_SRC_IMPORT; | |
| 10321 break; | |
| 10322 case XML_SCHEMA_SCHEMA_INCLUDE: | |
| 10323 err = XML_SCHEMAP_SRC_INCLUDE; | |
| 10324 break; | |
| 10325 case XML_SCHEMA_SCHEMA_REDEFINE: | |
| 10326 err = XML_SCHEMAP_SRC_REDEFINE; | |
| 10327 break; | |
| 10328 } | |
| 10329 | |
| 10330 | |
| 10331 /* Special handling for the main schema: | |
| 10332 * skip the location and relation logic and just parse the doc. | |
| 10333 * We need just a bucket to be returned in this case. | |
| 10334 */ | |
| 10335 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt))) | |
| 10336 goto doc_load; | |
| 10337 | |
| 10338 /* Note that we expect the location to be an absulute URI. */ | |
| 10339 if (schemaLocation != NULL) { | |
| 10340 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation); | |
| 10341 if ((bkt != NULL) && | |
| 10342 (pctxt->constructor->bucket == bkt)) { | |
| 10343 /* Report self-imports/inclusions/redefinitions. */ | |
| 10344 | |
| 10345 xmlSchemaCustomErr(ACTXT_CAST pctxt, err, | |
| 10346 invokingNode, NULL, | |
| 10347 "The schema must not import/include/redefine itself", | |
| 10348 NULL, NULL); | |
| 10349 goto exit; | |
| 10350 } | |
| 10351 } | |
| 10352 /* | |
| 10353 * Create a relation for the graph of schemas. | |
| 10354 */ | |
| 10355 relation = xmlSchemaSchemaRelationCreate(); | |
| 10356 if (relation == NULL) | |
| 10357 return(-1); | |
| 10358 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket, | |
| 10359 relation); | |
| 10360 relation->type = type; | |
| 10361 | |
| 10362 /* | |
| 10363 * Save the namespace import information. | |
| 10364 */ | |
| 10365 if (WXS_IS_BUCKET_IMPMAIN(type)) { | |
| 10366 relation->importNamespace = importNamespace; | |
| 10367 if (schemaLocation == NULL) { | |
| 10368 /* | |
| 10369 * No location; this is just an import of the namespace. | |
| 10370 * Note that we don't assign a bucket to the relation | |
| 10371 * in this case. | |
| 10372 */ | |
| 10373 goto exit; | |
| 10374 } | |
| 10375 targetNamespace = importNamespace; | |
| 10376 } | |
| 10377 | |
| 10378 /* Did we already fetch the doc? */ | |
| 10379 if (bkt != NULL) { | |
| 10380 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) { | |
| 10381 /* | |
| 10382 * We included/redefined and then try to import a schema, | |
| 10383 * but the new location provided for import was different. | |
| 10384 */ | |
| 10385 if (schemaLocation == NULL) | |
| 10386 schemaLocation = BAD_CAST "in_memory_buffer"; | |
| 10387 if (!xmlStrEqual(schemaLocation, | |
| 10388 bkt->schemaLocation)) { | |
| 10389 xmlSchemaCustomErr(ACTXT_CAST pctxt, err, | |
| 10390 invokingNode, NULL, | |
| 10391 "The schema document '%s' cannot be imported, since " | |
| 10392 "it was already included or redefined", | |
| 10393 schemaLocation, NULL); | |
| 10394 goto exit; | |
| 10395 } | |
| 10396 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) { | |
| 10397 /* | |
| 10398 * We imported and then try to include/redefine a schema, | |
| 10399 * but the new location provided for the include/redefine | |
| 10400 * was different. | |
| 10401 */ | |
| 10402 if (schemaLocation == NULL) | |
| 10403 schemaLocation = BAD_CAST "in_memory_buffer"; | |
| 10404 if (!xmlStrEqual(schemaLocation, | |
| 10405 bkt->schemaLocation)) { | |
| 10406 xmlSchemaCustomErr(ACTXT_CAST pctxt, err, | |
| 10407 invokingNode, NULL, | |
| 10408 "The schema document '%s' cannot be included or " | |
| 10409 "redefined, since it was already imported", | |
| 10410 schemaLocation, NULL); | |
| 10411 goto exit; | |
| 10412 } | |
| 10413 } | |
| 10414 } | |
| 10415 | |
| 10416 if (WXS_IS_BUCKET_IMPMAIN(type)) { | |
| 10417 /* | |
| 10418 * Given that the schemaLocation [attribute] is only a hint, it is open | |
| 10419 * to applications to ignore all but the first <import> for a given | |
| 10420 * namespace, regardless of the `actual value` of schemaLocation, but | |
| 10421 * such a strategy risks missing useful information when new | |
| 10422 * schemaLocations are offered. | |
| 10423 * | |
| 10424 * We will use the first <import> that comes with a location. | |
| 10425 * Further <import>s *with* a location, will result in an error. | |
| 10426 * TODO: Better would be to just report a warning here, but | |
| 10427 * we'll try it this way until someone complains. | |
| 10428 * | |
| 10429 * Schema Document Location Strategy: | |
| 10430 * 3 Based on the namespace name, identify an existing schema document, | |
| 10431 * either as a resource which is an XML document or a <schema> element | |
| 10432 * information item, in some local schema repository; | |
| 10433 * 5 Attempt to resolve the namespace name to locate such a resource. | |
| 10434 * | |
| 10435 * NOTE: (3) and (5) are not supported. | |
| 10436 */ | |
| 10437 if (bkt != NULL) { | |
| 10438 relation->bucket = bkt; | |
| 10439 goto exit; | |
| 10440 } | |
| 10441 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt, | |
| 10442 importNamespace, 1); | |
| 10443 | |
| 10444 if (bkt != NULL) { | |
| 10445 relation->bucket = bkt; | |
| 10446 if (bkt->schemaLocation == NULL) { | |
| 10447 /* First given location of the schema; load the doc. */ | |
| 10448 bkt->schemaLocation = schemaLocation; | |
| 10449 } else { | |
| 10450 if (!xmlStrEqual(schemaLocation, | |
| 10451 bkt->schemaLocation)) { | |
| 10452 /* | |
| 10453 * Additional location given; just skip it. | |
| 10454 * URGENT TODO: We should report a warning here. | |
| 10455 * res = XML_SCHEMAP_SRC_IMPORT; | |
| 10456 */ | |
| 10457 if (schemaLocation == NULL) | |
| 10458 schemaLocation = BAD_CAST "in_memory_buffer"; | |
| 10459 | |
| 10460 xmlSchemaCustomWarning(ACTXT_CAST pctxt, | |
| 10461 XML_SCHEMAP_WARN_SKIP_SCHEMA, | |
| 10462 invokingNode, NULL, | |
| 10463 "Skipping import of schema located at '%s' for the " | |
| 10464 "namespace '%s', since this namespace was already " | |
| 10465 "imported with the schema located at '%s'", | |
| 10466 schemaLocation, importNamespace, bkt->schemaLocation); | |
| 10467 } | |
| 10468 goto exit; | |
| 10469 } | |
| 10470 } | |
| 10471 /* | |
| 10472 * No bucket + first location: load the doc and create a | |
| 10473 * bucket. | |
| 10474 */ | |
| 10475 } else { | |
| 10476 /* <include> and <redefine> */ | |
| 10477 if (bkt != NULL) { | |
| 10478 | |
| 10479 if ((bkt->origTargetNamespace == NULL) && | |
| 10480 (bkt->targetNamespace != sourceTargetNamespace)) { | |
| 10481 xmlSchemaBucketPtr chamel; | |
| 10482 | |
| 10483 /* | |
| 10484 * Chameleon include/redefine: skip loading only if it was | |
| 10485 * aleady build for the targetNamespace of the including | |
| 10486 * schema. | |
| 10487 */ | |
| 10488 /* | |
| 10489 * URGENT TODO: If the schema is a chameleon-include then copy | |
| 10490 * the components into the including schema and modify the | |
| 10491 * targetNamespace of those components, do nothing otherwise. | |
| 10492 * NOTE: This is currently worked-around by compiling the | |
| 10493 * chameleon for every destinct including targetNamespace; thus | |
| 10494 * not performant at the moment. | |
| 10495 * TODO: Check when the namespace in wildcards for chameleons | |
| 10496 * needs to be converted: before we built wildcard intersections | |
| 10497 * or after. | |
| 10498 * Answer: after! | |
| 10499 */ | |
| 10500 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt, | |
| 10501 schemaLocation, sourceTargetNamespace); | |
| 10502 if (chamel != NULL) { | |
| 10503 /* A fitting chameleon was already parsed; NOP. */ | |
| 10504 relation->bucket = chamel; | |
| 10505 goto exit; | |
| 10506 } | |
| 10507 /* | |
| 10508 * We need to parse the chameleon again for a different | |
| 10509 * targetNamespace. | |
| 10510 * CHAMELEON TODO: Optimize this by only parsing the | |
| 10511 * chameleon once, and then copying the components to | |
| 10512 * the new targetNamespace. | |
| 10513 */ | |
| 10514 bkt = NULL; | |
| 10515 } else { | |
| 10516 relation->bucket = bkt; | |
| 10517 goto exit; | |
| 10518 } | |
| 10519 } | |
| 10520 } | |
| 10521 if ((bkt != NULL) && (bkt->doc != NULL)) { | |
| 10522 PERROR_INT("xmlSchemaAddSchemaDoc", | |
| 10523 "trying to load a schema doc, but a doc is already " | |
| 10524 "assigned to the schema bucket"); | |
| 10525 goto exit_failure; | |
| 10526 } | |
| 10527 | |
| 10528 doc_load: | |
| 10529 /* | |
| 10530 * Load the document. | |
| 10531 */ | |
| 10532 if (schemaDoc != NULL) { | |
| 10533 doc = schemaDoc; | |
| 10534 /* Don' free this one, since it was provided by the caller. */ | |
| 10535 preserveDoc = 1; | |
| 10536 /* TODO: Does the context or the doc hold the location? */ | |
| 10537 if (schemaDoc->URL != NULL) | |
| 10538 schemaLocation = xmlDictLookup(pctxt->dict, | |
| 10539 schemaDoc->URL, -1); | |
| 10540 else | |
| 10541 schemaLocation = BAD_CAST "in_memory_buffer"; | |
| 10542 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) { | |
| 10543 xmlParserCtxtPtr parserCtxt; | |
| 10544 | |
| 10545 parserCtxt = xmlNewParserCtxt(); | |
| 10546 if (parserCtxt == NULL) { | |
| 10547 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, " | |
| 10548 "allocating a parser context", NULL); | |
| 10549 goto exit_failure; | |
| 10550 } | |
| 10551 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) { | |
| 10552 /* | |
| 10553 * TODO: Do we have to burden the schema parser dict with all | |
| 10554 * the content of the schema doc? | |
| 10555 */ | |
| 10556 xmlDictFree(parserCtxt->dict); | |
| 10557 parserCtxt->dict = pctxt->dict; | |
| 10558 xmlDictReference(parserCtxt->dict); | |
| 10559 } | |
| 10560 if (schemaLocation != NULL) { | |
| 10561 /* Parse from file. */ | |
| 10562 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation, | |
| 10563 NULL, SCHEMAS_PARSE_OPTIONS); | |
| 10564 } else if (schemaBuffer != NULL) { | |
| 10565 /* Parse from memory buffer. */ | |
| 10566 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen, | |
| 10567 NULL, NULL, SCHEMAS_PARSE_OPTIONS); | |
| 10568 schemaLocation = BAD_CAST "in_memory_buffer"; | |
| 10569 if (doc != NULL) | |
| 10570 doc->URL = xmlStrdup(schemaLocation); | |
| 10571 } | |
| 10572 /* | |
| 10573 * For <import>: | |
| 10574 * 2.1 The referent is (a fragment of) a resource which is an | |
| 10575 * XML document (see clause 1.1), which in turn corresponds to | |
| 10576 * a <schema> element information item in a well-formed information | |
| 10577 * set, which in turn corresponds to a valid schema. | |
| 10578 * TODO: (2.1) fragments of XML documents are not supported. | |
| 10579 * | |
| 10580 * 2.2 The referent is a <schema> element information item in | |
| 10581 * a well-formed information set, which in turn corresponds | |
| 10582 * to a valid schema. | |
| 10583 * TODO: (2.2) is not supported. | |
| 10584 */ | |
| 10585 if (doc == NULL) { | |
| 10586 xmlErrorPtr lerr; | |
| 10587 lerr = xmlGetLastError(); | |
| 10588 /* | |
| 10589 * Check if this a parser error, or if the document could | |
| 10590 * just not be located. | |
| 10591 * TODO: Try to find specific error codes to react only on | |
| 10592 * localisation failures. | |
| 10593 */ | |
| 10594 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) { | |
| 10595 /* | |
| 10596 * We assume a parser error here. | |
| 10597 */ | |
| 10598 located = 1; | |
| 10599 /* TODO: Error code ?? */ | |
| 10600 res = XML_SCHEMAP_SRC_IMPORT_2_1; | |
| 10601 xmlSchemaCustomErr(ACTXT_CAST pctxt, res, | |
| 10602 invokingNode, NULL, | |
| 10603 "Failed to parse the XML resource '%s'", | |
| 10604 schemaLocation, NULL); | |
| 10605 } | |
| 10606 } | |
| 10607 xmlFreeParserCtxt(parserCtxt); | |
| 10608 if ((doc == NULL) && located) | |
| 10609 goto exit_error; | |
| 10610 } else { | |
| 10611 xmlSchemaPErr(pctxt, NULL, | |
| 10612 XML_SCHEMAP_NOTHING_TO_PARSE, | |
| 10613 "No information for parsing was provided with the " | |
| 10614 "given schema parser context.\n", | |
| 10615 NULL, NULL); | |
| 10616 goto exit_failure; | |
| 10617 } | |
| 10618 /* | |
| 10619 * Preprocess the document. | |
| 10620 */ | |
| 10621 if (doc != NULL) { | |
| 10622 xmlNodePtr docElem = NULL; | |
| 10623 | |
| 10624 located = 1; | |
| 10625 docElem = xmlDocGetRootElement(doc); | |
| 10626 if (docElem == NULL) { | |
| 10627 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT, | |
| 10628 invokingNode, NULL, | |
| 10629 "The document '%s' has no document element", | |
| 10630 schemaLocation, NULL); | |
| 10631 goto exit_error; | |
| 10632 } | |
| 10633 /* | |
| 10634 * Remove all the blank text nodes. | |
| 10635 */ | |
| 10636 xmlSchemaCleanupDoc(pctxt, docElem); | |
| 10637 /* | |
| 10638 * Check the schema's top level element. | |
| 10639 */ | |
| 10640 if (!IS_SCHEMA(docElem, "schema")) { | |
| 10641 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA, | |
| 10642 invokingNode, NULL, | |
| 10643 "The XML document '%s' is not a schema document", | |
| 10644 schemaLocation, NULL); | |
| 10645 goto exit_error; | |
| 10646 } | |
| 10647 /* | |
| 10648 * Note that we don't apply a type check for the | |
| 10649 * targetNamespace value here. | |
| 10650 */ | |
| 10651 targetNamespace = xmlSchemaGetProp(pctxt, docElem, | |
| 10652 "targetNamespace"); | |
| 10653 } | |
| 10654 | |
| 10655 /* after_doc_loading: */ | |
| 10656 if ((bkt == NULL) && located) { | |
| 10657 /* Only create a bucket if the schema was located. */ | |
| 10658 bkt = xmlSchemaBucketCreate(pctxt, type, | |
| 10659 targetNamespace); | |
| 10660 if (bkt == NULL) | |
| 10661 goto exit_failure; | |
| 10662 } | |
| 10663 if (bkt != NULL) { | |
| 10664 bkt->schemaLocation = schemaLocation; | |
| 10665 bkt->located = located; | |
| 10666 if (doc != NULL) { | |
| 10667 bkt->doc = doc; | |
| 10668 bkt->targetNamespace = targetNamespace; | |
| 10669 bkt->origTargetNamespace = targetNamespace; | |
| 10670 if (preserveDoc) | |
| 10671 bkt->preserveDoc = 1; | |
| 10672 } | |
| 10673 if (WXS_IS_BUCKET_IMPMAIN(type)) | |
| 10674 bkt->imported++; | |
| 10675 /* | |
| 10676 * Add it to the graph of schemas. | |
| 10677 */ | |
| 10678 if (relation != NULL) | |
| 10679 relation->bucket = bkt; | |
| 10680 } | |
| 10681 | |
| 10682 exit: | |
| 10683 /* | |
| 10684 * Return the bucket explicitely; this is needed for the | |
| 10685 * main schema. | |
| 10686 */ | |
| 10687 if (bucket != NULL) | |
| 10688 *bucket = bkt; | |
| 10689 return (0); | |
| 10690 | |
| 10691 exit_error: | |
| 10692 if ((doc != NULL) && (! preserveDoc)) { | |
| 10693 xmlFreeDoc(doc); | |
| 10694 if (bkt != NULL) | |
| 10695 bkt->doc = NULL; | |
| 10696 } | |
| 10697 return(pctxt->err); | |
| 10698 | |
| 10699 exit_failure: | |
| 10700 if ((doc != NULL) && (! preserveDoc)) { | |
| 10701 xmlFreeDoc(doc); | |
| 10702 if (bkt != NULL) | |
| 10703 bkt->doc = NULL; | |
| 10704 } | |
| 10705 return (-1); | |
| 10706 } | |
| 10707 | |
| 10708 /** | |
| 10709 * xmlSchemaParseImport: | |
| 10710 * @ctxt: a schema validation context | |
| 10711 * @schema: the schema being built | |
| 10712 * @node: a subtree containing XML Schema informations | |
| 10713 * | |
| 10714 * parse a XML schema Import definition | |
| 10715 * *WARNING* this interface is highly subject to change | |
| 10716 * | |
| 10717 * Returns 0 in case of success, a positive error code if | |
| 10718 * not valid and -1 in case of an internal error. | |
| 10719 */ | |
| 10720 static int | |
| 10721 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, | |
| 10722 xmlNodePtr node) | |
| 10723 { | |
| 10724 xmlNodePtr child; | |
| 10725 const xmlChar *namespaceName = NULL, *schemaLocation = NULL; | |
| 10726 const xmlChar *thisTargetNamespace; | |
| 10727 xmlAttrPtr attr; | |
| 10728 int ret = 0; | |
| 10729 xmlSchemaBucketPtr bucket = NULL; | |
| 10730 | |
| 10731 if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 10732 return (-1); | |
| 10733 | |
| 10734 /* | |
| 10735 * Check for illegal attributes. | |
| 10736 */ | |
| 10737 attr = node->properties; | |
| 10738 while (attr != NULL) { | |
| 10739 if (attr->ns == NULL) { | |
| 10740 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 10741 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) && | |
| 10742 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) { | |
| 10743 xmlSchemaPIllegalAttrErr(pctxt, | |
| 10744 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 10745 } | |
| 10746 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 10747 xmlSchemaPIllegalAttrErr(pctxt, | |
| 10748 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 10749 } | |
| 10750 attr = attr->next; | |
| 10751 } | |
| 10752 /* | |
| 10753 * Extract and validate attributes. | |
| 10754 */ | |
| 10755 if (xmlSchemaPValAttr(pctxt, NULL, node, | |
| 10756 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), | |
| 10757 &namespaceName) != 0) { | |
| 10758 xmlSchemaPSimpleTypeErr(pctxt, | |
| 10759 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 10760 NULL, node, | |
| 10761 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), | |
| 10762 NULL, namespaceName, NULL, NULL, NULL); | |
| 10763 return (pctxt->err); | |
| 10764 } | |
| 10765 | |
| 10766 if (xmlSchemaPValAttr(pctxt, NULL, node, | |
| 10767 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), | |
| 10768 &schemaLocation) != 0) { | |
| 10769 xmlSchemaPSimpleTypeErr(pctxt, | |
| 10770 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 10771 NULL, node, | |
| 10772 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), | |
| 10773 NULL, schemaLocation, NULL, NULL, NULL); | |
| 10774 return (pctxt->err); | |
| 10775 } | |
| 10776 /* | |
| 10777 * And now for the children... | |
| 10778 */ | |
| 10779 child = node->children; | |
| 10780 if (IS_SCHEMA(child, "annotation")) { | |
| 10781 /* | |
| 10782 * the annotation here is simply discarded ... | |
| 10783 * TODO: really? | |
| 10784 */ | |
| 10785 child = child->next; | |
| 10786 } | |
| 10787 if (child != NULL) { | |
| 10788 xmlSchemaPContentErr(pctxt, | |
| 10789 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 10790 NULL, node, child, NULL, | |
| 10791 "(annotation?)"); | |
| 10792 } | |
| 10793 /* | |
| 10794 * Apply additional constraints. | |
| 10795 * | |
| 10796 * Note that it is important to use the original @targetNamespace | |
| 10797 * (or none at all), to rule out imports of schemas _with_ a | |
| 10798 * @targetNamespace if the importing schema is a chameleon schema | |
| 10799 * (with no @targetNamespace). | |
| 10800 */ | |
| 10801 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace; | |
| 10802 if (namespaceName != NULL) { | |
| 10803 /* | |
| 10804 * 1.1 If the namespace [attribute] is present, then its `actual value` | |
| 10805 * must not match the `actual value` of the enclosing <schema>'s | |
| 10806 * targetNamespace [attribute]. | |
| 10807 */ | |
| 10808 if (xmlStrEqual(thisTargetNamespace, namespaceName)) { | |
| 10809 xmlSchemaPCustomErr(pctxt, | |
| 10810 XML_SCHEMAP_SRC_IMPORT_1_1, | |
| 10811 NULL, node, | |
| 10812 "The value of the attribute 'namespace' must not match " | |
| 10813 "the target namespace '%s' of the importing schema", | |
| 10814 thisTargetNamespace); | |
| 10815 return (pctxt->err); | |
| 10816 } | |
| 10817 } else { | |
| 10818 /* | |
| 10819 * 1.2 If the namespace [attribute] is not present, then the enclosing | |
| 10820 * <schema> must have a targetNamespace [attribute]. | |
| 10821 */ | |
| 10822 if (thisTargetNamespace == NULL) { | |
| 10823 xmlSchemaPCustomErr(pctxt, | |
| 10824 XML_SCHEMAP_SRC_IMPORT_1_2, | |
| 10825 NULL, node, | |
| 10826 "The attribute 'namespace' must be existent if " | |
| 10827 "the importing schema has no target namespace", | |
| 10828 NULL); | |
| 10829 return (pctxt->err); | |
| 10830 } | |
| 10831 } | |
| 10832 /* | |
| 10833 * Locate and acquire the schema document. | |
| 10834 */ | |
| 10835 if (schemaLocation != NULL) | |
| 10836 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict, | |
| 10837 schemaLocation, node); | |
| 10838 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT, | |
| 10839 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace, | |
| 10840 namespaceName, &bucket); | |
| 10841 | |
| 10842 if (ret != 0) | |
| 10843 return(ret); | |
| 10844 | |
| 10845 /* | |
| 10846 * For <import>: "It is *not* an error for the application | |
| 10847 * schema reference strategy to fail." | |
| 10848 * So just don't parse if no schema document was found. | |
| 10849 * Note that we will get no bucket if the schema could not be | |
| 10850 * located or if there was no schemaLocation. | |
| 10851 */ | |
| 10852 if ((bucket == NULL) && (schemaLocation != NULL)) { | |
| 10853 xmlSchemaCustomWarning(ACTXT_CAST pctxt, | |
| 10854 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA, | |
| 10855 node, NULL, | |
| 10856 "Failed to locate a schema at location '%s'. " | |
| 10857 "Skipping the import", schemaLocation, NULL, NULL); | |
| 10858 } | |
| 10859 | |
| 10860 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) { | |
| 10861 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket); | |
| 10862 } | |
| 10863 | |
| 10864 return (ret); | |
| 10865 } | |
| 10866 | |
| 10867 static int | |
| 10868 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt, | |
| 10869 xmlSchemaPtr schema, | |
| 10870 xmlNodePtr node, | |
| 10871 xmlChar **schemaLocation, | |
| 10872 int type) | |
| 10873 { | |
| 10874 xmlAttrPtr attr; | |
| 10875 | |
| 10876 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) || | |
| 10877 (schemaLocation == NULL)) | |
| 10878 return (-1); | |
| 10879 | |
| 10880 *schemaLocation = NULL; | |
| 10881 /* | |
| 10882 * Check for illegal attributes. | |
| 10883 * Applies for both <include> and <redefine>. | |
| 10884 */ | |
| 10885 attr = node->properties; | |
| 10886 while (attr != NULL) { | |
| 10887 if (attr->ns == NULL) { | |
| 10888 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 10889 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) { | |
| 10890 xmlSchemaPIllegalAttrErr(pctxt, | |
| 10891 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 10892 } | |
| 10893 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 10894 xmlSchemaPIllegalAttrErr(pctxt, | |
| 10895 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 10896 } | |
| 10897 attr = attr->next; | |
| 10898 } | |
| 10899 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); | |
| 10900 /* | |
| 10901 * Preliminary step, extract the URI-Reference and make an URI | |
| 10902 * from the base. | |
| 10903 */ | |
| 10904 /* | |
| 10905 * Attribute "schemaLocation" is mandatory. | |
| 10906 */ | |
| 10907 attr = xmlSchemaGetPropNode(node, "schemaLocation"); | |
| 10908 if (attr != NULL) { | |
| 10909 xmlChar *base = NULL; | |
| 10910 xmlChar *uri = NULL; | |
| 10911 | |
| 10912 if (xmlSchemaPValAttrNode(pctxt, NULL, attr, | |
| 10913 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), | |
| 10914 (const xmlChar **) schemaLocation) != 0) | |
| 10915 goto exit_error; | |
| 10916 base = xmlNodeGetBase(node->doc, node); | |
| 10917 if (base == NULL) { | |
| 10918 uri = xmlBuildURI(*schemaLocation, node->doc->URL); | |
| 10919 } else { | |
| 10920 uri = xmlBuildURI(*schemaLocation, base); | |
| 10921 xmlFree(base); | |
| 10922 } | |
| 10923 if (uri == NULL) { | |
| 10924 PERROR_INT("xmlSchemaParseIncludeOrRedefine", | |
| 10925 "could not build an URI from the schemaLocation") | |
| 10926 goto exit_failure; | |
| 10927 } | |
| 10928 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1); | |
| 10929 xmlFree(uri); | |
| 10930 } else { | |
| 10931 xmlSchemaPMissingAttrErr(pctxt, | |
| 10932 XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 10933 NULL, node, "schemaLocation", NULL); | |
| 10934 goto exit_error; | |
| 10935 } | |
| 10936 /* | |
| 10937 * Report self-inclusion and self-redefinition. | |
| 10938 */ | |
| 10939 if (xmlStrEqual(*schemaLocation, pctxt->URL)) { | |
| 10940 if (type == XML_SCHEMA_SCHEMA_REDEFINE) { | |
| 10941 xmlSchemaPCustomErr(pctxt, | |
| 10942 XML_SCHEMAP_SRC_REDEFINE, | |
| 10943 NULL, node, | |
| 10944 "The schema document '%s' cannot redefine itself.", | |
| 10945 *schemaLocation); | |
| 10946 } else { | |
| 10947 xmlSchemaPCustomErr(pctxt, | |
| 10948 XML_SCHEMAP_SRC_INCLUDE, | |
| 10949 NULL, node, | |
| 10950 "The schema document '%s' cannot include itself.", | |
| 10951 *schemaLocation); | |
| 10952 } | |
| 10953 goto exit_error; | |
| 10954 } | |
| 10955 | |
| 10956 return(0); | |
| 10957 exit_error: | |
| 10958 return(pctxt->err); | |
| 10959 exit_failure: | |
| 10960 return(-1); | |
| 10961 } | |
| 10962 | |
| 10963 static int | |
| 10964 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt, | |
| 10965 xmlSchemaPtr schema, | |
| 10966 xmlNodePtr node, | |
| 10967 int type) | |
| 10968 { | |
| 10969 xmlNodePtr child = NULL; | |
| 10970 const xmlChar *schemaLocation = NULL; | |
| 10971 int res = 0; /* hasRedefinitions = 0 */ | |
| 10972 int isChameleon = 0, wasChameleon = 0; | |
| 10973 xmlSchemaBucketPtr bucket = NULL; | |
| 10974 | |
| 10975 if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 10976 return (-1); | |
| 10977 | |
| 10978 /* | |
| 10979 * Parse attributes. Note that the returned schemaLocation will | |
| 10980 * be already converted to an absolute URI. | |
| 10981 */ | |
| 10982 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema, | |
| 10983 node, (xmlChar **) (&schemaLocation), type); | |
| 10984 if (res != 0) | |
| 10985 return(res); | |
| 10986 /* | |
| 10987 * Load and add the schema document. | |
| 10988 */ | |
| 10989 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL, | |
| 10990 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket); | |
| 10991 if (res != 0) | |
| 10992 return(res); | |
| 10993 /* | |
| 10994 * If we get no schema bucket back, then this means that the schema | |
| 10995 * document could not be located or was broken XML or was not | |
| 10996 * a schema document. | |
| 10997 */ | |
| 10998 if ((bucket == NULL) || (bucket->doc == NULL)) { | |
| 10999 if (type == XML_SCHEMA_SCHEMA_INCLUDE) { | |
| 11000 /* | |
| 11001 * WARNING for <include>: | |
| 11002 * We will raise an error if the schema cannot be located | |
| 11003 * for inclusions, since the that was the feedback from the | |
| 11004 * schema people. I.e. the following spec piece will *not* be | |
| 11005 * satisfied: | |
| 11006 * SPEC src-include: "It is not an error for the `actual value` of th
e | |
| 11007 * schemaLocation [attribute] to fail to resolve it all, in which | |
| 11008 * case no corresponding inclusion is performed. | |
| 11009 * So do we need a warning report here?" | |
| 11010 */ | |
| 11011 res = XML_SCHEMAP_SRC_INCLUDE; | |
| 11012 xmlSchemaCustomErr(ACTXT_CAST pctxt, res, | |
| 11013 node, NULL, | |
| 11014 "Failed to load the document '%s' for inclusion", | |
| 11015 schemaLocation, NULL); | |
| 11016 } else { | |
| 11017 /* | |
| 11018 * NOTE: This was changed to raise an error even if no redefinitions | |
| 11019 * are specified. | |
| 11020 * | |
| 11021 * SPEC src-redefine (1) | |
| 11022 * "If there are any element information items among the [children] | |
| 11023 * other than <annotation> then the `actual value` of the | |
| 11024 * schemaLocation [attribute] must successfully resolve." | |
| 11025 * TODO: Ask the WG if a the location has always to resolve | |
| 11026 * here as well! | |
| 11027 */ | |
| 11028 res = XML_SCHEMAP_SRC_REDEFINE; | |
| 11029 xmlSchemaCustomErr(ACTXT_CAST pctxt, res, | |
| 11030 node, NULL, | |
| 11031 "Failed to load the document '%s' for redefinition", | |
| 11032 schemaLocation, NULL); | |
| 11033 } | |
| 11034 } else { | |
| 11035 /* | |
| 11036 * Check targetNamespace sanity before parsing the new schema. | |
| 11037 * TODO: Note that we won't check further content if the | |
| 11038 * targetNamespace was bad. | |
| 11039 */ | |
| 11040 if (bucket->origTargetNamespace != NULL) { | |
| 11041 /* | |
| 11042 * SPEC src-include (2.1) | |
| 11043 * "SII has a targetNamespace [attribute], and its `actual | |
| 11044 * value` is identical to the `actual value` of the targetNamespace | |
| 11045 * [attribute] of SII' (which must have such an [attribute])." | |
| 11046 */ | |
| 11047 if (pctxt->targetNamespace == NULL) { | |
| 11048 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 11049 XML_SCHEMAP_SRC_INCLUDE, | |
| 11050 node, NULL, | |
| 11051 "The target namespace of the included/redefined schema " | |
| 11052 "'%s' has to be absent, since the including/redefining " | |
| 11053 "schema has no target namespace", | |
| 11054 schemaLocation, NULL); | |
| 11055 goto exit_error; | |
| 11056 } else if (!xmlStrEqual(bucket->origTargetNamespace, | |
| 11057 pctxt->targetNamespace)) { | |
| 11058 /* TODO: Change error function. */ | |
| 11059 xmlSchemaPCustomErrExt(pctxt, | |
| 11060 XML_SCHEMAP_SRC_INCLUDE, | |
| 11061 NULL, node, | |
| 11062 "The target namespace '%s' of the included/redefined " | |
| 11063 "schema '%s' differs from '%s' of the " | |
| 11064 "including/redefining schema", | |
| 11065 bucket->origTargetNamespace, schemaLocation, | |
| 11066 pctxt->targetNamespace); | |
| 11067 goto exit_error; | |
| 11068 } | |
| 11069 } else if (pctxt->targetNamespace != NULL) { | |
| 11070 /* | |
| 11071 * Chameleons: the original target namespace will | |
| 11072 * differ from the resulting namespace. | |
| 11073 */ | |
| 11074 isChameleon = 1; | |
| 11075 if (bucket->parsed && | |
| 11076 bucket->origTargetNamespace != NULL) { | |
| 11077 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 11078 XML_SCHEMAP_SRC_INCLUDE, | |
| 11079 node, NULL, | |
| 11080 "The target namespace of the included/redefined schema " | |
| 11081 "'%s' has to be absent or the same as the " | |
| 11082 "including/redefining schema's target namespace", | |
| 11083 schemaLocation, NULL); | |
| 11084 goto exit_error; | |
| 11085 } | |
| 11086 bucket->targetNamespace = pctxt->targetNamespace; | |
| 11087 } | |
| 11088 } | |
| 11089 /* | |
| 11090 * Parse the schema. | |
| 11091 */ | |
| 11092 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) { | |
| 11093 if (isChameleon) { | |
| 11094 /* TODO: Get rid of this flag on the schema itself. */ | |
| 11095 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) { | |
| 11096 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS; | |
| 11097 } else | |
| 11098 wasChameleon = 1; | |
| 11099 } | |
| 11100 xmlSchemaParseNewDoc(pctxt, schema, bucket); | |
| 11101 /* Restore chameleon flag. */ | |
| 11102 if (isChameleon && (!wasChameleon)) | |
| 11103 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS; | |
| 11104 } | |
| 11105 /* | |
| 11106 * And now for the children... | |
| 11107 */ | |
| 11108 child = node->children; | |
| 11109 if (type == XML_SCHEMA_SCHEMA_REDEFINE) { | |
| 11110 /* | |
| 11111 * Parse (simpleType | complexType | group | attributeGroup))* | |
| 11112 */ | |
| 11113 pctxt->redefined = bucket; | |
| 11114 /* | |
| 11115 * How to proceed if the redefined schema was not located? | |
| 11116 */ | |
| 11117 pctxt->isRedefine = 1; | |
| 11118 while (IS_SCHEMA(child, "annotation") || | |
| 11119 IS_SCHEMA(child, "simpleType") || | |
| 11120 IS_SCHEMA(child, "complexType") || | |
| 11121 IS_SCHEMA(child, "group") || | |
| 11122 IS_SCHEMA(child, "attributeGroup")) { | |
| 11123 if (IS_SCHEMA(child, "annotation")) { | |
| 11124 /* | |
| 11125 * TODO: discard or not? | |
| 11126 */ | |
| 11127 } else if (IS_SCHEMA(child, "simpleType")) { | |
| 11128 xmlSchemaParseSimpleType(pctxt, schema, child, 1); | |
| 11129 } else if (IS_SCHEMA(child, "complexType")) { | |
| 11130 xmlSchemaParseComplexType(pctxt, schema, child, 1); | |
| 11131 /* hasRedefinitions = 1; */ | |
| 11132 } else if (IS_SCHEMA(child, "group")) { | |
| 11133 /* hasRedefinitions = 1; */ | |
| 11134 xmlSchemaParseModelGroupDefinition(pctxt, | |
| 11135 schema, child); | |
| 11136 } else if (IS_SCHEMA(child, "attributeGroup")) { | |
| 11137 /* hasRedefinitions = 1; */ | |
| 11138 xmlSchemaParseAttributeGroupDefinition(pctxt, schema, | |
| 11139 child); | |
| 11140 } | |
| 11141 child = child->next; | |
| 11142 } | |
| 11143 pctxt->redefined = NULL; | |
| 11144 pctxt->isRedefine = 0; | |
| 11145 } else { | |
| 11146 if (IS_SCHEMA(child, "annotation")) { | |
| 11147 /* | |
| 11148 * TODO: discard or not? | |
| 11149 */ | |
| 11150 child = child->next; | |
| 11151 } | |
| 11152 } | |
| 11153 if (child != NULL) { | |
| 11154 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED; | |
| 11155 if (type == XML_SCHEMA_SCHEMA_REDEFINE) { | |
| 11156 xmlSchemaPContentErr(pctxt, res, | |
| 11157 NULL, node, child, NULL, | |
| 11158 "(annotation | (simpleType | complexType | group | attributeGrou
p))*"); | |
| 11159 } else { | |
| 11160 xmlSchemaPContentErr(pctxt, res, | |
| 11161 NULL, node, child, NULL, | |
| 11162 "(annotation?)"); | |
| 11163 } | |
| 11164 } | |
| 11165 return(res); | |
| 11166 | |
| 11167 exit_error: | |
| 11168 return(pctxt->err); | |
| 11169 } | |
| 11170 | |
| 11171 static int | |
| 11172 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, | |
| 11173 xmlNodePtr node) | |
| 11174 { | |
| 11175 int res; | |
| 11176 #ifndef ENABLE_REDEFINE | |
| 11177 TODO | |
| 11178 return(0); | |
| 11179 #endif | |
| 11180 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, | |
| 11181 XML_SCHEMA_SCHEMA_REDEFINE); | |
| 11182 if (res != 0) | |
| 11183 return(res); | |
| 11184 return(0); | |
| 11185 } | |
| 11186 | |
| 11187 static int | |
| 11188 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, | |
| 11189 xmlNodePtr node) | |
| 11190 { | |
| 11191 int res; | |
| 11192 | |
| 11193 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, | |
| 11194 XML_SCHEMA_SCHEMA_INCLUDE); | |
| 11195 if (res != 0) | |
| 11196 return(res); | |
| 11197 return(0); | |
| 11198 } | |
| 11199 | |
| 11200 /** | |
| 11201 * xmlSchemaParseModelGroup: | |
| 11202 * @ctxt: a schema validation context | |
| 11203 * @schema: the schema being built | |
| 11204 * @node: a subtree containing XML Schema informations | |
| 11205 * @type: the "compositor" type | |
| 11206 * @particleNeeded: if a a model group with a particle | |
| 11207 * | |
| 11208 * parse a XML schema Sequence definition. | |
| 11209 * Applies parts of: | |
| 11210 * Schema Representation Constraint: | |
| 11211 * Redefinition Constraints and Semantics (src-redefine) | |
| 11212 * (6.1), (6.1.1), (6.1.2) | |
| 11213 * | |
| 11214 * Schema Component Constraint: | |
| 11215 * All Group Limited (cos-all-limited) (2) | |
| 11216 * TODO: Actually this should go to component-level checks, | |
| 11217 * but is done here due to performance. Move it to an other layer | |
| 11218 * is schema construction via an API is implemented. | |
| 11219 * | |
| 11220 * *WARNING* this interface is highly subject to change | |
| 11221 * | |
| 11222 * Returns -1 in case of error, 0 if the declaration is improper and | |
| 11223 * 1 in case of success. | |
| 11224 */ | |
| 11225 static xmlSchemaTreeItemPtr | |
| 11226 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 11227 xmlNodePtr node, xmlSchemaTypeType type, | |
| 11228 int withParticle) | |
| 11229 { | |
| 11230 xmlSchemaModelGroupPtr item; | |
| 11231 xmlSchemaParticlePtr particle = NULL; | |
| 11232 xmlNodePtr child = NULL; | |
| 11233 xmlAttrPtr attr; | |
| 11234 int min = 1, max = 1, isElemRef, hasRefs = 0; | |
| 11235 | |
| 11236 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 11237 return (NULL); | |
| 11238 /* | |
| 11239 * Create a model group with the given compositor. | |
| 11240 */ | |
| 11241 item = xmlSchemaAddModelGroup(ctxt, schema, type, node); | |
| 11242 if (item == NULL) | |
| 11243 return (NULL); | |
| 11244 | |
| 11245 if (withParticle) { | |
| 11246 if (type == XML_SCHEMA_TYPE_ALL) { | |
| 11247 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)"); | |
| 11248 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1"); | |
| 11249 } else { | |
| 11250 /* choice + sequence */ | |
| 11251 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger")
; | |
| 11252 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, | |
| 11253 "(xs:nonNegativeInteger | unbounded)"); | |
| 11254 } | |
| 11255 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max); | |
| 11256 /* | |
| 11257 * Create a particle | |
| 11258 */ | |
| 11259 particle = xmlSchemaAddParticle(ctxt, node, min, max); | |
| 11260 if (particle == NULL) | |
| 11261 return (NULL); | |
| 11262 particle->children = (xmlSchemaTreeItemPtr) item; | |
| 11263 /* | |
| 11264 * Check for illegal attributes. | |
| 11265 */ | |
| 11266 attr = node->properties; | |
| 11267 while (attr != NULL) { | |
| 11268 if (attr->ns == NULL) { | |
| 11269 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 11270 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) && | |
| 11271 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) { | |
| 11272 xmlSchemaPIllegalAttrErr(ctxt, | |
| 11273 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 11274 } | |
| 11275 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 11276 xmlSchemaPIllegalAttrErr(ctxt, | |
| 11277 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 11278 } | |
| 11279 attr = attr->next; | |
| 11280 } | |
| 11281 } else { | |
| 11282 /* | |
| 11283 * Check for illegal attributes. | |
| 11284 */ | |
| 11285 attr = node->properties; | |
| 11286 while (attr != NULL) { | |
| 11287 if (attr->ns == NULL) { | |
| 11288 if (!xmlStrEqual(attr->name, BAD_CAST "id")) { | |
| 11289 xmlSchemaPIllegalAttrErr(ctxt, | |
| 11290 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 11291 } | |
| 11292 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 11293 xmlSchemaPIllegalAttrErr(ctxt, | |
| 11294 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 11295 } | |
| 11296 attr = attr->next; | |
| 11297 } | |
| 11298 } | |
| 11299 | |
| 11300 /* | |
| 11301 * Extract and validate attributes. | |
| 11302 */ | |
| 11303 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 11304 /* | |
| 11305 * And now for the children... | |
| 11306 */ | |
| 11307 child = node->children; | |
| 11308 if (IS_SCHEMA(child, "annotation")) { | |
| 11309 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | |
| 11310 child = child->next; | |
| 11311 } | |
| 11312 if (type == XML_SCHEMA_TYPE_ALL) { | |
| 11313 xmlSchemaParticlePtr part, last = NULL; | |
| 11314 | |
| 11315 while (IS_SCHEMA(child, "element")) { | |
| 11316 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt, | |
| 11317 schema, child, &isElemRef, 0); | |
| 11318 /* | |
| 11319 * SPEC cos-all-limited (2) | |
| 11320 * "The {max occurs} of all the particles in the {particles} | |
| 11321 * of the ('all') group must be 0 or 1. | |
| 11322 */ | |
| 11323 if (part != NULL) { | |
| 11324 if (isElemRef) | |
| 11325 hasRefs++; | |
| 11326 if (part->minOccurs > 1) { | |
| 11327 xmlSchemaPCustomErr(ctxt, | |
| 11328 XML_SCHEMAP_COS_ALL_LIMITED, | |
| 11329 NULL, child, | |
| 11330 "Invalid value for minOccurs (must be 0 or 1)", | |
| 11331 NULL); | |
| 11332 /* Reset to 1. */ | |
| 11333 part->minOccurs = 1; | |
| 11334 } | |
| 11335 if (part->maxOccurs > 1) { | |
| 11336 xmlSchemaPCustomErr(ctxt, | |
| 11337 XML_SCHEMAP_COS_ALL_LIMITED, | |
| 11338 NULL, child, | |
| 11339 "Invalid value for maxOccurs (must be 0 or 1)", | |
| 11340 NULL); | |
| 11341 /* Reset to 1. */ | |
| 11342 part->maxOccurs = 1; | |
| 11343 } | |
| 11344 if (last == NULL) | |
| 11345 item->children = (xmlSchemaTreeItemPtr) part; | |
| 11346 else | |
| 11347 last->next = (xmlSchemaTreeItemPtr) part; | |
| 11348 last = part; | |
| 11349 } | |
| 11350 child = child->next; | |
| 11351 } | |
| 11352 if (child != NULL) { | |
| 11353 xmlSchemaPContentErr(ctxt, | |
| 11354 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 11355 NULL, node, child, NULL, | |
| 11356 "(annotation?, (annotation?, element*)"); | |
| 11357 } | |
| 11358 } else { | |
| 11359 /* choice + sequence */ | |
| 11360 xmlSchemaTreeItemPtr part = NULL, last = NULL; | |
| 11361 | |
| 11362 while ((IS_SCHEMA(child, "element")) || | |
| 11363 (IS_SCHEMA(child, "group")) || | |
| 11364 (IS_SCHEMA(child, "any")) || | |
| 11365 (IS_SCHEMA(child, "choice")) || | |
| 11366 (IS_SCHEMA(child, "sequence"))) { | |
| 11367 | |
| 11368 if (IS_SCHEMA(child, "element")) { | |
| 11369 part = (xmlSchemaTreeItemPtr) | |
| 11370 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0); | |
| 11371 if (part && isElemRef) | |
| 11372 hasRefs++; | |
| 11373 } else if (IS_SCHEMA(child, "group")) { | |
| 11374 part = | |
| 11375 xmlSchemaParseModelGroupDefRef(ctxt, schema, child); | |
| 11376 if (part != NULL) | |
| 11377 hasRefs++; | |
| 11378 /* | |
| 11379 * Handle redefinitions. | |
| 11380 */ | |
| 11381 if (ctxt->isRedefine && ctxt->redef && | |
| 11382 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) && | |
| 11383 part && part->children) | |
| 11384 { | |
| 11385 if ((xmlSchemaGetQNameRefName(part->children) == | |
| 11386 ctxt->redef->refName) && | |
| 11387 (xmlSchemaGetQNameRefTargetNs(part->children) == | |
| 11388 ctxt->redef->refTargetNs)) | |
| 11389 { | |
| 11390 /* | |
| 11391 * SPEC src-redefine: | |
| 11392 * (6.1) "If it has a <group> among its contents at | |
| 11393 * some level the `actual value` of whose ref | |
| 11394 * [attribute] is the same as the `actual value` of | |
| 11395 * its own name attribute plus target namespace, then | |
| 11396 * all of the following must be true:" | |
| 11397 * (6.1.1) "It must have exactly one such group." | |
| 11398 */ | |
| 11399 if (ctxt->redefCounter != 0) { | |
| 11400 xmlChar *str = NULL; | |
| 11401 | |
| 11402 xmlSchemaCustomErr(ACTXT_CAST ctxt, | |
| 11403 XML_SCHEMAP_SRC_REDEFINE, child, NULL, | |
| 11404 "The redefining model group definition " | |
| 11405 "'%s' must not contain more than one " | |
| 11406 "reference to the redefined definition", | |
| 11407 xmlSchemaFormatQName(&str, | |
| 11408 ctxt->redef->refTargetNs, | |
| 11409 ctxt->redef->refName), | |
| 11410 NULL); | |
| 11411 FREE_AND_NULL(str) | |
| 11412 part = NULL; | |
| 11413 } else if (((WXS_PARTICLE(part))->minOccurs != 1) || | |
| 11414 ((WXS_PARTICLE(part))->maxOccurs != 1)) | |
| 11415 { | |
| 11416 xmlChar *str = NULL; | |
| 11417 /* | |
| 11418 * SPEC src-redefine: | |
| 11419 * (6.1.2) "The `actual value` of both that | |
| 11420 * group's minOccurs and maxOccurs [attribute] | |
| 11421 * must be 1 (or `absent`). | |
| 11422 */ | |
| 11423 xmlSchemaCustomErr(ACTXT_CAST ctxt, | |
| 11424 XML_SCHEMAP_SRC_REDEFINE, child, NULL, | |
| 11425 "The redefining model group definition " | |
| 11426 "'%s' must not contain a reference to the " | |
| 11427 "redefined definition with a " | |
| 11428 "maxOccurs/minOccurs other than 1", | |
| 11429 xmlSchemaFormatQName(&str, | |
| 11430 ctxt->redef->refTargetNs, | |
| 11431 ctxt->redef->refName), | |
| 11432 NULL); | |
| 11433 FREE_AND_NULL(str) | |
| 11434 part = NULL; | |
| 11435 } | |
| 11436 ctxt->redef->reference = WXS_BASIC_CAST part; | |
| 11437 ctxt->redefCounter++; | |
| 11438 } | |
| 11439 } | |
| 11440 } else if (IS_SCHEMA(child, "any")) { | |
| 11441 part = (xmlSchemaTreeItemPtr) | |
| 11442 xmlSchemaParseAny(ctxt, schema, child); | |
| 11443 } else if (IS_SCHEMA(child, "choice")) { | |
| 11444 part = xmlSchemaParseModelGroup(ctxt, schema, child, | |
| 11445 XML_SCHEMA_TYPE_CHOICE, 1); | |
| 11446 } else if (IS_SCHEMA(child, "sequence")) { | |
| 11447 part = xmlSchemaParseModelGroup(ctxt, schema, child, | |
| 11448 XML_SCHEMA_TYPE_SEQUENCE, 1); | |
| 11449 } | |
| 11450 if (part != NULL) { | |
| 11451 if (last == NULL) | |
| 11452 item->children = part; | |
| 11453 else | |
| 11454 last->next = part; | |
| 11455 last = part; | |
| 11456 } | |
| 11457 child = child->next; | |
| 11458 } | |
| 11459 if (child != NULL) { | |
| 11460 xmlSchemaPContentErr(ctxt, | |
| 11461 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 11462 NULL, node, child, NULL, | |
| 11463 "(annotation?, (element | group | choice | sequence | any)*)"); | |
| 11464 } | |
| 11465 } | |
| 11466 if ((max == 0) && (min == 0)) | |
| 11467 return (NULL); | |
| 11468 if (hasRefs) { | |
| 11469 /* | |
| 11470 * We need to resolve references. | |
| 11471 */ | |
| 11472 WXS_ADD_PENDING(ctxt, item); | |
| 11473 } | |
| 11474 if (withParticle) | |
| 11475 return ((xmlSchemaTreeItemPtr) particle); | |
| 11476 else | |
| 11477 return ((xmlSchemaTreeItemPtr) item); | |
| 11478 } | |
| 11479 | |
| 11480 /** | |
| 11481 * xmlSchemaParseRestriction: | |
| 11482 * @ctxt: a schema validation context | |
| 11483 * @schema: the schema being built | |
| 11484 * @node: a subtree containing XML Schema informations | |
| 11485 * | |
| 11486 * parse a XML schema Restriction definition | |
| 11487 * *WARNING* this interface is highly subject to change | |
| 11488 * | |
| 11489 * Returns the type definition or NULL in case of error | |
| 11490 */ | |
| 11491 static xmlSchemaTypePtr | |
| 11492 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 11493 xmlNodePtr node, xmlSchemaTypeType parentType) | |
| 11494 { | |
| 11495 xmlSchemaTypePtr type; | |
| 11496 xmlNodePtr child = NULL; | |
| 11497 xmlAttrPtr attr; | |
| 11498 | |
| 11499 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 11500 return (NULL); | |
| 11501 /* Not a component, don't create it. */ | |
| 11502 type = ctxt->ctxtType; | |
| 11503 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION; | |
| 11504 | |
| 11505 /* | |
| 11506 * Check for illegal attributes. | |
| 11507 */ | |
| 11508 attr = node->properties; | |
| 11509 while (attr != NULL) { | |
| 11510 if (attr->ns == NULL) { | |
| 11511 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 11512 (!xmlStrEqual(attr->name, BAD_CAST "base"))) { | |
| 11513 xmlSchemaPIllegalAttrErr(ctxt, | |
| 11514 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 11515 } | |
| 11516 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 11517 xmlSchemaPIllegalAttrErr(ctxt, | |
| 11518 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 11519 } | |
| 11520 attr = attr->next; | |
| 11521 } | |
| 11522 /* | |
| 11523 * Extract and validate attributes. | |
| 11524 */ | |
| 11525 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 11526 /* | |
| 11527 * Attribute | |
| 11528 */ | |
| 11529 /* | |
| 11530 * Extract the base type. The "base" attribute is mandatory if inside | |
| 11531 * a complex type or if redefining. | |
| 11532 * | |
| 11533 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> " | |
| 11534 * among its [children]), the simple type definition which is | |
| 11535 * the {content type} of the type definition `resolved` to by | |
| 11536 * the `actual value` of the base [attribute]" | |
| 11537 */ | |
| 11538 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base", | |
| 11539 &(type->baseNs), &(type->base)) == 0) | |
| 11540 { | |
| 11541 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) { | |
| 11542 xmlSchemaPMissingAttrErr(ctxt, | |
| 11543 XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 11544 NULL, node, "base", NULL); | |
| 11545 } else if ((ctxt->isRedefine) && | |
| 11546 (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) | |
| 11547 { | |
| 11548 if (type->base == NULL) { | |
| 11549 xmlSchemaPMissingAttrErr(ctxt, | |
| 11550 XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 11551 NULL, node, "base", NULL); | |
| 11552 } else if ((! xmlStrEqual(type->base, type->name)) || | |
| 11553 (! xmlStrEqual(type->baseNs, type->targetNamespace))) | |
| 11554 { | |
| 11555 xmlChar *str1 = NULL, *str2 = NULL; | |
| 11556 /* | |
| 11557 * REDEFINE: SPEC src-redefine (5) | |
| 11558 * "Within the [children], each <simpleType> must have a | |
| 11559 * <restriction> among its [children] ... the `actual value` of | |
| 11560 * whose base [attribute] must be the same as the `actual value` | |
| 11561 * of its own name attribute plus target namespace;" | |
| 11562 */ | |
| 11563 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE, | |
| 11564 NULL, node, "This is a redefinition, but the QName " | |
| 11565 "value '%s' of the 'base' attribute does not match the " | |
| 11566 "type's designation '%s'", | |
| 11567 xmlSchemaFormatQName(&str1, type->baseNs, type->base), | |
| 11568 xmlSchemaFormatQName(&str2, type->targetNamespace, | |
| 11569 type->name), NULL); | |
| 11570 FREE_AND_NULL(str1); | |
| 11571 FREE_AND_NULL(str2); | |
| 11572 /* Avoid confusion and erase the values. */ | |
| 11573 type->base = NULL; | |
| 11574 type->baseNs = NULL; | |
| 11575 } | |
| 11576 } | |
| 11577 } | |
| 11578 /* | |
| 11579 * And now for the children... | |
| 11580 */ | |
| 11581 child = node->children; | |
| 11582 if (IS_SCHEMA(child, "annotation")) { | |
| 11583 /* | |
| 11584 * Add the annotation to the simple type ancestor. | |
| 11585 */ | |
| 11586 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, | |
| 11587 xmlSchemaParseAnnotation(ctxt, child, 1)); | |
| 11588 child = child->next; | |
| 11589 } | |
| 11590 if (parentType == XML_SCHEMA_TYPE_SIMPLE) { | |
| 11591 /* | |
| 11592 * Corresponds to <simpleType><restriction><simpleType>. | |
| 11593 */ | |
| 11594 if (IS_SCHEMA(child, "simpleType")) { | |
| 11595 if (type->base != NULL) { | |
| 11596 /* | |
| 11597 * src-restriction-base-or-simpleType | |
| 11598 * Either the base [attribute] or the simpleType [child] of the | |
| 11599 * <restriction> element must be present, but not both. | |
| 11600 */ | |
| 11601 xmlSchemaPContentErr(ctxt, | |
| 11602 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE, | |
| 11603 NULL, node, child, | |
| 11604 "The attribute 'base' and the <simpleType> child are " | |
| 11605 "mutually exclusive", NULL); | |
| 11606 } else { | |
| 11607 type->baseType = (xmlSchemaTypePtr) | |
| 11608 xmlSchemaParseSimpleType(ctxt, schema, child, 0); | |
| 11609 } | |
| 11610 child = child->next; | |
| 11611 } else if (type->base == NULL) { | |
| 11612 xmlSchemaPContentErr(ctxt, | |
| 11613 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE, | |
| 11614 NULL, node, child, | |
| 11615 "Either the attribute 'base' or a <simpleType> child " | |
| 11616 "must be present", NULL); | |
| 11617 } | |
| 11618 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { | |
| 11619 /* | |
| 11620 * Corresponds to <complexType><complexContent><restriction>... | |
| 11621 * followed by: | |
| 11622 * | |
| 11623 * Model groups <all>, <choice> and <sequence>. | |
| 11624 */ | |
| 11625 if (IS_SCHEMA(child, "all")) { | |
| 11626 type->subtypes = (xmlSchemaTypePtr) | |
| 11627 xmlSchemaParseModelGroup(ctxt, schema, child, | |
| 11628 XML_SCHEMA_TYPE_ALL, 1); | |
| 11629 child = child->next; | |
| 11630 } else if (IS_SCHEMA(child, "choice")) { | |
| 11631 type->subtypes = (xmlSchemaTypePtr) | |
| 11632 xmlSchemaParseModelGroup(ctxt, | |
| 11633 schema, child, XML_SCHEMA_TYPE_CHOICE, 1); | |
| 11634 child = child->next; | |
| 11635 } else if (IS_SCHEMA(child, "sequence")) { | |
| 11636 type->subtypes = (xmlSchemaTypePtr) | |
| 11637 xmlSchemaParseModelGroup(ctxt, schema, child, | |
| 11638 XML_SCHEMA_TYPE_SEQUENCE, 1); | |
| 11639 child = child->next; | |
| 11640 /* | |
| 11641 * Model group reference <group>. | |
| 11642 */ | |
| 11643 } else if (IS_SCHEMA(child, "group")) { | |
| 11644 type->subtypes = (xmlSchemaTypePtr) | |
| 11645 xmlSchemaParseModelGroupDefRef(ctxt, schema, child); | |
| 11646 /* | |
| 11647 * Note that the reference will be resolved in | |
| 11648 * xmlSchemaResolveTypeReferences(); | |
| 11649 */ | |
| 11650 child = child->next; | |
| 11651 } | |
| 11652 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) { | |
| 11653 /* | |
| 11654 * Corresponds to <complexType><simpleContent><restriction>... | |
| 11655 * | |
| 11656 * "1.1 the simple type definition corresponding to the <simpleType> | |
| 11657 * among the [children] of <restriction> if there is one;" | |
| 11658 */ | |
| 11659 if (IS_SCHEMA(child, "simpleType")) { | |
| 11660 /* | |
| 11661 * We will store the to-be-restricted simple type in | |
| 11662 * type->contentTypeDef *temporarily*. | |
| 11663 */ | |
| 11664 type->contentTypeDef = (xmlSchemaTypePtr) | |
| 11665 xmlSchemaParseSimpleType(ctxt, schema, child, 0); | |
| 11666 if ( type->contentTypeDef == NULL) | |
| 11667 return (NULL); | |
| 11668 child = child->next; | |
| 11669 } | |
| 11670 } | |
| 11671 | |
| 11672 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) || | |
| 11673 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) { | |
| 11674 xmlSchemaFacetPtr facet, lastfacet = NULL; | |
| 11675 /* | |
| 11676 * Corresponds to <complexType><simpleContent><restriction>... | |
| 11677 * <simpleType><restriction>... | |
| 11678 */ | |
| 11679 | |
| 11680 /* | |
| 11681 * Add the facets to the simple type ancestor. | |
| 11682 */ | |
| 11683 /* | |
| 11684 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of | |
| 11685 * Simple Type Definition Schema Representation Constraint: | |
| 11686 * *Single Facet Value* | |
| 11687 */ | |
| 11688 while ((IS_SCHEMA(child, "minInclusive")) || | |
| 11689 (IS_SCHEMA(child, "minExclusive")) || | |
| 11690 (IS_SCHEMA(child, "maxInclusive")) || | |
| 11691 (IS_SCHEMA(child, "maxExclusive")) || | |
| 11692 (IS_SCHEMA(child, "totalDigits")) || | |
| 11693 (IS_SCHEMA(child, "fractionDigits")) || | |
| 11694 (IS_SCHEMA(child, "pattern")) || | |
| 11695 (IS_SCHEMA(child, "enumeration")) || | |
| 11696 (IS_SCHEMA(child, "whiteSpace")) || | |
| 11697 (IS_SCHEMA(child, "length")) || | |
| 11698 (IS_SCHEMA(child, "maxLength")) || | |
| 11699 (IS_SCHEMA(child, "minLength"))) { | |
| 11700 facet = xmlSchemaParseFacet(ctxt, schema, child); | |
| 11701 if (facet != NULL) { | |
| 11702 if (lastfacet == NULL) | |
| 11703 type->facets = facet; | |
| 11704 else | |
| 11705 lastfacet->next = facet; | |
| 11706 lastfacet = facet; | |
| 11707 lastfacet->next = NULL; | |
| 11708 } | |
| 11709 child = child->next; | |
| 11710 } | |
| 11711 /* | |
| 11712 * Create links for derivation and validation. | |
| 11713 */ | |
| 11714 if (type->facets != NULL) { | |
| 11715 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL; | |
| 11716 | |
| 11717 facet = type->facets; | |
| 11718 do { | |
| 11719 facetLink = (xmlSchemaFacetLinkPtr) | |
| 11720 xmlMalloc(sizeof(xmlSchemaFacetLink)); | |
| 11721 if (facetLink == NULL) { | |
| 11722 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL); | |
| 11723 xmlFree(facetLink); | |
| 11724 return (NULL); | |
| 11725 } | |
| 11726 facetLink->facet = facet; | |
| 11727 facetLink->next = NULL; | |
| 11728 if (lastFacetLink == NULL) | |
| 11729 type->facetSet = facetLink; | |
| 11730 else | |
| 11731 lastFacetLink->next = facetLink; | |
| 11732 lastFacetLink = facetLink; | |
| 11733 facet = facet->next; | |
| 11734 } while (facet != NULL); | |
| 11735 } | |
| 11736 } | |
| 11737 if (type->type == XML_SCHEMA_TYPE_COMPLEX) { | |
| 11738 /* | |
| 11739 * Attribute uses/declarations. | |
| 11740 */ | |
| 11741 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child, | |
| 11742 (xmlSchemaItemListPtr *) &(type->attrUses), | |
| 11743 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1) | |
| 11744 return(NULL); | |
| 11745 /* | |
| 11746 * Attribute wildcard. | |
| 11747 */ | |
| 11748 if (IS_SCHEMA(child, "anyAttribute")) { | |
| 11749 type->attributeWildcard = | |
| 11750 xmlSchemaParseAnyAttribute(ctxt, schema, child); | |
| 11751 child = child->next; | |
| 11752 } | |
| 11753 } | |
| 11754 if (child != NULL) { | |
| 11755 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { | |
| 11756 xmlSchemaPContentErr(ctxt, | |
| 11757 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 11758 NULL, node, child, NULL, | |
| 11759 "annotation?, (group | all | choice | sequence)?, " | |
| 11760 "((attribute | attributeGroup)*, anyAttribute?))"); | |
| 11761 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) { | |
| 11762 xmlSchemaPContentErr(ctxt, | |
| 11763 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 11764 NULL, node, child, NULL, | |
| 11765 "(annotation?, (simpleType?, (minExclusive | minInclusive | " | |
| 11766 "maxExclusive | maxInclusive | totalDigits | fractionDigits | " | |
| 11767 "length | minLength | maxLength | enumeration | whiteSpace | " | |
| 11768 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))"); | |
| 11769 } else { | |
| 11770 /* Simple type */ | |
| 11771 xmlSchemaPContentErr(ctxt, | |
| 11772 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 11773 NULL, node, child, NULL, | |
| 11774 "(annotation?, (simpleType?, (minExclusive | minInclusive | " | |
| 11775 "maxExclusive | maxInclusive | totalDigits | fractionDigits | " | |
| 11776 "length | minLength | maxLength | enumeration | whiteSpace | " | |
| 11777 "pattern)*))"); | |
| 11778 } | |
| 11779 } | |
| 11780 return (NULL); | |
| 11781 } | |
| 11782 | |
| 11783 /** | |
| 11784 * xmlSchemaParseExtension: | |
| 11785 * @ctxt: a schema validation context | |
| 11786 * @schema: the schema being built | |
| 11787 * @node: a subtree containing XML Schema informations | |
| 11788 * | |
| 11789 * Parses an <extension>, which is found inside a | |
| 11790 * <simpleContent> or <complexContent>. | |
| 11791 * *WARNING* this interface is highly subject to change. | |
| 11792 * | |
| 11793 * TODO: Returns the type definition or NULL in case of error | |
| 11794 */ | |
| 11795 static xmlSchemaTypePtr | |
| 11796 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 11797 xmlNodePtr node, xmlSchemaTypeType parentType) | |
| 11798 { | |
| 11799 xmlSchemaTypePtr type; | |
| 11800 xmlNodePtr child = NULL; | |
| 11801 xmlAttrPtr attr; | |
| 11802 | |
| 11803 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 11804 return (NULL); | |
| 11805 /* Not a component, don't create it. */ | |
| 11806 type = ctxt->ctxtType; | |
| 11807 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION; | |
| 11808 | |
| 11809 /* | |
| 11810 * Check for illegal attributes. | |
| 11811 */ | |
| 11812 attr = node->properties; | |
| 11813 while (attr != NULL) { | |
| 11814 if (attr->ns == NULL) { | |
| 11815 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 11816 (!xmlStrEqual(attr->name, BAD_CAST "base"))) { | |
| 11817 xmlSchemaPIllegalAttrErr(ctxt, | |
| 11818 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 11819 } | |
| 11820 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 11821 xmlSchemaPIllegalAttrErr(ctxt, | |
| 11822 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 11823 } | |
| 11824 attr = attr->next; | |
| 11825 } | |
| 11826 | |
| 11827 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 11828 | |
| 11829 /* | |
| 11830 * Attribute "base" - mandatory. | |
| 11831 */ | |
| 11832 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node, | |
| 11833 "base", &(type->baseNs), &(type->base)) == 0) && | |
| 11834 (type->base == NULL)) { | |
| 11835 xmlSchemaPMissingAttrErr(ctxt, | |
| 11836 XML_SCHEMAP_S4S_ATTR_MISSING, | |
| 11837 NULL, node, "base", NULL); | |
| 11838 } | |
| 11839 /* | |
| 11840 * And now for the children... | |
| 11841 */ | |
| 11842 child = node->children; | |
| 11843 if (IS_SCHEMA(child, "annotation")) { | |
| 11844 /* | |
| 11845 * Add the annotation to the type ancestor. | |
| 11846 */ | |
| 11847 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, | |
| 11848 xmlSchemaParseAnnotation(ctxt, child, 1)); | |
| 11849 child = child->next; | |
| 11850 } | |
| 11851 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { | |
| 11852 /* | |
| 11853 * Corresponds to <complexType><complexContent><extension>... and: | |
| 11854 * | |
| 11855 * Model groups <all>, <choice>, <sequence> and <group>. | |
| 11856 */ | |
| 11857 if (IS_SCHEMA(child, "all")) { | |
| 11858 type->subtypes = (xmlSchemaTypePtr) | |
| 11859 xmlSchemaParseModelGroup(ctxt, schema, | |
| 11860 child, XML_SCHEMA_TYPE_ALL, 1); | |
| 11861 child = child->next; | |
| 11862 } else if (IS_SCHEMA(child, "choice")) { | |
| 11863 type->subtypes = (xmlSchemaTypePtr) | |
| 11864 xmlSchemaParseModelGroup(ctxt, schema, | |
| 11865 child, XML_SCHEMA_TYPE_CHOICE, 1); | |
| 11866 child = child->next; | |
| 11867 } else if (IS_SCHEMA(child, "sequence")) { | |
| 11868 type->subtypes = (xmlSchemaTypePtr) | |
| 11869 xmlSchemaParseModelGroup(ctxt, schema, | |
| 11870 child, XML_SCHEMA_TYPE_SEQUENCE, 1); | |
| 11871 child = child->next; | |
| 11872 } else if (IS_SCHEMA(child, "group")) { | |
| 11873 type->subtypes = (xmlSchemaTypePtr) | |
| 11874 xmlSchemaParseModelGroupDefRef(ctxt, schema, child); | |
| 11875 /* | |
| 11876 * Note that the reference will be resolved in | |
| 11877 * xmlSchemaResolveTypeReferences(); | |
| 11878 */ | |
| 11879 child = child->next; | |
| 11880 } | |
| 11881 } | |
| 11882 if (child != NULL) { | |
| 11883 /* | |
| 11884 * Attribute uses/declarations. | |
| 11885 */ | |
| 11886 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child, | |
| 11887 (xmlSchemaItemListPtr *) &(type->attrUses), | |
| 11888 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1) | |
| 11889 return(NULL); | |
| 11890 /* | |
| 11891 * Attribute wildcard. | |
| 11892 */ | |
| 11893 if (IS_SCHEMA(child, "anyAttribute")) { | |
| 11894 ctxt->ctxtType->attributeWildcard = | |
| 11895 xmlSchemaParseAnyAttribute(ctxt, schema, child); | |
| 11896 child = child->next; | |
| 11897 } | |
| 11898 } | |
| 11899 if (child != NULL) { | |
| 11900 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { | |
| 11901 /* Complex content extension. */ | |
| 11902 xmlSchemaPContentErr(ctxt, | |
| 11903 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 11904 NULL, node, child, NULL, | |
| 11905 "(annotation?, ((group | all | choice | sequence)?, " | |
| 11906 "((attribute | attributeGroup)*, anyAttribute?)))"); | |
| 11907 } else { | |
| 11908 /* Simple content extension. */ | |
| 11909 xmlSchemaPContentErr(ctxt, | |
| 11910 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 11911 NULL, node, child, NULL, | |
| 11912 "(annotation?, ((attribute | attributeGroup)*, " | |
| 11913 "anyAttribute?))"); | |
| 11914 } | |
| 11915 } | |
| 11916 return (NULL); | |
| 11917 } | |
| 11918 | |
| 11919 /** | |
| 11920 * xmlSchemaParseSimpleContent: | |
| 11921 * @ctxt: a schema validation context | |
| 11922 * @schema: the schema being built | |
| 11923 * @node: a subtree containing XML Schema informations | |
| 11924 * | |
| 11925 * parse a XML schema SimpleContent definition | |
| 11926 * *WARNING* this interface is highly subject to change | |
| 11927 * | |
| 11928 * Returns the type definition or NULL in case of error | |
| 11929 */ | |
| 11930 static int | |
| 11931 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt, | |
| 11932 xmlSchemaPtr schema, xmlNodePtr node, | |
| 11933 int *hasRestrictionOrExtension) | |
| 11934 { | |
| 11935 xmlSchemaTypePtr type; | |
| 11936 xmlNodePtr child = NULL; | |
| 11937 xmlAttrPtr attr; | |
| 11938 | |
| 11939 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || | |
| 11940 (hasRestrictionOrExtension == NULL)) | |
| 11941 return (-1); | |
| 11942 *hasRestrictionOrExtension = 0; | |
| 11943 /* Not a component, don't create it. */ | |
| 11944 type = ctxt->ctxtType; | |
| 11945 type->contentType = XML_SCHEMA_CONTENT_SIMPLE; | |
| 11946 /* | |
| 11947 * Check for illegal attributes. | |
| 11948 */ | |
| 11949 attr = node->properties; | |
| 11950 while (attr != NULL) { | |
| 11951 if (attr->ns == NULL) { | |
| 11952 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) { | |
| 11953 xmlSchemaPIllegalAttrErr(ctxt, | |
| 11954 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 11955 } | |
| 11956 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 11957 xmlSchemaPIllegalAttrErr(ctxt, | |
| 11958 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 11959 } | |
| 11960 attr = attr->next; | |
| 11961 } | |
| 11962 | |
| 11963 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 11964 | |
| 11965 /* | |
| 11966 * And now for the children... | |
| 11967 */ | |
| 11968 child = node->children; | |
| 11969 if (IS_SCHEMA(child, "annotation")) { | |
| 11970 /* | |
| 11971 * Add the annotation to the complex type ancestor. | |
| 11972 */ | |
| 11973 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, | |
| 11974 xmlSchemaParseAnnotation(ctxt, child, 1)); | |
| 11975 child = child->next; | |
| 11976 } | |
| 11977 if (child == NULL) { | |
| 11978 xmlSchemaPContentErr(ctxt, | |
| 11979 XML_SCHEMAP_S4S_ELEM_MISSING, | |
| 11980 NULL, node, NULL, NULL, | |
| 11981 "(annotation?, (restriction | extension))"); | |
| 11982 } | |
| 11983 if (child == NULL) { | |
| 11984 xmlSchemaPContentErr(ctxt, | |
| 11985 XML_SCHEMAP_S4S_ELEM_MISSING, | |
| 11986 NULL, node, NULL, NULL, | |
| 11987 "(annotation?, (restriction | extension))"); | |
| 11988 } | |
| 11989 if (IS_SCHEMA(child, "restriction")) { | |
| 11990 xmlSchemaParseRestriction(ctxt, schema, child, | |
| 11991 XML_SCHEMA_TYPE_SIMPLE_CONTENT); | |
| 11992 (*hasRestrictionOrExtension) = 1; | |
| 11993 child = child->next; | |
| 11994 } else if (IS_SCHEMA(child, "extension")) { | |
| 11995 xmlSchemaParseExtension(ctxt, schema, child, | |
| 11996 XML_SCHEMA_TYPE_SIMPLE_CONTENT); | |
| 11997 (*hasRestrictionOrExtension) = 1; | |
| 11998 child = child->next; | |
| 11999 } | |
| 12000 if (child != NULL) { | |
| 12001 xmlSchemaPContentErr(ctxt, | |
| 12002 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 12003 NULL, node, child, NULL, | |
| 12004 "(annotation?, (restriction | extension))"); | |
| 12005 } | |
| 12006 return (0); | |
| 12007 } | |
| 12008 | |
| 12009 /** | |
| 12010 * xmlSchemaParseComplexContent: | |
| 12011 * @ctxt: a schema validation context | |
| 12012 * @schema: the schema being built | |
| 12013 * @node: a subtree containing XML Schema informations | |
| 12014 * | |
| 12015 * parse a XML schema ComplexContent definition | |
| 12016 * *WARNING* this interface is highly subject to change | |
| 12017 * | |
| 12018 * Returns the type definition or NULL in case of error | |
| 12019 */ | |
| 12020 static int | |
| 12021 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt, | |
| 12022 xmlSchemaPtr schema, xmlNodePtr node, | |
| 12023 int *hasRestrictionOrExtension) | |
| 12024 { | |
| 12025 xmlSchemaTypePtr type; | |
| 12026 xmlNodePtr child = NULL; | |
| 12027 xmlAttrPtr attr; | |
| 12028 | |
| 12029 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || | |
| 12030 (hasRestrictionOrExtension == NULL)) | |
| 12031 return (-1); | |
| 12032 *hasRestrictionOrExtension = 0; | |
| 12033 /* Not a component, don't create it. */ | |
| 12034 type = ctxt->ctxtType; | |
| 12035 /* | |
| 12036 * Check for illegal attributes. | |
| 12037 */ | |
| 12038 attr = node->properties; | |
| 12039 while (attr != NULL) { | |
| 12040 if (attr->ns == NULL) { | |
| 12041 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | |
| 12042 (!xmlStrEqual(attr->name, BAD_CAST "mixed"))) | |
| 12043 { | |
| 12044 xmlSchemaPIllegalAttrErr(ctxt, | |
| 12045 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 12046 } | |
| 12047 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 12048 xmlSchemaPIllegalAttrErr(ctxt, | |
| 12049 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 12050 } | |
| 12051 attr = attr->next; | |
| 12052 } | |
| 12053 | |
| 12054 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 12055 | |
| 12056 /* | |
| 12057 * Set the 'mixed' on the complex type ancestor. | |
| 12058 */ | |
| 12059 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) { | |
| 12060 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0) | |
| 12061 type->flags |= XML_SCHEMAS_TYPE_MIXED; | |
| 12062 } | |
| 12063 child = node->children; | |
| 12064 if (IS_SCHEMA(child, "annotation")) { | |
| 12065 /* | |
| 12066 * Add the annotation to the complex type ancestor. | |
| 12067 */ | |
| 12068 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, | |
| 12069 xmlSchemaParseAnnotation(ctxt, child, 1)); | |
| 12070 child = child->next; | |
| 12071 } | |
| 12072 if (child == NULL) { | |
| 12073 xmlSchemaPContentErr(ctxt, | |
| 12074 XML_SCHEMAP_S4S_ELEM_MISSING, | |
| 12075 NULL, node, NULL, | |
| 12076 NULL, "(annotation?, (restriction | extension))"); | |
| 12077 } | |
| 12078 if (child == NULL) { | |
| 12079 xmlSchemaPContentErr(ctxt, | |
| 12080 XML_SCHEMAP_S4S_ELEM_MISSING, | |
| 12081 NULL, node, NULL, | |
| 12082 NULL, "(annotation?, (restriction | extension))"); | |
| 12083 } | |
| 12084 if (IS_SCHEMA(child, "restriction")) { | |
| 12085 xmlSchemaParseRestriction(ctxt, schema, child, | |
| 12086 XML_SCHEMA_TYPE_COMPLEX_CONTENT); | |
| 12087 (*hasRestrictionOrExtension) = 1; | |
| 12088 child = child->next; | |
| 12089 } else if (IS_SCHEMA(child, "extension")) { | |
| 12090 xmlSchemaParseExtension(ctxt, schema, child, | |
| 12091 XML_SCHEMA_TYPE_COMPLEX_CONTENT); | |
| 12092 (*hasRestrictionOrExtension) = 1; | |
| 12093 child = child->next; | |
| 12094 } | |
| 12095 if (child != NULL) { | |
| 12096 xmlSchemaPContentErr(ctxt, | |
| 12097 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 12098 NULL, node, child, | |
| 12099 NULL, "(annotation?, (restriction | extension))"); | |
| 12100 } | |
| 12101 return (0); | |
| 12102 } | |
| 12103 | |
| 12104 /** | |
| 12105 * xmlSchemaParseComplexType: | |
| 12106 * @ctxt: a schema validation context | |
| 12107 * @schema: the schema being built | |
| 12108 * @node: a subtree containing XML Schema informations | |
| 12109 * | |
| 12110 * parse a XML schema Complex Type definition | |
| 12111 * *WARNING* this interface is highly subject to change | |
| 12112 * | |
| 12113 * Returns the type definition or NULL in case of error | |
| 12114 */ | |
| 12115 static xmlSchemaTypePtr | |
| 12116 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | |
| 12117 xmlNodePtr node, int topLevel) | |
| 12118 { | |
| 12119 xmlSchemaTypePtr type, ctxtType; | |
| 12120 xmlNodePtr child = NULL; | |
| 12121 const xmlChar *name = NULL; | |
| 12122 xmlAttrPtr attr; | |
| 12123 const xmlChar *attrValue; | |
| 12124 #ifdef ENABLE_NAMED_LOCALS | |
| 12125 char buf[40]; | |
| 12126 #endif | |
| 12127 int final = 0, block = 0, hasRestrictionOrExtension = 0; | |
| 12128 | |
| 12129 | |
| 12130 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | |
| 12131 return (NULL); | |
| 12132 | |
| 12133 ctxtType = ctxt->ctxtType; | |
| 12134 | |
| 12135 if (topLevel) { | |
| 12136 attr = xmlSchemaGetPropNode(node, "name"); | |
| 12137 if (attr == NULL) { | |
| 12138 xmlSchemaPMissingAttrErr(ctxt, | |
| 12139 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL); | |
| 12140 return (NULL); | |
| 12141 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr, | |
| 12142 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { | |
| 12143 return (NULL); | |
| 12144 } | |
| 12145 } | |
| 12146 | |
| 12147 if (topLevel == 0) { | |
| 12148 /* | |
| 12149 * Parse as local complex type definition. | |
| 12150 */ | |
| 12151 #ifdef ENABLE_NAMED_LOCALS | |
| 12152 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1); | |
| 12153 type = xmlSchemaAddType(ctxt, schema, | |
| 12154 XML_SCHEMA_TYPE_COMPLEX, | |
| 12155 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1), | |
| 12156 ctxt->targetNamespace, node, 0); | |
| 12157 #else | |
| 12158 type = xmlSchemaAddType(ctxt, schema, | |
| 12159 XML_SCHEMA_TYPE_COMPLEX, | |
| 12160 NULL, ctxt->targetNamespace, node, 0); | |
| 12161 #endif | |
| 12162 if (type == NULL) | |
| 12163 return (NULL); | |
| 12164 name = type->name; | |
| 12165 type->node = node; | |
| 12166 type->type = XML_SCHEMA_TYPE_COMPLEX; | |
| 12167 /* | |
| 12168 * TODO: We need the target namespace. | |
| 12169 */ | |
| 12170 } else { | |
| 12171 /* | |
| 12172 * Parse as global complex type definition. | |
| 12173 */ | |
| 12174 type = xmlSchemaAddType(ctxt, schema, | |
| 12175 XML_SCHEMA_TYPE_COMPLEX, | |
| 12176 name, ctxt->targetNamespace, node, 1); | |
| 12177 if (type == NULL) | |
| 12178 return (NULL); | |
| 12179 type->node = node; | |
| 12180 type->type = XML_SCHEMA_TYPE_COMPLEX; | |
| 12181 type->flags |= XML_SCHEMAS_TYPE_GLOBAL; | |
| 12182 } | |
| 12183 type->targetNamespace = ctxt->targetNamespace; | |
| 12184 /* | |
| 12185 * Handle attributes. | |
| 12186 */ | |
| 12187 attr = node->properties; | |
| 12188 while (attr != NULL) { | |
| 12189 if (attr->ns == NULL) { | |
| 12190 if (xmlStrEqual(attr->name, BAD_CAST "id")) { | |
| 12191 /* | |
| 12192 * Attribute "id". | |
| 12193 */ | |
| 12194 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | |
| 12195 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) { | |
| 12196 /* | |
| 12197 * Attribute "mixed". | |
| 12198 */ | |
| 12199 if (xmlSchemaPGetBoolNodeValue(ctxt, | |
| 12200 NULL, (xmlNodePtr) attr)) | |
| 12201 type->flags |= XML_SCHEMAS_TYPE_MIXED; | |
| 12202 } else if (topLevel) { | |
| 12203 /* | |
| 12204 * Attributes of global complex type definitions. | |
| 12205 */ | |
| 12206 if (xmlStrEqual(attr->name, BAD_CAST "name")) { | |
| 12207 /* Pass. */ | |
| 12208 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) { | |
| 12209 /* | |
| 12210 * Attribute "abstract". | |
| 12211 */ | |
| 12212 if (xmlSchemaPGetBoolNodeValue(ctxt, | |
| 12213 NULL, (xmlNodePtr) attr)) | |
| 12214 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT; | |
| 12215 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) { | |
| 12216 /* | |
| 12217 * Attribute "final". | |
| 12218 */ | |
| 12219 attrValue = xmlSchemaGetNodeContent(ctxt, | |
| 12220 (xmlNodePtr) attr); | |
| 12221 if (xmlSchemaPValAttrBlockFinal(attrValue, | |
| 12222 &(type->flags), | |
| 12223 -1, | |
| 12224 XML_SCHEMAS_TYPE_FINAL_EXTENSION, | |
| 12225 XML_SCHEMAS_TYPE_FINAL_RESTRICTION, | |
| 12226 -1, -1, -1) != 0) | |
| 12227 { | |
| 12228 xmlSchemaPSimpleTypeErr(ctxt, | |
| 12229 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 12230 NULL, (xmlNodePtr) attr, NULL, | |
| 12231 "(#all | List of (extension | restriction))", | |
| 12232 attrValue, NULL, NULL, NULL); | |
| 12233 } else | |
| 12234 final = 1; | |
| 12235 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) { | |
| 12236 /* | |
| 12237 * Attribute "block". | |
| 12238 */ | |
| 12239 attrValue = xmlSchemaGetNodeContent(ctxt, | |
| 12240 (xmlNodePtr) attr); | |
| 12241 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags), | |
| 12242 -1, | |
| 12243 XML_SCHEMAS_TYPE_BLOCK_EXTENSION, | |
| 12244 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION, | |
| 12245 -1, -1, -1) != 0) { | |
| 12246 xmlSchemaPSimpleTypeErr(ctxt, | |
| 12247 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | |
| 12248 NULL, (xmlNodePtr) attr, NULL, | |
| 12249 "(#all | List of (extension | restriction)) ", | |
| 12250 attrValue, NULL, NULL, NULL); | |
| 12251 } else | |
| 12252 block = 1; | |
| 12253 } else { | |
| 12254 xmlSchemaPIllegalAttrErr(ctxt, | |
| 12255 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 12256 } | |
| 12257 } else { | |
| 12258 xmlSchemaPIllegalAttrErr(ctxt, | |
| 12259 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 12260 } | |
| 12261 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | |
| 12262 xmlSchemaPIllegalAttrErr(ctxt, | |
| 12263 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | |
| 12264 } | |
| 12265 attr = attr->next; | |
| 12266 } | |
| 12267 if (! block) { | |
| 12268 /* | |
| 12269 * Apply default "block" values. | |
| 12270 */ | |
| 12271 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION) | |
| 12272 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; | |
| 12273 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION) | |
| 12274 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; | |
| 12275 } | |
| 12276 if (! final) { | |
| 12277 /* | |
| 12278 * Apply default "block" values. | |
| 12279 */ | |
| 12280 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) | |
| 12281 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION; | |
| 12282 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) | |
| 12283 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION; | |
| 12284 } | |
| 12285 /* | |
| 12286 * And now for the children... | |
| 12287 */ | |
| 12288 child = node->children; | |
| 12289 if (IS_SCHEMA(child, "annotation")) { | |
| 12290 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | |
| 12291 child = child->next; | |
| 12292 } | |
| 12293 ctxt->ctxtType = type; | |
| 12294 if (IS_SCHEMA(child, "simpleContent")) { | |
| 12295 /* | |
| 12296 * <complexType><simpleContent>... | |
| 12297 * 3.4.3 : 2.2 | |
| 12298 * Specifying mixed='true' when the <simpleContent> | |
| 12299 * alternative is chosen has no effect | |
| 12300 */ | |
| 12301 if (type->flags & XML_SCHEMAS_TYPE_MIXED) | |
| 12302 type->flags ^= XML_SCHEMAS_TYPE_MIXED; | |
| 12303 xmlSchemaParseSimpleContent(ctxt, schema, child, | |
| 12304 &hasRestrictionOrExtension); | |
| 12305 child = child->next; | |
| 12306 } else if (IS_SCHEMA(child, "complexContent")) { | |
| 12307 /* | |
| 12308 * <complexType><complexContent>... | |
| 12309 */ | |
| 12310 type->contentType = XML_SCHEMA_CONTENT_EMPTY; | |
| 12311 xmlSchemaParseComplexContent(ctxt, schema, child, | |
| 12312 &hasRestrictionOrExtension); | |
| 12313 child = child->next; | |
| 12314 } else { | |
| 12315 /* | |
| 12316 * E.g <complexType><sequence>... or <complexType><attribute>... etc. | |
| 12317 * | |
| 12318 * SPEC | |
| 12319 * "...the third alternative (neither <simpleContent> nor | |
| 12320 * <complexContent>) is chosen. This case is understood as shorthand | |
| 12321 * for complex content restricting the `ur-type definition`, and the | |
| 12322 * details of the mappings should be modified as necessary. | |
| 12323 */ | |
| 12324 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); | |
| 12325 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION; | |
| 12326 /* | |
| 12327 * Parse model groups. | |
| 12328 */ | |
| 12329 if (IS_SCHEMA(child, "all")) { | |
| 12330 type->subtypes = (xmlSchemaTypePtr) | |
| 12331 xmlSchemaParseModelGroup(ctxt, schema, child, | |
| 12332 XML_SCHEMA_TYPE_ALL, 1); | |
| 12333 child = child->next; | |
| 12334 } else if (IS_SCHEMA(child, "choice")) { | |
| 12335 type->subtypes = (xmlSchemaTypePtr) | |
| 12336 xmlSchemaParseModelGroup(ctxt, schema, child, | |
| 12337 XML_SCHEMA_TYPE_CHOICE, 1); | |
| 12338 child = child->next; | |
| 12339 } else if (IS_SCHEMA(child, "sequence")) { | |
| 12340 type->subtypes = (xmlSchemaTypePtr) | |
| 12341 xmlSchemaParseModelGroup(ctxt, schema, child, | |
| 12342 XML_SCHEMA_TYPE_SEQUENCE, 1); | |
| 12343 child = child->next; | |
| 12344 } else if (IS_SCHEMA(child, "group")) { | |
| 12345 type->subtypes = (xmlSchemaTypePtr) | |
| 12346 xmlSchemaParseModelGroupDefRef(ctxt, schema, child); | |
| 12347 /* | |
| 12348 * Note that the reference will be resolved in | |
| 12349 * xmlSchemaResolveTypeReferences(); | |
| 12350 */ | |
| 12351 child = child->next; | |
| 12352 } | |
| 12353 /* | |
| 12354 * Parse attribute decls/refs. | |
| 12355 */ | |
| 12356 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child, | |
| 12357 (xmlSchemaItemListPtr *) &(type->attrUses), | |
| 12358 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1) | |
| 12359 return(NULL); | |
| 12360 /* | |
| 12361 * Parse attribute wildcard. | |
| 12362 */ | |
| 12363 if (IS_SCHEMA(child, "anyAttribute")) { | |
| 12364 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, c
hild); | |
| 12365 child = child->next; | |
| 12366 } | |
| 12367 } | |
| 12368 if (child != NULL) { | |
| 12369 xmlSchemaPContentErr(ctxt, | |
| 12370 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | |
| 12371 NULL, node, child, | |
| 12372 NULL, "(annotation?, (simpleContent | complexContent | " | |
| 12373 "((group | all | choice | sequence)?, ((attribute | " | |
| 12374 "attributeGroup)*, anyAttribute?))))"); | |
| 12375 } | |
| 12376 /* | |
| 12377 * REDEFINE: SPEC src-redefine (5) | |
| 12378 */ | |
| 12379 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) { | |
| 12380 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, | |
| 12381 NULL, node, "This is a redefinition, thus the " | |
| 12382 "<complexType> must have a <restriction> or <extension> " | |
| 12383 "grand-child", NULL); | |
| 12384 } | |
| 12385 ctxt->ctxtType = ctxtType; | |
| 12386 return (type); | |
| 12387 } | |
| 12388 | |
| 12389 /************************************************************************ | |
| 12390 * * | |
| 12391 * Validating using Schemas * | |
| 12392 * * | |
| 12393 ************************************************************************/ | |
| 12394 | |
| 12395 /************************************************************************ | |
| 12396 * * | |
| 12397 * Reading/Writing Schemas * | |
| 12398 * * | |
| 12399 ************************************************************************/ | |
| 12400 | |
| 12401 #if 0 /* Will be enabled if it is clear what options are needed. */ | |
| 12402 /** | |
| 12403 * xmlSchemaParserCtxtSetOptions: | |
| 12404 * @ctxt: a schema parser context | |
| 12405 * @options: a combination of xmlSchemaParserOption | |
| 12406 * | |
| 12407 * Sets the options to be used during the parse. | |
| 12408 * | |
| 12409 * Returns 0 in case of success, -1 in case of an | |
| 12410 * API error. | |
| 12411 */ | |
| 12412 static int | |
| 12413 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt, | |
| 12414 int options) | |
| 12415 | |
| 12416 { | |
| 12417 int i; | |
| 12418 | |
| 12419 if (ctxt == NULL) | |
| 12420 return (-1); | |
| 12421 /* | |
| 12422 * WARNING: Change the start value if adding to the | |
| 12423 * xmlSchemaParseOption. | |
| 12424 */ | |
| 12425 for (i = 1; i < (int) sizeof(int) * 8; i++) { | |
| 12426 if (options & 1<<i) { | |
| 12427 return (-1); | |
| 12428 } | |
| 12429 } | |
| 12430 ctxt->options = options; | |
| 12431 return (0); | |
| 12432 } | |
| 12433 | |
| 12434 /** | |
| 12435 * xmlSchemaValidCtxtGetOptions: | |
| 12436 * @ctxt: a schema parser context | |
| 12437 * | |
| 12438 * Returns the option combination of the parser context. | |
| 12439 */ | |
| 12440 static int | |
| 12441 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt) | |
| 12442 | |
| 12443 { | |
| 12444 if (ctxt == NULL) | |
| 12445 return (-1); | |
| 12446 else | |
| 12447 return (ctxt->options); | |
| 12448 } | |
| 12449 #endif | |
| 12450 | |
| 12451 /** | |
| 12452 * xmlSchemaNewParserCtxt: | |
| 12453 * @URL: the location of the schema | |
| 12454 * | |
| 12455 * Create an XML Schemas parse context for that file/resource expected | |
| 12456 * to contain an XML Schemas file. | |
| 12457 * | |
| 12458 * Returns the parser context or NULL in case of error | |
| 12459 */ | |
| 12460 xmlSchemaParserCtxtPtr | |
| 12461 xmlSchemaNewParserCtxt(const char *URL) | |
| 12462 { | |
| 12463 xmlSchemaParserCtxtPtr ret; | |
| 12464 | |
| 12465 if (URL == NULL) | |
| 12466 return (NULL); | |
| 12467 | |
| 12468 ret = xmlSchemaParserCtxtCreate(); | |
| 12469 if (ret == NULL) | |
| 12470 return(NULL); | |
| 12471 ret->dict = xmlDictCreate(); | |
| 12472 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1); | |
| 12473 return (ret); | |
| 12474 } | |
| 12475 | |
| 12476 /** | |
| 12477 * xmlSchemaNewMemParserCtxt: | |
| 12478 * @buffer: a pointer to a char array containing the schemas | |
| 12479 * @size: the size of the array | |
| 12480 * | |
| 12481 * Create an XML Schemas parse context for that memory buffer expected | |
| 12482 * to contain an XML Schemas file. | |
| 12483 * | |
| 12484 * Returns the parser context or NULL in case of error | |
| 12485 */ | |
| 12486 xmlSchemaParserCtxtPtr | |
| 12487 xmlSchemaNewMemParserCtxt(const char *buffer, int size) | |
| 12488 { | |
| 12489 xmlSchemaParserCtxtPtr ret; | |
| 12490 | |
| 12491 if ((buffer == NULL) || (size <= 0)) | |
| 12492 return (NULL); | |
| 12493 ret = xmlSchemaParserCtxtCreate(); | |
| 12494 if (ret == NULL) | |
| 12495 return(NULL); | |
| 12496 ret->buffer = buffer; | |
| 12497 ret->size = size; | |
| 12498 ret->dict = xmlDictCreate(); | |
| 12499 return (ret); | |
| 12500 } | |
| 12501 | |
| 12502 /** | |
| 12503 * xmlSchemaNewDocParserCtxt: | |
| 12504 * @doc: a preparsed document tree | |
| 12505 * | |
| 12506 * Create an XML Schemas parse context for that document. | |
| 12507 * NB. The document may be modified during the parsing process. | |
| 12508 * | |
| 12509 * Returns the parser context or NULL in case of error | |
| 12510 */ | |
| 12511 xmlSchemaParserCtxtPtr | |
| 12512 xmlSchemaNewDocParserCtxt(xmlDocPtr doc) | |
| 12513 { | |
| 12514 xmlSchemaParserCtxtPtr ret; | |
| 12515 | |
| 12516 if (doc == NULL) | |
| 12517 return (NULL); | |
| 12518 ret = xmlSchemaParserCtxtCreate(); | |
| 12519 if (ret == NULL) | |
| 12520 return(NULL); | |
| 12521 ret->doc = doc; | |
| 12522 ret->dict = xmlDictCreate(); | |
| 12523 /* The application has responsibility for the document */ | |
| 12524 ret->preserve = 1; | |
| 12525 | |
| 12526 return (ret); | |
| 12527 } | |
| 12528 | |
| 12529 /** | |
| 12530 * xmlSchemaFreeParserCtxt: | |
| 12531 * @ctxt: the schema parser context | |
| 12532 * | |
| 12533 * Free the resources associated to the schema parser context | |
| 12534 */ | |
| 12535 void | |
| 12536 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt) | |
| 12537 { | |
| 12538 if (ctxt == NULL) | |
| 12539 return; | |
| 12540 if (ctxt->doc != NULL && !ctxt->preserve) | |
| 12541 xmlFreeDoc(ctxt->doc); | |
| 12542 if (ctxt->vctxt != NULL) { | |
| 12543 xmlSchemaFreeValidCtxt(ctxt->vctxt); | |
| 12544 } | |
| 12545 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) { | |
| 12546 xmlSchemaConstructionCtxtFree(ctxt->constructor); | |
| 12547 ctxt->constructor = NULL; | |
| 12548 ctxt->ownsConstructor = 0; | |
| 12549 } | |
| 12550 if (ctxt->attrProhibs != NULL) | |
| 12551 xmlSchemaItemListFree(ctxt->attrProhibs); | |
| 12552 xmlDictFree(ctxt->dict); | |
| 12553 xmlFree(ctxt); | |
| 12554 } | |
| 12555 | |
| 12556 /************************************************************************ | |
| 12557 * * | |
| 12558 * Building the content models * | |
| 12559 * * | |
| 12560 ************************************************************************/ | |
| 12561 | |
| 12562 /** | |
| 12563 * xmlSchemaBuildContentModelForSubstGroup: | |
| 12564 * | |
| 12565 * Returns 1 if nillable, 0 otherwise | |
| 12566 */ | |
| 12567 static int | |
| 12568 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt, | |
| 12569 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end) | |
| 12570 { | |
| 12571 xmlAutomataStatePtr start, tmp; | |
| 12572 xmlSchemaElementPtr elemDecl, member; | |
| 12573 xmlSchemaSubstGroupPtr substGroup; | |
| 12574 int i; | |
| 12575 int ret = 0; | |
| 12576 | |
| 12577 elemDecl = (xmlSchemaElementPtr) particle->children; | |
| 12578 /* | |
| 12579 * Wrap the substitution group with a CHOICE. | |
| 12580 */ | |
| 12581 start = pctxt->state; | |
| 12582 if (end == NULL) | |
| 12583 end = xmlAutomataNewState(pctxt->am); | |
| 12584 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl); | |
| 12585 if (substGroup == NULL) { | |
| 12586 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle), | |
| 12587 XML_SCHEMAP_INTERNAL, | |
| 12588 "Internal error: xmlSchemaBuildContentModelForSubstGroup, " | |
| 12589 "declaration is marked having a subst. group but none " | |
| 12590 "available.\n", elemDecl->name, NULL); | |
| 12591 return(0); | |
| 12592 } | |
| 12593 if (counter >= 0) { | |
| 12594 /* | |
| 12595 * NOTE that we put the declaration in, even if it's abstract. | |
| 12596 * However, an error will be raised during *validation* if an element | |
| 12597 * information item shall be validated against an abstract element | |
| 12598 * declaration. | |
| 12599 */ | |
| 12600 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter); | |
| 12601 xmlAutomataNewTransition2(pctxt->am, tmp, end, | |
| 12602 elemDecl->name, elemDecl->targetNamespace, elemDecl); | |
| 12603 /* | |
| 12604 * Add subst. group members. | |
| 12605 */ | |
| 12606 for (i = 0; i < substGroup->members->nbItems; i++) { | |
| 12607 member = (xmlSchemaElementPtr) substGroup->members->items[i]; | |
| 12608 xmlAutomataNewTransition2(pctxt->am, tmp, end, | |
| 12609 member->name, member->targetNamespace, member); | |
| 12610 } | |
| 12611 } else if (particle->maxOccurs == 1) { | |
| 12612 /* | |
| 12613 * NOTE that we put the declaration in, even if it's abstract, | |
| 12614 */ | |
| 12615 xmlAutomataNewEpsilon(pctxt->am, | |
| 12616 xmlAutomataNewTransition2(pctxt->am, | |
| 12617 start, NULL, | |
| 12618 elemDecl->name, elemDecl->targetNamespace, elemDecl), end); | |
| 12619 /* | |
| 12620 * Add subst. group members. | |
| 12621 */ | |
| 12622 for (i = 0; i < substGroup->members->nbItems; i++) { | |
| 12623 member = (xmlSchemaElementPtr) substGroup->members->items[i]; | |
| 12624 /* | |
| 12625 * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2() | |
| 12626 * was incorrectly used instead of xmlAutomataNewTransition2() | |
| 12627 * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL | |
| 12628 * section in xmlSchemaBuildAContentModel() ). | |
| 12629 * TODO: Check if xmlAutomataNewOnceTrans2() was instead | |
| 12630 * intended for the above "counter" section originally. I.e., | |
| 12631 * check xs:all with subst-groups. | |
| 12632 * | |
| 12633 * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL, | |
| 12634 * member->name, member->targetNamespace, | |
| 12635 * 1, 1, member); | |
| 12636 */ | |
| 12637 tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL, | |
| 12638 member->name, member->targetNamespace, member); | |
| 12639 xmlAutomataNewEpsilon(pctxt->am, tmp, end); | |
| 12640 } | |
| 12641 } else { | |
| 12642 xmlAutomataStatePtr hop; | |
| 12643 int maxOccurs = particle->maxOccurs == UNBOUNDED ? | |
| 12644 UNBOUNDED : particle->maxOccurs - 1; | |
| 12645 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1; | |
| 12646 | |
| 12647 counter = | |
| 12648 xmlAutomataNewCounter(pctxt->am, minOccurs, | |
| 12649 maxOccurs); | |
| 12650 hop = xmlAutomataNewState(pctxt->am); | |
| 12651 | |
| 12652 xmlAutomataNewEpsilon(pctxt->am, | |
| 12653 xmlAutomataNewTransition2(pctxt->am, | |
| 12654 start, NULL, | |
| 12655 elemDecl->name, elemDecl->targetNamespace, elemDecl), | |
| 12656 hop); | |
| 12657 /* | |
| 12658 * Add subst. group members. | |
| 12659 */ | |
| 12660 for (i = 0; i < substGroup->members->nbItems; i++) { | |
| 12661 member = (xmlSchemaElementPtr) substGroup->members->items[i]; | |
| 12662 xmlAutomataNewEpsilon(pctxt->am, | |
| 12663 xmlAutomataNewTransition2(pctxt->am, | |
| 12664 start, NULL, | |
| 12665 member->name, member->targetNamespace, member), | |
| 12666 hop); | |
| 12667 } | |
| 12668 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter); | |
| 12669 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); | |
| 12670 } | |
| 12671 if (particle->minOccurs == 0) { | |
| 12672 xmlAutomataNewEpsilon(pctxt->am, start, end); | |
| 12673 ret = 1; | |
| 12674 } | |
| 12675 pctxt->state = end; | |
| 12676 return(ret); | |
| 12677 } | |
| 12678 | |
| 12679 /** | |
| 12680 * xmlSchemaBuildContentModelForElement: | |
| 12681 * | |
| 12682 * Returns 1 if nillable, 0 otherwise | |
| 12683 */ | |
| 12684 static int | |
| 12685 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt, | |
| 12686 xmlSchemaParticlePtr particle) | |
| 12687 { | |
| 12688 int ret = 0; | |
| 12689 | |
| 12690 if (((xmlSchemaElementPtr) particle->children)->flags & | |
| 12691 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) { | |
| 12692 /* | |
| 12693 * Substitution groups. | |
| 12694 */ | |
| 12695 ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL); | |
| 12696 } else { | |
| 12697 xmlSchemaElementPtr elemDecl; | |
| 12698 xmlAutomataStatePtr start; | |
| 12699 | |
| 12700 elemDecl = (xmlSchemaElementPtr) particle->children; | |
| 12701 | |
| 12702 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) | |
| 12703 return(0); | |
| 12704 if (particle->maxOccurs == 1) { | |
| 12705 start = ctxt->state; | |
| 12706 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, | |
| 12707 elemDecl->name, elemDecl->targetNamespace, elemDecl); | |
| 12708 } else if ((particle->maxOccurs >= UNBOUNDED) && | |
| 12709 (particle->minOccurs < 2)) { | |
| 12710 /* Special case. */ | |
| 12711 start = ctxt->state; | |
| 12712 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, | |
| 12713 elemDecl->name, elemDecl->targetNamespace, elemDecl); | |
| 12714 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt-
>state, | |
| 12715 elemDecl->name, elemDecl->targetNamespace, elemDecl); | |
| 12716 } else { | |
| 12717 int counter; | |
| 12718 int maxOccurs = particle->maxOccurs == UNBOUNDED ? | |
| 12719 UNBOUNDED : particle->maxOccurs - 1; | |
| 12720 int minOccurs = particle->minOccurs < 1 ? | |
| 12721 0 : particle->minOccurs - 1; | |
| 12722 | |
| 12723 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL); | |
| 12724 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs); | |
| 12725 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, | |
| 12726 elemDecl->name, elemDecl->targetNamespace, elemDecl); | |
| 12727 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter); | |
| 12728 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state, | |
| 12729 NULL, counter); | |
| 12730 } | |
| 12731 if (particle->minOccurs == 0) { | |
| 12732 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state); | |
| 12733 ret = 1; | |
| 12734 } | |
| 12735 } | |
| 12736 return(ret); | |
| 12737 } | |
| 12738 | |
| 12739 /** | |
| 12740 * xmlSchemaBuildAContentModel: | |
| 12741 * @ctxt: the schema parser context | |
| 12742 * @particle: the particle component | |
| 12743 * @name: the complex type's name whose content is being built | |
| 12744 * | |
| 12745 * Create the automaton for the {content type} of a complex type. | |
| 12746 * | |
| 12747 * Returns 1 if the content is nillable, 0 otherwise | |
| 12748 */ | |
| 12749 static int | |
| 12750 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt, | |
| 12751 xmlSchemaParticlePtr particle) | |
| 12752 { | |
| 12753 int ret = 0, tmp2; | |
| 12754 | |
| 12755 if (particle == NULL) { | |
| 12756 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL"); | |
| 12757 return(1); | |
| 12758 } | |
| 12759 if (particle->children == NULL) { | |
| 12760 /* | |
| 12761 * Just return in this case. A missing "term" of the particle | |
| 12762 * might arise due to an invalid "term" component. | |
| 12763 */ | |
| 12764 return(1); | |
| 12765 } | |
| 12766 | |
| 12767 switch (particle->children->type) { | |
| 12768 case XML_SCHEMA_TYPE_ANY: { | |
| 12769 xmlAutomataStatePtr start, end; | |
| 12770 xmlSchemaWildcardPtr wild; | |
| 12771 xmlSchemaWildcardNsPtr ns; | |
| 12772 | |
| 12773 wild = (xmlSchemaWildcardPtr) particle->children; | |
| 12774 | |
| 12775 start = pctxt->state; | |
| 12776 end = xmlAutomataNewState(pctxt->am); | |
| 12777 | |
| 12778 if (particle->maxOccurs == 1) { | |
| 12779 if (wild->any == 1) { | |
| 12780 /* | |
| 12781 * We need to add both transitions: | |
| 12782 * | |
| 12783 * 1. the {"*", "*"} for elements in a namespace. | |
| 12784 */ | |
| 12785 pctxt->state = | |
| 12786 xmlAutomataNewTransition2(pctxt->am, | |
| 12787 start, NULL, BAD_CAST "*", BAD_CAST "*", wild); | |
| 12788 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); | |
| 12789 /* | |
| 12790 * 2. the {"*"} for elements in no namespace. | |
| 12791 */ | |
| 12792 pctxt->state = | |
| 12793 xmlAutomataNewTransition2(pctxt->am, | |
| 12794 start, NULL, BAD_CAST "*", NULL, wild); | |
| 12795 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); | |
| 12796 | |
| 12797 } else if (wild->nsSet != NULL) { | |
| 12798 ns = wild->nsSet; | |
| 12799 do { | |
| 12800 pctxt->state = start; | |
| 12801 pctxt->state = xmlAutomataNewTransition2(pctxt->am, | |
| 12802 pctxt->state, NULL, BAD_CAST "*", ns->value, wild); | |
| 12803 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); | |
| 12804 ns = ns->next; | |
| 12805 } while (ns != NULL); | |
| 12806 | |
| 12807 } else if (wild->negNsSet != NULL) { | |
| 12808 pctxt->state = xmlAutomataNewNegTrans(pctxt->am, | |
| 12809 start, end, BAD_CAST "*", wild->negNsSet->value, | |
| 12810 wild); | |
| 12811 } | |
| 12812 } else { | |
| 12813 int counter; | |
| 12814 xmlAutomataStatePtr hop; | |
| 12815 int maxOccurs = | |
| 12816 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : | |
| 12817 particle->maxOccurs - 1; | |
| 12818 int minOccurs = | |
| 12819 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1; | |
| 12820 | |
| 12821 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs)
; | |
| 12822 hop = xmlAutomataNewState(pctxt->am); | |
| 12823 if (wild->any == 1) { | |
| 12824 pctxt->state = | |
| 12825 xmlAutomataNewTransition2(pctxt->am, | |
| 12826 start, NULL, BAD_CAST "*", BAD_CAST "*", wild); | |
| 12827 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); | |
| 12828 pctxt->state = | |
| 12829 xmlAutomataNewTransition2(pctxt->am, | |
| 12830 start, NULL, BAD_CAST "*", NULL, wild); | |
| 12831 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); | |
| 12832 } else if (wild->nsSet != NULL) { | |
| 12833 ns = wild->nsSet; | |
| 12834 do { | |
| 12835 pctxt->state = | |
| 12836 xmlAutomataNewTransition2(pctxt->am, | |
| 12837 start, NULL, BAD_CAST "*", ns->value, wild); | |
| 12838 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); | |
| 12839 ns = ns->next; | |
| 12840 } while (ns != NULL); | |
| 12841 | |
| 12842 } else if (wild->negNsSet != NULL) { | |
| 12843 pctxt->state = xmlAutomataNewNegTrans(pctxt->am, | |
| 12844 start, hop, BAD_CAST "*", wild->negNsSet->value, | |
| 12845 wild); | |
| 12846 } | |
| 12847 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter); | |
| 12848 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); | |
| 12849 } | |
| 12850 if (particle->minOccurs == 0) { | |
| 12851 xmlAutomataNewEpsilon(pctxt->am, start, end); | |
| 12852 ret = 1; | |
| 12853 } | |
| 12854 pctxt->state = end; | |
| 12855 break; | |
| 12856 } | |
| 12857 case XML_SCHEMA_TYPE_ELEMENT: | |
| 12858 ret = xmlSchemaBuildContentModelForElement(pctxt, particle); | |
| 12859 break; | |
| 12860 case XML_SCHEMA_TYPE_SEQUENCE:{ | |
| 12861 xmlSchemaTreeItemPtr sub; | |
| 12862 | |
| 12863 ret = 1; | |
| 12864 /* | |
| 12865 * If max and min occurances are default (1) then | |
| 12866 * simply iterate over the particles of the <sequence>. | |
| 12867 */ | |
| 12868 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) { | |
| 12869 sub = particle->children->children; | |
| 12870 | |
| 12871 while (sub != NULL) { | |
| 12872 tmp2 = xmlSchemaBuildAContentModel(pctxt, | |
| 12873 (xmlSchemaParticlePtr) sub); | |
| 12874 if (tmp2 != 1) ret = 0; | |
| 12875 sub = sub->next; | |
| 12876 } | |
| 12877 } else { | |
| 12878 xmlAutomataStatePtr oldstate = pctxt->state; | |
| 12879 | |
| 12880 if (particle->maxOccurs >= UNBOUNDED) { | |
| 12881 if (particle->minOccurs > 1) { | |
| 12882 xmlAutomataStatePtr tmp; | |
| 12883 int counter; | |
| 12884 | |
| 12885 pctxt->state = xmlAutomataNewEpsilon(pctxt->am, | |
| 12886 oldstate, NULL); | |
| 12887 oldstate = pctxt->state; | |
| 12888 | |
| 12889 counter = xmlAutomataNewCounter(pctxt->am, | |
| 12890 particle->minOccurs - 1, UNBOUNDED); | |
| 12891 | |
| 12892 sub = particle->children->children; | |
| 12893 while (sub != NULL) { | |
| 12894 tmp2 = xmlSchemaBuildAContentModel(pctxt, | |
| 12895 (xmlSchemaParticlePtr) sub); | |
| 12896 if (tmp2 != 1) ret = 0; | |
| 12897 sub = sub->next; | |
| 12898 } | |
| 12899 tmp = pctxt->state; | |
| 12900 xmlAutomataNewCountedTrans(pctxt->am, tmp, | |
| 12901 oldstate, counter); | |
| 12902 pctxt->state = | |
| 12903 xmlAutomataNewCounterTrans(pctxt->am, tmp, | |
| 12904 NULL, counter); | |
| 12905 if (ret == 1) | |
| 12906 xmlAutomataNewEpsilon(pctxt->am, | |
| 12907 oldstate, pctxt->state); | |
| 12908 | |
| 12909 } else { | |
| 12910 pctxt->state = xmlAutomataNewEpsilon(pctxt->am, | |
| 12911 oldstate, NULL); | |
| 12912 oldstate = pctxt->state; | |
| 12913 | |
| 12914 sub = particle->children->children; | |
| 12915 while (sub != NULL) { | |
| 12916 tmp2 = xmlSchemaBuildAContentModel(pctxt, | |
| 12917 (xmlSchemaParticlePtr) sub); | |
| 12918 if (tmp2 != 1) ret = 0; | |
| 12919 sub = sub->next; | |
| 12920 } | |
| 12921 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, | |
| 12922 oldstate); | |
| 12923 /* | |
| 12924 * epsilon needed to block previous trans from | |
| 12925 * being allowed to enter back from another | |
| 12926 * construct | |
| 12927 */ | |
| 12928 pctxt->state = xmlAutomataNewEpsilon(pctxt->am, | |
| 12929 pctxt->state, NULL); | |
| 12930 if (particle->minOccurs == 0) { | |
| 12931 xmlAutomataNewEpsilon(pctxt->am, | |
| 12932 oldstate, pctxt->state); | |
| 12933 ret = 1; | |
| 12934 } | |
| 12935 } | |
| 12936 } else if ((particle->maxOccurs > 1) | |
| 12937 || (particle->minOccurs > 1)) { | |
| 12938 xmlAutomataStatePtr tmp; | |
| 12939 int counter; | |
| 12940 | |
| 12941 pctxt->state = xmlAutomataNewEpsilon(pctxt->am, | |
| 12942 oldstate, NULL); | |
| 12943 oldstate = pctxt->state; | |
| 12944 | |
| 12945 counter = xmlAutomataNewCounter(pctxt->am, | |
| 12946 particle->minOccurs - 1, | |
| 12947 particle->maxOccurs - 1); | |
| 12948 | |
| 12949 sub = particle->children->children; | |
| 12950 while (sub != NULL) { | |
| 12951 tmp2 = xmlSchemaBuildAContentModel(pctxt, | |
| 12952 (xmlSchemaParticlePtr) sub); | |
| 12953 if (tmp2 != 1) ret = 0; | |
| 12954 sub = sub->next; | |
| 12955 } | |
| 12956 tmp = pctxt->state; | |
| 12957 xmlAutomataNewCountedTrans(pctxt->am, | |
| 12958 tmp, oldstate, counter); | |
| 12959 pctxt->state = | |
| 12960 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL, | |
| 12961 counter); | |
| 12962 if ((particle->minOccurs == 0) || (ret == 1)) { | |
| 12963 xmlAutomataNewEpsilon(pctxt->am, | |
| 12964 oldstate, pctxt->state); | |
| 12965 ret = 1; | |
| 12966 } | |
| 12967 } else { | |
| 12968 sub = particle->children->children; | |
| 12969 while (sub != NULL) { | |
| 12970 tmp2 = xmlSchemaBuildAContentModel(pctxt, | |
| 12971 (xmlSchemaParticlePtr) sub); | |
| 12972 if (tmp2 != 1) ret = 0; | |
| 12973 sub = sub->next; | |
| 12974 } | |
| 12975 | |
| 12976 /* | |
| 12977 * epsilon needed to block previous trans from | |
| 12978 * being allowed to enter back from another | |
| 12979 * construct | |
| 12980 */ | |
| 12981 pctxt->state = xmlAutomataNewEpsilon(pctxt->am, | |
| 12982 pctxt->state, NULL); | |
| 12983 | |
| 12984 if (particle->minOccurs == 0) { | |
| 12985 xmlAutomataNewEpsilon(pctxt->am, oldstate, | |
| 12986 pctxt->state); | |
| 12987 ret = 1; | |
| 12988 } | |
| 12989 } | |
| 12990 } | |
| 12991 break; | |
| 12992 } | |
| 12993 case XML_SCHEMA_TYPE_CHOICE:{ | |
| 12994 xmlSchemaTreeItemPtr sub; | |
| 12995 xmlAutomataStatePtr start, end; | |
| 12996 | |
| 12997 ret = 0; | |
| 12998 start = pctxt->state; | |
| 12999 end = xmlAutomataNewState(pctxt->am); | |
| 13000 | |
| 13001 /* | |
| 13002 * iterate over the subtypes and remerge the end with an | |
| 13003 * epsilon transition | |
| 13004 */ | |
| 13005 if (particle->maxOccurs == 1) { | |
| 13006 sub = particle->children->children; | |
| 13007 while (sub != NULL) { | |
| 13008 pctxt->state = start; | |
| 13009 tmp2 = xmlSchemaBuildAContentModel(pctxt, | |
| 13010 (xmlSchemaParticlePtr) sub); | |
| 13011 if (tmp2 == 1) ret = 1; | |
| 13012 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); | |
| 13013 sub = sub->next; | |
| 13014 } | |
| 13015 } else { | |
| 13016 int counter; | |
| 13017 xmlAutomataStatePtr hop, base; | |
| 13018 int maxOccurs = particle->maxOccurs == UNBOUNDED ? | |
| 13019 UNBOUNDED : particle->maxOccurs - 1; | |
| 13020 int minOccurs = | |
| 13021 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1; | |
| 13022 | |
| 13023 /* | |
| 13024 * use a counter to keep track of the number of transtions | |
| 13025 * which went through the choice. | |
| 13026 */ | |
| 13027 counter = | |
| 13028 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs); | |
| 13029 hop = xmlAutomataNewState(pctxt->am); | |
| 13030 base = xmlAutomataNewState(pctxt->am); | |
| 13031 | |
| 13032 sub = particle->children->children; | |
| 13033 while (sub != NULL) { | |
| 13034 pctxt->state = base; | |
| 13035 tmp2 = xmlSchemaBuildAContentModel(pctxt, | |
| 13036 (xmlSchemaParticlePtr) sub); | |
| 13037 if (tmp2 == 1) ret = 1; | |
| 13038 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); | |
| 13039 sub = sub->next; | |
| 13040 } | |
| 13041 xmlAutomataNewEpsilon(pctxt->am, start, base); | |
| 13042 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter); | |
| 13043 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); | |
| 13044 if (ret == 1) | |
| 13045 xmlAutomataNewEpsilon(pctxt->am, base, end); | |
| 13046 } | |
| 13047 if (particle->minOccurs == 0) { | |
| 13048 xmlAutomataNewEpsilon(pctxt->am, start, end); | |
| 13049 ret = 1; | |
| 13050 } | |
| 13051 pctxt->state = end; | |
| 13052 break; | |
| 13053 } | |
| 13054 case XML_SCHEMA_TYPE_ALL:{ | |
| 13055 xmlAutomataStatePtr start, tmp; | |
| 13056 xmlSchemaParticlePtr sub; | |
| 13057 xmlSchemaElementPtr elemDecl; | |
| 13058 | |
| 13059 ret = 1; | |
| 13060 | |
| 13061 sub = (xmlSchemaParticlePtr) particle->children->children; | |
| 13062 if (sub == NULL) | |
| 13063 break; | |
| 13064 | |
| 13065 ret = 0; | |
| 13066 | |
| 13067 start = pctxt->state; | |
| 13068 tmp = xmlAutomataNewState(pctxt->am); | |
| 13069 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp); | |
| 13070 pctxt->state = tmp; | |
| 13071 while (sub != NULL) { | |
| 13072 pctxt->state = tmp; | |
| 13073 | |
| 13074 elemDecl = (xmlSchemaElementPtr) sub->children; | |
| 13075 if (elemDecl == NULL) { | |
| 13076 PERROR_INT("xmlSchemaBuildAContentModel", | |
| 13077 "<element> particle has no term"); | |
| 13078 return(ret); | |
| 13079 }; | |
| 13080 /* | |
| 13081 * NOTE: The {max occurs} of all the particles in the | |
| 13082 * {particles} of the group must be 0 or 1; this is | |
| 13083 * already ensured during the parse of the content of | |
| 13084 * <all>. | |
| 13085 */ | |
| 13086 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) { | |
| 13087 int counter; | |
| 13088 | |
| 13089 /* | |
| 13090 * This is an abstract group, we need to share | |
| 13091 * the same counter for all the element transitions | |
| 13092 * derived from the group | |
| 13093 */ | |
| 13094 counter = xmlAutomataNewCounter(pctxt->am, | |
| 13095 sub->minOccurs, sub->maxOccurs); | |
| 13096 xmlSchemaBuildContentModelForSubstGroup(pctxt, | |
| 13097 sub, counter, pctxt->state); | |
| 13098 } else { | |
| 13099 if ((sub->minOccurs == 1) && | |
| 13100 (sub->maxOccurs == 1)) { | |
| 13101 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state, | |
| 13102 pctxt->state, | |
| 13103 elemDecl->name, | |
| 13104 elemDecl->targetNamespace, | |
| 13105 1, 1, elemDecl); | |
| 13106 } else if ((sub->minOccurs == 0) && | |
| 13107 (sub->maxOccurs == 1)) { | |
| 13108 | |
| 13109 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state, | |
| 13110 pctxt->state, | |
| 13111 elemDecl->name, | |
| 13112 elemDecl->targetNamespace, | |
| 13113 0, | |
| 13114 1, | |
| 13115 elemDecl); | |
| 13116 } | |
| 13117 } | |
| 13118 sub = (xmlSchemaParticlePtr) sub->next; | |
| 13119 } | |
| 13120 pctxt->state = | |
| 13121 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0); | |
| 13122 if (particle->minOccurs == 0) { | |
| 13123 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state); | |
| 13124 ret = 1; | |
| 13125 } | |
| 13126 break; | |
| 13127 } | |
| 13128 case XML_SCHEMA_TYPE_GROUP: | |
| 13129 /* | |
| 13130 * If we hit a model group definition, then this means that | |
| 13131 * it was empty, thus was not substituted for the containing | |
| 13132 * model group. Just do nothing in this case. | |
| 13133 * TODO: But the group should be substituted and not occur at | |
| 13134 * all in the content model at this point. Fix this. | |
| 13135 */ | |
| 13136 ret = 1; | |
| 13137 break; | |
| 13138 default: | |
| 13139 xmlSchemaInternalErr2(ACTXT_CAST pctxt, | |
| 13140 "xmlSchemaBuildAContentModel", | |
| 13141 "found unexpected term of type '%s' in content model", | |
| 13142 WXS_ITEM_TYPE_NAME(particle->children), NULL); | |
| 13143 return(ret); | |
| 13144 } | |
| 13145 return(ret); | |
| 13146 } | |
| 13147 | |
| 13148 /** | |
| 13149 * xmlSchemaBuildContentModel: | |
| 13150 * @ctxt: the schema parser context | |
| 13151 * @type: the complex type definition | |
| 13152 * @name: the element name | |
| 13153 * | |
| 13154 * Builds the content model of the complex type. | |
| 13155 */ | |
| 13156 static void | |
| 13157 xmlSchemaBuildContentModel(xmlSchemaTypePtr type, | |
| 13158 xmlSchemaParserCtxtPtr ctxt) | |
| 13159 { | |
| 13160 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || | |
| 13161 (type->contModel != NULL) || | |
| 13162 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) && | |
| 13163 (type->contentType != XML_SCHEMA_CONTENT_MIXED))) | |
| 13164 return; | |
| 13165 | |
| 13166 #ifdef DEBUG_CONTENT | |
| 13167 xmlGenericError(xmlGenericErrorContext, | |
| 13168 "Building content model for %s\n", name); | |
| 13169 #endif | |
| 13170 ctxt->am = NULL; | |
| 13171 ctxt->am = xmlNewAutomata(); | |
| 13172 if (ctxt->am == NULL) { | |
| 13173 xmlGenericError(xmlGenericErrorContext, | |
| 13174 "Cannot create automata for complex type %s\n", type->name); | |
| 13175 return; | |
| 13176 } | |
| 13177 ctxt->state = xmlAutomataGetInitState(ctxt->am); | |
| 13178 /* | |
| 13179 * Build the automaton. | |
| 13180 */ | |
| 13181 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type)); | |
| 13182 xmlAutomataSetFinalState(ctxt->am, ctxt->state); | |
| 13183 type->contModel = xmlAutomataCompile(ctxt->am); | |
| 13184 if (type->contModel == NULL) { | |
| 13185 xmlSchemaPCustomErr(ctxt, | |
| 13186 XML_SCHEMAP_INTERNAL, | |
| 13187 WXS_BASIC_CAST type, type->node, | |
| 13188 "Failed to compile the content model", NULL); | |
| 13189 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) { | |
| 13190 xmlSchemaPCustomErr(ctxt, | |
| 13191 XML_SCHEMAP_NOT_DETERMINISTIC, | |
| 13192 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */ | |
| 13193 WXS_BASIC_CAST type, type->node, | |
| 13194 "The content model is not determinist", NULL); | |
| 13195 } else { | |
| 13196 #ifdef DEBUG_CONTENT_REGEXP | |
| 13197 xmlGenericError(xmlGenericErrorContext, | |
| 13198 "Content model of %s:\n", type->name); | |
| 13199 xmlRegexpPrint(stderr, type->contModel); | |
| 13200 #endif | |
| 13201 } | |
| 13202 ctxt->state = NULL; | |
| 13203 xmlFreeAutomata(ctxt->am); | |
| 13204 ctxt->am = NULL; | |
| 13205 } | |
| 13206 | |
| 13207 /** | |
| 13208 * xmlSchemaResolveElementReferences: | |
| 13209 * @elem: the schema element context | |
| 13210 * @ctxt: the schema parser context | |
| 13211 * | |
| 13212 * Resolves the references of an element declaration | |
| 13213 * or particle, which has an element declaration as it's | |
| 13214 * term. | |
| 13215 */ | |
| 13216 static void | |
| 13217 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl, | |
| 13218 xmlSchemaParserCtxtPtr ctxt) | |
| 13219 { | |
| 13220 if ((ctxt == NULL) || (elemDecl == NULL) || | |
| 13221 ((elemDecl != NULL) && | |
| 13222 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED))) | |
| 13223 return; | |
| 13224 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED; | |
| 13225 | |
| 13226 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) { | |
| 13227 xmlSchemaTypePtr type; | |
| 13228 | |
| 13229 /* (type definition) ... otherwise the type definition `resolved` | |
| 13230 * to by the `actual value` of the type [attribute] ... | |
| 13231 */ | |
| 13232 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType, | |
| 13233 elemDecl->namedTypeNs); | |
| 13234 if (type == NULL) { | |
| 13235 xmlSchemaPResCompAttrErr(ctxt, | |
| 13236 XML_SCHEMAP_SRC_RESOLVE, | |
| 13237 WXS_BASIC_CAST elemDecl, elemDecl->node, | |
| 13238 "type", elemDecl->namedType, elemDecl->namedTypeNs, | |
| 13239 XML_SCHEMA_TYPE_BASIC, "type definition"); | |
| 13240 } else | |
| 13241 elemDecl->subtypes = type; | |
| 13242 } | |
| 13243 if (elemDecl->substGroup != NULL) { | |
| 13244 xmlSchemaElementPtr substHead; | |
| 13245 | |
| 13246 /* | |
| 13247 * FIXME TODO: Do we need a new field in _xmlSchemaElement for | |
| 13248 * substitutionGroup? | |
| 13249 */ | |
| 13250 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup, | |
| 13251 elemDecl->substGroupNs); | |
| 13252 if (substHead == NULL) { | |
| 13253 xmlSchemaPResCompAttrErr(ctxt, | |
| 13254 XML_SCHEMAP_SRC_RESOLVE, | |
| 13255 WXS_BASIC_CAST elemDecl, NULL, | |
| 13256 "substitutionGroup", elemDecl->substGroup, | |
| 13257 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL); | |
| 13258 } else { | |
| 13259 xmlSchemaResolveElementReferences(substHead, ctxt); | |
| 13260 /* | |
| 13261 * Set the "substitution group affiliation". | |
| 13262 * NOTE that now we use the "refDecl" field for this. | |
| 13263 */ | |
| 13264 WXS_SUBST_HEAD(elemDecl) = substHead; | |
| 13265 /* | |
| 13266 * The type definitions is set to: | |
| 13267 * SPEC "...the {type definition} of the element | |
| 13268 * declaration `resolved` to by the `actual value` | |
| 13269 * of the substitutionGroup [attribute], if present" | |
| 13270 */ | |
| 13271 if (elemDecl->subtypes == NULL) | |
| 13272 elemDecl->subtypes = substHead->subtypes; | |
| 13273 } | |
| 13274 } | |
| 13275 /* | |
| 13276 * SPEC "The definition of anyType serves as the default type definition | |
| 13277 * for element declarations whose XML representation does not specify one." | |
| 13278 */ | |
| 13279 if ((elemDecl->subtypes == NULL) && | |
| 13280 (elemDecl->namedType == NULL) && | |
| 13281 (elemDecl->substGroup == NULL)) | |
| 13282 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); | |
| 13283 } | |
| 13284 | |
| 13285 /** | |
| 13286 * xmlSchemaResolveUnionMemberTypes: | |
| 13287 * @ctxt: the schema parser context | |
| 13288 * @type: the schema simple type definition | |
| 13289 * | |
| 13290 * Checks and builds the "member type definitions" property of the union | |
| 13291 * simple type. This handles part (1), part (2) is done in | |
| 13292 * xmlSchemaFinishMemberTypeDefinitionsProperty() | |
| 13293 * | |
| 13294 * Returns -1 in case of an internal error, 0 otherwise. | |
| 13295 */ | |
| 13296 static int | |
| 13297 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt, | |
| 13298 xmlSchemaTypePtr type) | |
| 13299 { | |
| 13300 | |
| 13301 xmlSchemaTypeLinkPtr link, lastLink, newLink; | |
| 13302 xmlSchemaTypePtr memberType; | |
| 13303 | |
| 13304 /* | |
| 13305 * SPEC (1) "If the <union> alternative is chosen, then [Definition:] | |
| 13306 * define the explicit members as the type definitions `resolved` | |
| 13307 * to by the items in the `actual value` of the memberTypes [attribute], | |
| 13308 * if any, followed by the type definitions corresponding to the | |
| 13309 * <simpleType>s among the [children] of <union>, if any." | |
| 13310 */ | |
| 13311 /* | |
| 13312 * Resolve references. | |
| 13313 */ | |
| 13314 link = type->memberTypes; | |
| 13315 lastLink = NULL; | |
| 13316 while (link != NULL) { | |
| 13317 const xmlChar *name, *nsName; | |
| 13318 | |
| 13319 name = ((xmlSchemaQNameRefPtr) link->type)->name; | |
| 13320 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace; | |
| 13321 | |
| 13322 memberType = xmlSchemaGetType(ctxt->schema, name, nsName); | |
| 13323 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) { | |
| 13324 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE, | |
| 13325 WXS_BASIC_CAST type, type->node, "memberTypes", | |
| 13326 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL); | |
| 13327 /* | |
| 13328 * Remove the member type link. | |
| 13329 */ | |
| 13330 if (lastLink == NULL) | |
| 13331 type->memberTypes = link->next; | |
| 13332 else | |
| 13333 lastLink->next = link->next; | |
| 13334 newLink = link; | |
| 13335 link = link->next; | |
| 13336 xmlFree(newLink); | |
| 13337 } else { | |
| 13338 link->type = memberType; | |
| 13339 lastLink = link; | |
| 13340 link = link->next; | |
| 13341 } | |
| 13342 } | |
| 13343 /* | |
| 13344 * Add local simple types, | |
| 13345 */ | |
| 13346 memberType = type->subtypes; | |
| 13347 while (memberType != NULL) { | |
| 13348 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink)); | |
| 13349 if (link == NULL) { | |
| 13350 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL); | |
| 13351 return (-1); | |
| 13352 } | |
| 13353 link->type = memberType; | |
| 13354 link->next = NULL; | |
| 13355 if (lastLink == NULL) | |
| 13356 type->memberTypes = link; | |
| 13357 else | |
| 13358 lastLink->next = link; | |
| 13359 lastLink = link; | |
| 13360 memberType = memberType->next; | |
| 13361 } | |
| 13362 return (0); | |
| 13363 } | |
| 13364 | |
| 13365 /** | |
| 13366 * xmlSchemaIsDerivedFromBuiltInType: | |
| 13367 * @ctxt: the schema parser context | |
| 13368 * @type: the type definition | |
| 13369 * @valType: the value type | |
| 13370 * | |
| 13371 * | |
| 13372 * Returns 1 if the type has the given value type, or | |
| 13373 * is derived from such a type. | |
| 13374 */ | |
| 13375 static int | |
| 13376 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType) | |
| 13377 { | |
| 13378 if (type == NULL) | |
| 13379 return (0); | |
| 13380 if (WXS_IS_COMPLEX(type)) | |
| 13381 return (0); | |
| 13382 if (type->type == XML_SCHEMA_TYPE_BASIC) { | |
| 13383 if (type->builtInType == valType) | |
| 13384 return(1); | |
| 13385 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) || | |
| 13386 (type->builtInType == XML_SCHEMAS_ANYTYPE)) | |
| 13387 return (0); | |
| 13388 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType)); | |
| 13389 } | |
| 13390 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType)); | |
| 13391 } | |
| 13392 | |
| 13393 #if 0 | |
| 13394 /** | |
| 13395 * xmlSchemaIsDerivedFromBuiltInType: | |
| 13396 * @ctxt: the schema parser context | |
| 13397 * @type: the type definition | |
| 13398 * @valType: the value type | |
| 13399 * | |
| 13400 * | |
| 13401 * Returns 1 if the type has the given value type, or | |
| 13402 * is derived from such a type. | |
| 13403 */ | |
| 13404 static int | |
| 13405 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType) | |
| 13406 { | |
| 13407 if (type == NULL) | |
| 13408 return (0); | |
| 13409 if (WXS_IS_COMPLEX(type)) | |
| 13410 return (0); | |
| 13411 if (type->type == XML_SCHEMA_TYPE_BASIC) { | |
| 13412 if (type->builtInType == valType) | |
| 13413 return(1); | |
| 13414 return (0); | |
| 13415 } else | |
| 13416 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType)); | |
| 13417 | |
| 13418 return (0); | |
| 13419 } | |
| 13420 | |
| 13421 static xmlSchemaTypePtr | |
| 13422 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type) | |
| 13423 { | |
| 13424 if (type == NULL) | |
| 13425 return (NULL); | |
| 13426 if (WXS_IS_COMPLEX(type)) | |
| 13427 return (NULL); | |
| 13428 if (type->type == XML_SCHEMA_TYPE_BASIC) | |
| 13429 return(type); | |
| 13430 return(xmlSchemaQueryBuiltInType(type->subtypes)); | |
| 13431 } | |
| 13432 #endif | |
| 13433 | |
| 13434 /** | |
| 13435 * xmlSchemaGetPrimitiveType: | |
| 13436 * @type: the simpleType definition | |
| 13437 * | |
| 13438 * Returns the primitive type of the given type or | |
| 13439 * NULL in case of error. | |
| 13440 */ | |
| 13441 static xmlSchemaTypePtr | |
| 13442 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type) | |
| 13443 { | |
| 13444 | |
| 13445 while (type != NULL) { | |
| 13446 /* | |
| 13447 * Note that anySimpleType is actually not a primitive type | |
| 13448 * but we need that here. | |
| 13449 */ | |
| 13450 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) || | |
| 13451 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)) | |
| 13452 return (type); | |
| 13453 type = type->baseType; | |
| 13454 } | |
| 13455 | |
| 13456 return (NULL); | |
| 13457 } | |
| 13458 | |
| 13459 #if 0 | |
| 13460 /** | |
| 13461 * xmlSchemaGetBuiltInTypeAncestor: | |
| 13462 * @type: the simpleType definition | |
| 13463 * | |
| 13464 * Returns the primitive type of the given type or | |
| 13465 * NULL in case of error. | |
| 13466 */ | |
| 13467 static xmlSchemaTypePtr | |
| 13468 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type) | |
| 13469 { | |
| 13470 if (WXS_IS_LIST(type) || WXS_IS_UNION(type)) | |
| 13471 return (0); | |
| 13472 while (type != NULL) { | |
| 13473 if (type->type == XML_SCHEMA_TYPE_BASIC) | |
| 13474 return (type); | |
| 13475 type = type->baseType; | |
| 13476 } | |
| 13477 | |
| 13478 return (NULL); | |
| 13479 } | |
| 13480 #endif | |
| 13481 | |
| 13482 /** | |
| 13483 * xmlSchemaCloneWildcardNsConstraints: | |
| 13484 * @ctxt: the schema parser context | |
| 13485 * @dest: the destination wildcard | |
| 13486 * @source: the source wildcard | |
| 13487 * | |
| 13488 * Clones the namespace constraints of source | |
| 13489 * and assignes them to dest. | |
| 13490 * Returns -1 on internal error, 0 otherwise. | |
| 13491 */ | |
| 13492 static int | |
| 13493 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt, | |
| 13494 xmlSchemaWildcardPtr dest, | |
| 13495 xmlSchemaWildcardPtr source) | |
| 13496 { | |
| 13497 xmlSchemaWildcardNsPtr cur, tmp, last; | |
| 13498 | |
| 13499 if ((source == NULL) || (dest == NULL)) | |
| 13500 return(-1); | |
| 13501 dest->any = source->any; | |
| 13502 cur = source->nsSet; | |
| 13503 last = NULL; | |
| 13504 while (cur != NULL) { | |
| 13505 tmp = xmlSchemaNewWildcardNsConstraint(ctxt); | |
| 13506 if (tmp == NULL) | |
| 13507 return(-1); | |
| 13508 tmp->value = cur->value; | |
| 13509 if (last == NULL) | |
| 13510 dest->nsSet = tmp; | |
| 13511 else | |
| 13512 last->next = tmp; | |
| 13513 last = tmp; | |
| 13514 cur = cur->next; | |
| 13515 } | |
| 13516 if (dest->negNsSet != NULL) | |
| 13517 xmlSchemaFreeWildcardNsSet(dest->negNsSet); | |
| 13518 if (source->negNsSet != NULL) { | |
| 13519 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); | |
| 13520 if (dest->negNsSet == NULL) | |
| 13521 return(-1); | |
| 13522 dest->negNsSet->value = source->negNsSet->value; | |
| 13523 } else | |
| 13524 dest->negNsSet = NULL; | |
| 13525 return(0); | |
| 13526 } | |
| 13527 | |
| 13528 /** | |
| 13529 * xmlSchemaUnionWildcards: | |
| 13530 * @ctxt: the schema parser context | |
| 13531 * @completeWild: the first wildcard | |
| 13532 * @curWild: the second wildcard | |
| 13533 * | |
| 13534 * Unions the namespace constraints of the given wildcards. | |
| 13535 * @completeWild will hold the resulting union. | |
| 13536 * Returns a positive error code on failure, -1 in case of an | |
| 13537 * internal error, 0 otherwise. | |
| 13538 */ | |
| 13539 static int | |
| 13540 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt, | |
| 13541 xmlSchemaWildcardPtr completeWild, | |
| 13542 xmlSchemaWildcardPtr curWild) | |
| 13543 { | |
| 13544 xmlSchemaWildcardNsPtr cur, curB, tmp; | |
| 13545 | |
| 13546 /* | |
| 13547 * 1 If O1 and O2 are the same value, then that value must be the | |
| 13548 * value. | |
| 13549 */ | |
| 13550 if ((completeWild->any == curWild->any) && | |
| 13551 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) && | |
| 13552 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) { | |
| 13553 | |
| 13554 if ((completeWild->negNsSet == NULL) || | |
| 13555 (completeWild->negNsSet->value == curWild->negNsSet->value)) { | |
| 13556 | |
| 13557 if (completeWild->nsSet != NULL) { | |
| 13558 int found = 0; | |
| 13559 | |
| 13560 /* | |
| 13561 * Check equality of sets. | |
| 13562 */ | |
| 13563 cur = completeWild->nsSet; | |
| 13564 while (cur != NULL) { | |
| 13565 found = 0; | |
| 13566 curB = curWild->nsSet; | |
| 13567 while (curB != NULL) { | |
| 13568 if (cur->value == curB->value) { | |
| 13569 found = 1; | |
| 13570 break; | |
| 13571 } | |
| 13572 curB = curB->next; | |
| 13573 } | |
| 13574 if (!found) | |
| 13575 break; | |
| 13576 cur = cur->next; | |
| 13577 } | |
| 13578 if (found) | |
| 13579 return(0); | |
| 13580 } else | |
| 13581 return(0); | |
| 13582 } | |
| 13583 } | |
| 13584 /* | |
| 13585 * 2 If either O1 or O2 is any, then any must be the value | |
| 13586 */ | |
| 13587 if (completeWild->any != curWild->any) { | |
| 13588 if (completeWild->any == 0) { | |
| 13589 completeWild->any = 1; | |
| 13590 if (completeWild->nsSet != NULL) { | |
| 13591 xmlSchemaFreeWildcardNsSet(completeWild->nsSet); | |
| 13592 completeWild->nsSet = NULL; | |
| 13593 } | |
| 13594 if (completeWild->negNsSet != NULL) { | |
| 13595 xmlFree(completeWild->negNsSet); | |
| 13596 completeWild->negNsSet = NULL; | |
| 13597 } | |
| 13598 } | |
| 13599 return (0); | |
| 13600 } | |
| 13601 /* | |
| 13602 * 3 If both O1 and O2 are sets of (namespace names or `absent`), | |
| 13603 * then the union of those sets must be the value. | |
| 13604 */ | |
| 13605 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) { | |
| 13606 int found; | |
| 13607 xmlSchemaWildcardNsPtr start; | |
| 13608 | |
| 13609 cur = curWild->nsSet; | |
| 13610 start = completeWild->nsSet; | |
| 13611 while (cur != NULL) { | |
| 13612 found = 0; | |
| 13613 curB = start; | |
| 13614 while (curB != NULL) { | |
| 13615 if (cur->value == curB->value) { | |
| 13616 found = 1; | |
| 13617 break; | |
| 13618 } | |
| 13619 curB = curB->next; | |
| 13620 } | |
| 13621 if (!found) { | |
| 13622 tmp = xmlSchemaNewWildcardNsConstraint(ctxt); | |
| 13623 if (tmp == NULL) | |
| 13624 return (-1); | |
| 13625 tmp->value = cur->value; | |
| 13626 tmp->next = completeWild->nsSet; | |
| 13627 completeWild->nsSet = tmp; | |
| 13628 } | |
| 13629 cur = cur->next; | |
| 13630 } | |
| 13631 | |
| 13632 return(0); | |
| 13633 } | |
| 13634 /* | |
| 13635 * 4 If the two are negations of different values (namespace names | |
| 13636 * or `absent`), then a pair of not and `absent` must be the value. | |
| 13637 */ | |
| 13638 if ((completeWild->negNsSet != NULL) && | |
| 13639 (curWild->negNsSet != NULL) && | |
| 13640 (completeWild->negNsSet->value != curWild->negNsSet->value)) { | |
| 13641 completeWild->negNsSet->value = NULL; | |
| 13642 | |
| 13643 return(0); | |
| 13644 } | |
| 13645 /* | |
| 13646 * 5. | |
| 13647 */ | |
| 13648 if (((completeWild->negNsSet != NULL) && | |
| 13649 (completeWild->negNsSet->value != NULL) && | |
| 13650 (curWild->nsSet != NULL)) || | |
| 13651 ((curWild->negNsSet != NULL) && | |
| 13652 (curWild->negNsSet->value != NULL) && | |
| 13653 (completeWild->nsSet != NULL))) { | |
| 13654 | |
| 13655 int nsFound, absentFound = 0; | |
| 13656 | |
| 13657 if (completeWild->nsSet != NULL) { | |
| 13658 cur = completeWild->nsSet; | |
| 13659 curB = curWild->negNsSet; | |
| 13660 } else { | |
| 13661 cur = curWild->nsSet; | |
| 13662 curB = completeWild->negNsSet; | |
| 13663 } | |
| 13664 nsFound = 0; | |
| 13665 while (cur != NULL) { | |
| 13666 if (cur->value == NULL) | |
| 13667 absentFound = 1; | |
| 13668 else if (cur->value == curB->value) | |
| 13669 nsFound = 1; | |
| 13670 if (nsFound && absentFound) | |
| 13671 break; | |
| 13672 cur = cur->next; | |
| 13673 } | |
| 13674 | |
| 13675 if (nsFound && absentFound) { | |
| 13676 /* | |
| 13677 * 5.1 If the set S includes both the negated namespace | |
| 13678 * name and `absent`, then any must be the value. | |
| 13679 */ | |
| 13680 completeWild->any = 1; | |
| 13681 if (completeWild->nsSet != NULL) { | |
| 13682 xmlSchemaFreeWildcardNsSet(completeWild->nsSet); | |
| 13683 completeWild->nsSet = NULL; | |
| 13684 } | |
| 13685 if (completeWild->negNsSet != NULL) { | |
| 13686 xmlFree(completeWild->negNsSet); | |
| 13687 completeWild->negNsSet = NULL; | |
| 13688 } | |
| 13689 } else if (nsFound && (!absentFound)) { | |
| 13690 /* | |
| 13691 * 5.2 If the set S includes the negated namespace name | |
| 13692 * but not `absent`, then a pair of not and `absent` must | |
| 13693 * be the value. | |
| 13694 */ | |
| 13695 if (completeWild->nsSet != NULL) { | |
| 13696 xmlSchemaFreeWildcardNsSet(completeWild->nsSet); | |
| 13697 completeWild->nsSet = NULL; | |
| 13698 } | |
| 13699 if (completeWild->negNsSet == NULL) { | |
| 13700 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); | |
| 13701 if (completeWild->negNsSet == NULL) | |
| 13702 return (-1); | |
| 13703 } | |
| 13704 completeWild->negNsSet->value = NULL; | |
| 13705 } else if ((!nsFound) && absentFound) { | |
| 13706 /* | |
| 13707 * 5.3 If the set S includes `absent` but not the negated | |
| 13708 * namespace name, then the union is not expressible. | |
| 13709 */ | |
| 13710 xmlSchemaPErr(ctxt, completeWild->node, | |
| 13711 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE, | |
| 13712 "The union of the wilcard is not expressible.\n", | |
| 13713 NULL, NULL); | |
| 13714 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE); | |
| 13715 } else if ((!nsFound) && (!absentFound)) { | |
| 13716 /* | |
| 13717 * 5.4 If the set S does not include either the negated namespace | |
| 13718 * name or `absent`, then whichever of O1 or O2 is a pair of not | |
| 13719 * and a namespace name must be the value. | |
| 13720 */ | |
| 13721 if (completeWild->negNsSet == NULL) { | |
| 13722 if (completeWild->nsSet != NULL) { | |
| 13723 xmlSchemaFreeWildcardNsSet(completeWild->nsSet); | |
| 13724 completeWild->nsSet = NULL; | |
| 13725 } | |
| 13726 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); | |
| 13727 if (completeWild->negNsSet == NULL) | |
| 13728 return (-1); | |
| 13729 completeWild->negNsSet->value = curWild->negNsSet->value; | |
| 13730 } | |
| 13731 } | |
| 13732 return (0); | |
| 13733 } | |
| 13734 /* | |
| 13735 * 6. | |
| 13736 */ | |
| 13737 if (((completeWild->negNsSet != NULL) && | |
| 13738 (completeWild->negNsSet->value == NULL) && | |
| 13739 (curWild->nsSet != NULL)) || | |
| 13740 ((curWild->negNsSet != NULL) && | |
| 13741 (curWild->negNsSet->value == NULL) && | |
| 13742 (completeWild->nsSet != NULL))) { | |
| 13743 | |
| 13744 if (completeWild->nsSet != NULL) { | |
| 13745 cur = completeWild->nsSet; | |
| 13746 } else { | |
| 13747 cur = curWild->nsSet; | |
| 13748 } | |
| 13749 while (cur != NULL) { | |
| 13750 if (cur->value == NULL) { | |
| 13751 /* | |
| 13752 * 6.1 If the set S includes `absent`, then any must be the | |
| 13753 * value. | |
| 13754 */ | |
| 13755 completeWild->any = 1; | |
| 13756 if (completeWild->nsSet != NULL) { | |
| 13757 xmlSchemaFreeWildcardNsSet(completeWild->nsSet); | |
| 13758 completeWild->nsSet = NULL; | |
| 13759 } | |
| 13760 if (completeWild->negNsSet != NULL) { | |
| 13761 xmlFree(completeWild->negNsSet); | |
| 13762 completeWild->negNsSet = NULL; | |
| 13763 } | |
| 13764 return (0); | |
| 13765 } | |
| 13766 cur = cur->next; | |
| 13767 } | |
| 13768 if (completeWild->negNsSet == NULL) { | |
| 13769 /* | |
| 13770 * 6.2 If the set S does not include `absent`, then a pair of not | |
| 13771 * and `absent` must be the value. | |
| 13772 */ | |
| 13773 if (completeWild->nsSet != NULL) { | |
| 13774 xmlSchemaFreeWildcardNsSet(completeWild->nsSet); | |
| 13775 completeWild->nsSet = NULL; | |
| 13776 } | |
| 13777 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); | |
| 13778 if (completeWild->negNsSet == NULL) | |
| 13779 return (-1); | |
| 13780 completeWild->negNsSet->value = NULL; | |
| 13781 } | |
| 13782 return (0); | |
| 13783 } | |
| 13784 return (0); | |
| 13785 | |
| 13786 } | |
| 13787 | |
| 13788 /** | |
| 13789 * xmlSchemaIntersectWildcards: | |
| 13790 * @ctxt: the schema parser context | |
| 13791 * @completeWild: the first wildcard | |
| 13792 * @curWild: the second wildcard | |
| 13793 * | |
| 13794 * Intersects the namespace constraints of the given wildcards. | |
| 13795 * @completeWild will hold the resulting intersection. | |
| 13796 * Returns a positive error code on failure, -1 in case of an | |
| 13797 * internal error, 0 otherwise. | |
| 13798 */ | |
| 13799 static int | |
| 13800 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt, | |
| 13801 xmlSchemaWildcardPtr completeWild, | |
| 13802 xmlSchemaWildcardPtr curWild) | |
| 13803 { | |
| 13804 xmlSchemaWildcardNsPtr cur, curB, prev, tmp; | |
| 13805 | |
| 13806 /* | |
| 13807 * 1 If O1 and O2 are the same value, then that value must be the | |
| 13808 * value. | |
| 13809 */ | |
| 13810 if ((completeWild->any == curWild->any) && | |
| 13811 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) && | |
| 13812 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) { | |
| 13813 | |
| 13814 if ((completeWild->negNsSet == NULL) || | |
| 13815 (completeWild->negNsSet->value == curWild->negNsSet->value)) { | |
| 13816 | |
| 13817 if (completeWild->nsSet != NULL) { | |
| 13818 int found = 0; | |
| 13819 | |
| 13820 /* | |
| 13821 * Check equality of sets. | |
| 13822 */ | |
| 13823 cur = completeWild->nsSet; | |
| 13824 while (cur != NULL) { | |
| 13825 found = 0; | |
| 13826 curB = curWild->nsSet; | |
| 13827 while (curB != NULL) { | |
| 13828 if (cur->value == curB->value) { | |
| 13829 found = 1; | |
| 13830 break; | |
| 13831 } | |
| 13832 curB = curB->next; | |
| 13833 } | |
| 13834 if (!found) | |
| 13835 break; | |
| 13836 cur = cur->next; | |
| 13837 } | |
| 13838 if (found) | |
| 13839 return(0); | |
| 13840 } else | |
| 13841 return(0); | |
| 13842 } | |
| 13843 } | |
| 13844 /* | |
| 13845 * 2 If either O1 or O2 is any, then the other must be the value. | |
| 13846 */ | |
| 13847 if ((completeWild->any != curWild->any) && (completeWild->any)) { | |
| 13848 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) ==
-1) | |
| 13849 return(-1); | |
| 13850 return(0); | |
| 13851 } | |
| 13852 /* | |
| 13853 * 3 If either O1 or O2 is a pair of not and a value (a namespace | |
| 13854 * name or `absent`) and the other is a set of (namespace names or | |
| 13855 * `absent`), then that set, minus the negated value if it was in | |
| 13856 * the set, minus `absent` if it was in the set, must be the value. | |
| 13857 */ | |
| 13858 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) || | |
| 13859 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) { | |
| 13860 const xmlChar *neg; | |
| 13861 | |
| 13862 if (completeWild->nsSet == NULL) { | |
| 13863 neg = completeWild->negNsSet->value; | |
| 13864 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild)
== -1) | |
| 13865 return(-1); | |
| 13866 } else | |
| 13867 neg = curWild->negNsSet->value; | |
| 13868 /* | |
| 13869 * Remove absent and negated. | |
| 13870 */ | |
| 13871 prev = NULL; | |
| 13872 cur = completeWild->nsSet; | |
| 13873 while (cur != NULL) { | |
| 13874 if (cur->value == NULL) { | |
| 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 if (neg != NULL) { | |
| 13886 prev = NULL; | |
| 13887 cur = completeWild->nsSet; | |
| 13888 while (cur != NULL) { | |
| 13889 if (cur->value == neg) { | |
| 13890 if (prev == NULL) | |
| 13891 completeWild->nsSet = cur->next; | |
| 13892 else | |
| 13893 prev->next = cur->next; | |
| 13894 xmlFree(cur); | |
| 13895 break; | |
| 13896 } | |
| 13897 prev = cur; | |
| 13898 cur = cur->next; | |
| 13899 } | |
| 13900 } | |
| 13901 | |
| 13902 return(0); | |
| 13903 } | |
| 13904 /* | |
| 13905 * 4 If both O1 and O2 are sets of (namespace names or `absent`), | |
| 13906 * then the intersection of those sets must be the value. | |
| 13907 */ | |
| 13908 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) { | |
| 13909 int found; | |
| 13910 | |
| 13911 cur = completeWild->nsSet; | |
| 13912 prev = NULL; | |
| 13913 while (cur != NULL) { | |
| 13914 found = 0; | |
| 13915 curB = curWild->nsSet; | |
| 13916 while (curB != NULL) { | |
| 13917 if (cur->value == curB->value) { | |
| 13918 found = 1; | |
| 13919 break; | |
| 13920 } | |
| 13921 curB = curB->next; | |
| 13922 } | |
| 13923 if (!found) { | |
| 13924 if (prev == NULL) | |
| 13925 completeWild->nsSet = cur->next; | |
| 13926 else | |
| 13927 prev->next = cur->next; | |
| 13928 tmp = cur->next; | |
| 13929 xmlFree(cur); | |
| 13930 cur = tmp; | |
| 13931 continue; | |
| 13932 } | |
| 13933 prev = cur; | |
| 13934 cur = cur->next; | |
| 13935 } | |
| 13936 | |
| 13937 return(0); | |
| 13938 } | |
| 13939 /* 5 If the two are negations of different namespace names, | |
| 13940 * then the intersection is not expressible | |
| 13941 */ | |
| 13942 if ((completeWild->negNsSet != NULL) && | |
| 13943 (curWild->negNsSet != NULL) && | |
| 13944 (completeWild->negNsSet->value != curWild->negNsSet->value) && | |
| 13945 (completeWild->negNsSet->value != NULL) && | |
| 13946 (curWild->negNsSet->value != NULL)) { | |
| 13947 | |
| 13948 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXP
RESSIBLE, | |
| 13949 "The intersection of the wilcard is not expressible.\n", | |
| 13950 NULL, NULL); | |
| 13951 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE); | |
| 13952 } | |
| 13953 /* | |
| 13954 * 6 If the one is a negation of a namespace name and the other | |
| 13955 * is a negation of `absent`, then the one which is the negation | |
| 13956 * of a namespace name must be the value. | |
| 13957 */ | |
| 13958 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) && | |
| 13959 (completeWild->negNsSet->value != curWild->negNsSet->value) && | |
| 13960 (completeWild->negNsSet->value == NULL)) { | |
| 13961 completeWild->negNsSet->value = curWild->negNsSet->value; | |
| 13962 } | |
| 13963 return(0); | |
| 13964 } | |
| 13965 | |
| 13966 /** | |
| 13967 * xmlSchemaIsWildcardNsConstraintSubset: | |
| 13968 * @ctxt: the schema parser context | |
| 13969 * @sub: the first wildcard | |
| 13970 * @super: the second wildcard | |
| 13971 * | |
| 13972 * Schema Component Constraint: Wildcard Subset (cos-ns-subset) | |
| 13973 * | |
| 13974 * Returns 0 if the namespace constraint of @sub is an intensional | |
| 13975 * subset of @super, 1 otherwise. | |
| 13976 */ | |
| 13977 static int | |
| 13978 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub, | |
| 13979 xmlSchemaWildcardPtr super) | |
| 13980 { | |
| 13981 /* | |
| 13982 * 1 super must be any. | |
| 13983 */ | |
| 13984 if (super->any) | |
| 13985 return (0); | |
| 13986 /* | |
| 13987 * 2.1 sub must be a pair of not and a namespace name or `absent`. | |
| 13988 * 2.2 super must be a pair of not and the same value. | |
| 13989 */ | |
| 13990 if ((sub->negNsSet != NULL) && | |
| 13991 (super->negNsSet != NULL) && | |
| 13992 (sub->negNsSet->value == super->negNsSet->value)) | |
| 13993 return (0); | |
| 13994 /* | |
| 13995 * 3.1 sub must be a set whose members are either namespace names or `absent`
. | |
| 13996 */ | |
| 13997 if (sub->nsSet != NULL) { | |
| 13998 /* | |
| 13999 * 3.2.1 super must be the same set or a superset thereof. | |
| 14000 */ | |
| 14001 if (super->nsSet != NULL) { | |
| 14002 xmlSchemaWildcardNsPtr cur, curB; | |
| 14003 int found = 0; | |
| 14004 | |
| 14005 cur = sub->nsSet; | |
| 14006 while (cur != NULL) { | |
| 14007 found = 0; | |
| 14008 curB = super->nsSet; | |
| 14009 while (curB != NULL) { | |
| 14010 if (cur->value == curB->value) { | |
| 14011 found = 1; | |
| 14012 break; | |
| 14013 } | |
| 14014 curB = curB->next; | |
| 14015 } | |
| 14016 if (!found) | |
| 14017 return (1); | |
| 14018 cur = cur->next; | |
| 14019 } | |
| 14020 if (found) | |
| 14021 return (0); | |
| 14022 } else if (super->negNsSet != NULL) { | |
| 14023 xmlSchemaWildcardNsPtr cur; | |
| 14024 /* | |
| 14025 * 3.2.2 super must be a pair of not and a namespace name or | |
| 14026 * `absent` and that value must not be in sub's set. | |
| 14027 */ | |
| 14028 cur = sub->nsSet; | |
| 14029 while (cur != NULL) { | |
| 14030 if (cur->value == super->negNsSet->value) | |
| 14031 return (1); | |
| 14032 cur = cur->next; | |
| 14033 } | |
| 14034 return (0); | |
| 14035 } | |
| 14036 } | |
| 14037 return (1); | |
| 14038 } | |
| 14039 | |
| 14040 static int | |
| 14041 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse, | |
| 14042 int *fixed, | |
| 14043 const xmlChar **value, | |
| 14044 xmlSchemaValPtr *val) | |
| 14045 { | |
| 14046 *fixed = 0; | |
| 14047 *value = NULL; | |
| 14048 if (val != 0) | |
| 14049 *val = NULL; | |
| 14050 | |
| 14051 if (attruse->defValue != NULL) { | |
| 14052 *value = attruse->defValue; | |
| 14053 if (val != NULL) | |
| 14054 *val = attruse->defVal; | |
| 14055 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED) | |
| 14056 *fixed = 1; | |
| 14057 return(1); | |
| 14058 } else if ((attruse->attrDecl != NULL) && | |
| 14059 (attruse->attrDecl->defValue != NULL)) { | |
| 14060 *value = attruse->attrDecl->defValue; | |
| 14061 if (val != NULL) | |
| 14062 *val = attruse->attrDecl->defVal; | |
| 14063 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED) | |
| 14064 *fixed = 1; | |
| 14065 return(1); | |
| 14066 } | |
| 14067 return(0); | |
| 14068 } | |
| 14069 /** | |
| 14070 * xmlSchemaCheckCVCWildcardNamespace: | |
| 14071 * @wild: the wildcard | |
| 14072 * @ns: the namespace | |
| 14073 * | |
| 14074 * Validation Rule: Wildcard allows Namespace Name | |
| 14075 * (cvc-wildcard-namespace) | |
| 14076 * | |
| 14077 * Returns 0 if the given namespace matches the wildcard, | |
| 14078 * 1 otherwise and -1 on API errors. | |
| 14079 */ | |
| 14080 static int | |
| 14081 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild, | |
| 14082 const xmlChar* ns) | |
| 14083 { | |
| 14084 if (wild == NULL) | |
| 14085 return(-1); | |
| 14086 | |
| 14087 if (wild->any) | |
| 14088 return(0); | |
| 14089 else if (wild->nsSet != NULL) { | |
| 14090 xmlSchemaWildcardNsPtr cur; | |
| 14091 | |
| 14092 cur = wild->nsSet; | |
| 14093 while (cur != NULL) { | |
| 14094 if (xmlStrEqual(cur->value, ns)) | |
| 14095 return(0); | |
| 14096 cur = cur->next; | |
| 14097 } | |
| 14098 } else if ((wild->negNsSet != NULL) && (ns != NULL) && | |
| 14099 (!xmlStrEqual(wild->negNsSet->value, ns))) | |
| 14100 return(0); | |
| 14101 | |
| 14102 return(1); | |
| 14103 } | |
| 14104 | |
| 14105 #define XML_SCHEMA_ACTION_DERIVE 0 | |
| 14106 #define XML_SCHEMA_ACTION_REDEFINE 1 | |
| 14107 | |
| 14108 #define WXS_ACTION_STR(a) \ | |
| 14109 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *)
"redefined" | |
| 14110 | |
| 14111 /* | |
| 14112 * Schema Component Constraint: | |
| 14113 * Derivation Valid (Restriction, Complex) | |
| 14114 * derivation-ok-restriction (2) - (4) | |
| 14115 * | |
| 14116 * ATTENTION: | |
| 14117 * In XML Schema 1.1 this will be: | |
| 14118 * Validation Rule: | |
| 14119 * Checking complex type subsumption (practicalSubsumption) (1, 2 and 3) | |
| 14120 * | |
| 14121 */ | |
| 14122 static int | |
| 14123 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt, | |
| 14124 int action, | |
| 14125 xmlSchemaBasicItemPtr item, | |
| 14126 xmlSchemaBasicItemPtr baseItem, | |
| 14127 xmlSchemaItemListPtr uses, | |
| 14128 xmlSchemaItemListPtr baseUses, | |
| 14129 xmlSchemaWildcardPtr wild, | |
| 14130 xmlSchemaWildcardPtr baseWild) | |
| 14131 { | |
| 14132 xmlSchemaAttributeUsePtr cur = NULL, bcur; | |
| 14133 int i, j, found; /* err = 0; */ | |
| 14134 const xmlChar *bEffValue; | |
| 14135 int effFixed; | |
| 14136 | |
| 14137 if (uses != NULL) { | |
| 14138 for (i = 0; i < uses->nbItems; i++) { | |
| 14139 cur = uses->items[i]; | |
| 14140 found = 0; | |
| 14141 if (baseUses == NULL) | |
| 14142 goto not_found; | |
| 14143 for (j = 0; j < baseUses->nbItems; j++) { | |
| 14144 bcur = baseUses->items[j]; | |
| 14145 if ((WXS_ATTRUSE_DECL_NAME(cur) == | |
| 14146 WXS_ATTRUSE_DECL_NAME(bcur)) && | |
| 14147 (WXS_ATTRUSE_DECL_TNS(cur) == | |
| 14148 WXS_ATTRUSE_DECL_TNS(bcur))) | |
| 14149 { | |
| 14150 /* | |
| 14151 * (2.1) "If there is an attribute use in the {attribute | |
| 14152 * uses} of the {base type definition} (call this B) whose | |
| 14153 * {attribute declaration} has the same {name} and {target | |
| 14154 * namespace}, then all of the following must be true:" | |
| 14155 */ | |
| 14156 found = 1; | |
| 14157 | |
| 14158 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) && | |
| 14159 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) | |
| 14160 { | |
| 14161 xmlChar *str = NULL; | |
| 14162 /* | |
| 14163 * (2.1.1) "one of the following must be true:" | |
| 14164 * (2.1.1.1) "B's {required} is false." | |
| 14165 * (2.1.1.2) "R's {required} is true." | |
| 14166 */ | |
| 14167 xmlSchemaPAttrUseErr4(pctxt, | |
| 14168 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1, | |
| 14169 WXS_ITEM_NODE(item), item, cur, | |
| 14170 "The 'optional' attribute use is inconsistent " | |
| 14171 "with the corresponding 'required' attribute use of
" | |
| 14172 "the %s %s", | |
| 14173 WXS_ACTION_STR(action), | |
| 14174 xmlSchemaGetComponentDesignation(&str, baseItem), | |
| 14175 NULL, NULL); | |
| 14176 FREE_AND_NULL(str); | |
| 14177 /* err = pctxt->err; */ | |
| 14178 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, | |
| 14179 WXS_ATTRUSE_TYPEDEF(cur), | |
| 14180 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0) | |
| 14181 { | |
| 14182 xmlChar *strA = NULL, *strB = NULL, *strC = NULL; | |
| 14183 | |
| 14184 /* | |
| 14185 * SPEC (2.1.2) "R's {attribute declaration}'s | |
| 14186 * {type definition} must be validly derived from | |
| 14187 * B's {type definition} given the empty set as | |
| 14188 * defined in Type Derivation OK (Simple) ($3.14.6)." | |
| 14189 */ | |
| 14190 xmlSchemaPAttrUseErr4(pctxt, | |
| 14191 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2, | |
| 14192 WXS_ITEM_NODE(item), item, cur, | |
| 14193 "The attribute declaration's %s " | |
| 14194 "is not validly derived from " | |
| 14195 "the corresponding %s of the " | |
| 14196 "attribute declaration in the %s %s", | |
| 14197 xmlSchemaGetComponentDesignation(&strA, | |
| 14198 WXS_ATTRUSE_TYPEDEF(cur)), | |
| 14199 xmlSchemaGetComponentDesignation(&strB, | |
| 14200 WXS_ATTRUSE_TYPEDEF(bcur)), | |
| 14201 WXS_ACTION_STR(action), | |
| 14202 xmlSchemaGetComponentDesignation(&strC, baseItem)); | |
| 14203 /* xmlSchemaGetComponentDesignation(&str, baseItem),
*/ | |
| 14204 FREE_AND_NULL(strA); | |
| 14205 FREE_AND_NULL(strB); | |
| 14206 FREE_AND_NULL(strC); | |
| 14207 /* err = pctxt->err; */ | |
| 14208 } else { | |
| 14209 /* | |
| 14210 * 2.1.3 [Definition:] Let the effective value | |
| 14211 * constraint of an attribute use be its {value | |
| 14212 * constraint}, if present, otherwise its {attribute | |
| 14213 * declaration}'s {value constraint} . | |
| 14214 */ | |
| 14215 xmlSchemaGetEffectiveValueConstraint(bcur, | |
| 14216 &effFixed, &bEffValue, NULL); | |
| 14217 /* | |
| 14218 * 2.1.3 ... one of the following must be true | |
| 14219 * | |
| 14220 * 2.1.3.1 B's `effective value constraint` is | |
| 14221 * `absent` or default. | |
| 14222 */ | |
| 14223 if ((bEffValue != NULL) && | |
| 14224 (effFixed == 1)) { | |
| 14225 const xmlChar *rEffValue = NULL; | |
| 14226 | |
| 14227 xmlSchemaGetEffectiveValueConstraint(bcur, | |
| 14228 &effFixed, &rEffValue, NULL); | |
| 14229 /* | |
| 14230 * 2.1.3.2 R's `effective value constraint` is | |
| 14231 * fixed with the same string as B's. | |
| 14232 * MAYBE TODO: Compare the computed values. | |
| 14233 * Hmm, it says "same string" so | |
| 14234 * string-equality might really be sufficient. | |
| 14235 */ | |
| 14236 if ((effFixed == 0) || | |
| 14237 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValu
e))) | |
| 14238 { | |
| 14239 xmlChar *str = NULL; | |
| 14240 | |
| 14241 xmlSchemaPAttrUseErr4(pctxt, | |
| 14242 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3, | |
| 14243 WXS_ITEM_NODE(item), item, cur, | |
| 14244 "The effective value constraint of the " | |
| 14245 "attribute use is inconsistent with " | |
| 14246 "its correspondent in the %s %s", | |
| 14247 WXS_ACTION_STR(action), | |
| 14248 xmlSchemaGetComponentDesignation(&str, | |
| 14249 baseItem), | |
| 14250 NULL, NULL); | |
| 14251 FREE_AND_NULL(str); | |
| 14252 /* err = pctxt->err; */ | |
| 14253 } | |
| 14254 } | |
| 14255 } | |
| 14256 break; | |
| 14257 } | |
| 14258 } | |
| 14259 not_found: | |
| 14260 if (!found) { | |
| 14261 /* | |
| 14262 * (2.2) "otherwise the {base type definition} must have an | |
| 14263 * {attribute wildcard} and the {target namespace} of the | |
| 14264 * R's {attribute declaration} must be `valid` with respect | |
| 14265 * to that wildcard, as defined in Wildcard allows Namespace | |
| 14266 * Name ($3.10.4)." | |
| 14267 */ | |
| 14268 if ((baseWild == NULL) || | |
| 14269 (xmlSchemaCheckCVCWildcardNamespace(baseWild, | |
| 14270 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0)) | |
| 14271 { | |
| 14272 xmlChar *str = NULL; | |
| 14273 | |
| 14274 xmlSchemaPAttrUseErr4(pctxt, | |
| 14275 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2, | |
| 14276 WXS_ITEM_NODE(item), item, cur, | |
| 14277 "Neither a matching attribute use, " | |
| 14278 "nor a matching wildcard exists in the %s %s", | |
| 14279 WXS_ACTION_STR(action), | |
| 14280 xmlSchemaGetComponentDesignation(&str, baseItem), | |
| 14281 NULL, NULL); | |
| 14282 FREE_AND_NULL(str); | |
| 14283 /* err = pctxt->err; */ | |
| 14284 } | |
| 14285 } | |
| 14286 } | |
| 14287 } | |
| 14288 /* | |
| 14289 * SPEC derivation-ok-restriction (3): | |
| 14290 * (3) "For each attribute use in the {attribute uses} of the {base type | |
| 14291 * definition} whose {required} is true, there must be an attribute | |
| 14292 * use with an {attribute declaration} with the same {name} and | |
| 14293 * {target namespace} as its {attribute declaration} in the {attribute | |
| 14294 * uses} of the complex type definition itself whose {required} is true. | |
| 14295 */ | |
| 14296 if (baseUses != NULL) { | |
| 14297 for (j = 0; j < baseUses->nbItems; j++) { | |
| 14298 bcur = baseUses->items[j]; | |
| 14299 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED) | |
| 14300 continue; | |
| 14301 found = 0; | |
| 14302 if (uses != NULL) { | |
| 14303 for (i = 0; i < uses->nbItems; i++) { | |
| 14304 cur = uses->items[i]; | |
| 14305 if ((WXS_ATTRUSE_DECL_NAME(cur) == | |
| 14306 WXS_ATTRUSE_DECL_NAME(bcur)) && | |
| 14307 (WXS_ATTRUSE_DECL_TNS(cur) == | |
| 14308 WXS_ATTRUSE_DECL_TNS(bcur))) { | |
| 14309 found = 1; | |
| 14310 break; | |
| 14311 } | |
| 14312 } | |
| 14313 } | |
| 14314 if (!found) { | |
| 14315 xmlChar *strA = NULL, *strB = NULL; | |
| 14316 | |
| 14317 xmlSchemaCustomErr4(ACTXT_CAST pctxt, | |
| 14318 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3, | |
| 14319 NULL, item, | |
| 14320 "A matching attribute use for the " | |
| 14321 "'required' %s of the %s %s is missing", | |
| 14322 xmlSchemaGetComponentDesignation(&strA, bcur), | |
| 14323 WXS_ACTION_STR(action), | |
| 14324 xmlSchemaGetComponentDesignation(&strB, baseItem), | |
| 14325 NULL); | |
| 14326 FREE_AND_NULL(strA); | |
| 14327 FREE_AND_NULL(strB); | |
| 14328 } | |
| 14329 } | |
| 14330 } | |
| 14331 /* | |
| 14332 * derivation-ok-restriction (4) | |
| 14333 */ | |
| 14334 if (wild != NULL) { | |
| 14335 /* | |
| 14336 * (4) "If there is an {attribute wildcard}, all of the | |
| 14337 * following must be true:" | |
| 14338 */ | |
| 14339 if (baseWild == NULL) { | |
| 14340 xmlChar *str = NULL; | |
| 14341 | |
| 14342 /* | |
| 14343 * (4.1) "The {base type definition} must also have one." | |
| 14344 */ | |
| 14345 xmlSchemaCustomErr4(ACTXT_CAST pctxt, | |
| 14346 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1, | |
| 14347 NULL, item, | |
| 14348 "The %s has an attribute wildcard, " | |
| 14349 "but the %s %s '%s' does not have one", | |
| 14350 WXS_ITEM_TYPE_NAME(item), | |
| 14351 WXS_ACTION_STR(action), | |
| 14352 WXS_ITEM_TYPE_NAME(baseItem), | |
| 14353 xmlSchemaGetComponentQName(&str, baseItem)); | |
| 14354 FREE_AND_NULL(str); | |
| 14355 return(pctxt->err); | |
| 14356 } else if ((baseWild->any == 0) && | |
| 14357 xmlSchemaCheckCOSNSSubset(wild, baseWild)) | |
| 14358 { | |
| 14359 xmlChar *str = NULL; | |
| 14360 /* | |
| 14361 * (4.2) "The complex type definition's {attribute wildcard}'s | |
| 14362 * {namespace constraint} must be a subset of the {base type | |
| 14363 * definition}'s {attribute wildcard}'s {namespace constraint}, | |
| 14364 * as defined by Wildcard Subset ($3.10.6)." | |
| 14365 */ | |
| 14366 xmlSchemaCustomErr4(ACTXT_CAST pctxt, | |
| 14367 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2, | |
| 14368 NULL, item, | |
| 14369 "The attribute wildcard is not a valid " | |
| 14370 "subset of the wildcard in the %s %s '%s'", | |
| 14371 WXS_ACTION_STR(action), | |
| 14372 WXS_ITEM_TYPE_NAME(baseItem), | |
| 14373 xmlSchemaGetComponentQName(&str, baseItem), | |
| 14374 NULL); | |
| 14375 FREE_AND_NULL(str); | |
| 14376 return(pctxt->err); | |
| 14377 } | |
| 14378 /* 4.3 Unless the {base type definition} is the `ur-type | |
| 14379 * definition`, the complex type definition's {attribute | |
| 14380 * wildcard}'s {process contents} must be identical to or | |
| 14381 * stronger than the {base type definition}'s {attribute | |
| 14382 * wildcard}'s {process contents}, where strict is stronger | |
| 14383 * than lax is stronger than skip. | |
| 14384 */ | |
| 14385 if ((! WXS_IS_ANYTYPE(baseItem)) && | |
| 14386 (wild->processContents < baseWild->processContents)) { | |
| 14387 xmlChar *str = NULL; | |
| 14388 xmlSchemaCustomErr4(ACTXT_CAST pctxt, | |
| 14389 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3, | |
| 14390 NULL, baseItem, | |
| 14391 "The {process contents} of the attribute wildcard is " | |
| 14392 "weaker than the one in the %s %s '%s'", | |
| 14393 WXS_ACTION_STR(action), | |
| 14394 WXS_ITEM_TYPE_NAME(baseItem), | |
| 14395 xmlSchemaGetComponentQName(&str, baseItem), | |
| 14396 NULL); | |
| 14397 FREE_AND_NULL(str) | |
| 14398 return(pctxt->err); | |
| 14399 } | |
| 14400 } | |
| 14401 return(0); | |
| 14402 } | |
| 14403 | |
| 14404 | |
| 14405 static int | |
| 14406 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt, | |
| 14407 xmlSchemaBasicItemPtr item, | |
| 14408 xmlSchemaWildcardPtr *completeWild, | |
| 14409 xmlSchemaItemListPtr list, | |
| 14410 xmlSchemaItemListPtr prohibs); | |
| 14411 /** | |
| 14412 * xmlSchemaFixupTypeAttributeUses: | |
| 14413 * @ctxt: the schema parser context | |
| 14414 * @type: the complex type definition | |
| 14415 * | |
| 14416 * | |
| 14417 * Builds the wildcard and the attribute uses on the given complex type. | |
| 14418 * Returns -1 if an internal error occurs, 0 otherwise. | |
| 14419 * | |
| 14420 * ATTENTION TODO: Experimantally this uses pointer comparisons for | |
| 14421 * strings, so recheck this if we start to hardcode some schemata, since | |
| 14422 * they might not be in the same dict. | |
| 14423 * NOTE: It is allowed to "extend" the xs:anyType type. | |
| 14424 */ | |
| 14425 static int | |
| 14426 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt, | |
| 14427 xmlSchemaTypePtr type) | |
| 14428 { | |
| 14429 xmlSchemaTypePtr baseType = NULL; | |
| 14430 xmlSchemaAttributeUsePtr use; | |
| 14431 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL; | |
| 14432 | |
| 14433 if (type->baseType == NULL) { | |
| 14434 PERROR_INT("xmlSchemaFixupTypeAttributeUses", | |
| 14435 "no base type"); | |
| 14436 return (-1); | |
| 14437 } | |
| 14438 baseType = type->baseType; | |
| 14439 if (WXS_IS_TYPE_NOT_FIXED(baseType)) | |
| 14440 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1) | |
| 14441 return(-1); | |
| 14442 | |
| 14443 uses = type->attrUses; | |
| 14444 baseUses = baseType->attrUses; | |
| 14445 /* | |
| 14446 * Expand attribute group references. And build the 'complete' | |
| 14447 * wildcard, i.e. intersect multiple wildcards. | |
| 14448 * Move attribute prohibitions into a separate list. | |
| 14449 */ | |
| 14450 if (uses != NULL) { | |
| 14451 if (WXS_IS_RESTRICTION(type)) { | |
| 14452 /* | |
| 14453 * This one will transfer all attr. prohibitions | |
| 14454 * into pctxt->attrProhibs. | |
| 14455 */ | |
| 14456 if (xmlSchemaExpandAttributeGroupRefs(pctxt, | |
| 14457 WXS_BASIC_CAST type, &(type->attributeWildcard), uses, | |
| 14458 pctxt->attrProhibs) == -1) | |
| 14459 { | |
| 14460 PERROR_INT("xmlSchemaFixupTypeAttributeUses", | |
| 14461 "failed to expand attributes"); | |
| 14462 } | |
| 14463 if (pctxt->attrProhibs->nbItems != 0) | |
| 14464 prohibs = pctxt->attrProhibs; | |
| 14465 } else { | |
| 14466 if (xmlSchemaExpandAttributeGroupRefs(pctxt, | |
| 14467 WXS_BASIC_CAST type, &(type->attributeWildcard), uses, | |
| 14468 NULL) == -1) | |
| 14469 { | |
| 14470 PERROR_INT("xmlSchemaFixupTypeAttributeUses", | |
| 14471 "failed to expand attributes"); | |
| 14472 } | |
| 14473 } | |
| 14474 } | |
| 14475 /* | |
| 14476 * Inherit the attribute uses of the base type. | |
| 14477 */ | |
| 14478 if (baseUses != NULL) { | |
| 14479 int i, j; | |
| 14480 xmlSchemaAttributeUseProhibPtr pro; | |
| 14481 | |
| 14482 if (WXS_IS_RESTRICTION(type)) { | |
| 14483 int usesCount; | |
| 14484 xmlSchemaAttributeUsePtr tmp; | |
| 14485 | |
| 14486 if (uses != NULL) | |
| 14487 usesCount = uses->nbItems; | |
| 14488 else | |
| 14489 usesCount = 0; | |
| 14490 | |
| 14491 /* Restriction. */ | |
| 14492 for (i = 0; i < baseUses->nbItems; i++) { | |
| 14493 use = baseUses->items[i]; | |
| 14494 if (prohibs) { | |
| 14495 /* | |
| 14496 * Filter out prohibited uses. | |
| 14497 */ | |
| 14498 for (j = 0; j < prohibs->nbItems; j++) { | |
| 14499 pro = prohibs->items[j]; | |
| 14500 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) && | |
| 14501 (WXS_ATTRUSE_DECL_TNS(use) == | |
| 14502 pro->targetNamespace)) | |
| 14503 { | |
| 14504 goto inherit_next; | |
| 14505 } | |
| 14506 } | |
| 14507 } | |
| 14508 if (usesCount) { | |
| 14509 /* | |
| 14510 * Filter out existing uses. | |
| 14511 */ | |
| 14512 for (j = 0; j < usesCount; j++) { | |
| 14513 tmp = uses->items[j]; | |
| 14514 if ((WXS_ATTRUSE_DECL_NAME(use) == | |
| 14515 WXS_ATTRUSE_DECL_NAME(tmp)) && | |
| 14516 (WXS_ATTRUSE_DECL_TNS(use) == | |
| 14517 WXS_ATTRUSE_DECL_TNS(tmp))) | |
| 14518 { | |
| 14519 goto inherit_next; | |
| 14520 } | |
| 14521 } | |
| 14522 } | |
| 14523 if (uses == NULL) { | |
| 14524 type->attrUses = xmlSchemaItemListCreate(); | |
| 14525 if (type->attrUses == NULL) | |
| 14526 goto exit_failure; | |
| 14527 uses = type->attrUses; | |
| 14528 } | |
| 14529 xmlSchemaItemListAddSize(uses, 2, use); | |
| 14530 inherit_next: {} | |
| 14531 } | |
| 14532 } else { | |
| 14533 /* Extension. */ | |
| 14534 for (i = 0; i < baseUses->nbItems; i++) { | |
| 14535 use = baseUses->items[i]; | |
| 14536 if (uses == NULL) { | |
| 14537 type->attrUses = xmlSchemaItemListCreate(); | |
| 14538 if (type->attrUses == NULL) | |
| 14539 goto exit_failure; | |
| 14540 uses = type->attrUses; | |
| 14541 } | |
| 14542 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use); | |
| 14543 } | |
| 14544 } | |
| 14545 } | |
| 14546 /* | |
| 14547 * Shrink attr. uses. | |
| 14548 */ | |
| 14549 if (uses) { | |
| 14550 if (uses->nbItems == 0) { | |
| 14551 xmlSchemaItemListFree(uses); | |
| 14552 type->attrUses = NULL; | |
| 14553 } | |
| 14554 /* | |
| 14555 * TODO: We could shrink the size of the array | |
| 14556 * to fit the actual number of items. | |
| 14557 */ | |
| 14558 } | |
| 14559 /* | |
| 14560 * Compute the complete wildcard. | |
| 14561 */ | |
| 14562 if (WXS_IS_EXTENSION(type)) { | |
| 14563 if (baseType->attributeWildcard != NULL) { | |
| 14564 /* | |
| 14565 * (3.2.2.1) "If the `base wildcard` is non-`absent`, then | |
| 14566 * the appropriate case among the following:" | |
| 14567 */ | |
| 14568 if (type->attributeWildcard != NULL) { | |
| 14569 /* | |
| 14570 * Union the complete wildcard with the base wildcard. | |
| 14571 * SPEC {attribute wildcard} | |
| 14572 * (3.2.2.1.2) "otherwise a wildcard whose {process contents} | |
| 14573 * and {annotation} are those of the `complete wildcard`, | |
| 14574 * and whose {namespace constraint} is the intensional union | |
| 14575 * of the {namespace constraint} of the `complete wildcard` | |
| 14576 * and of the `base wildcard`, as defined in Attribute | |
| 14577 * Wildcard Union ($3.10.6)." | |
| 14578 */ | |
| 14579 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard, | |
| 14580 baseType->attributeWildcard) == -1) | |
| 14581 goto exit_failure; | |
| 14582 } else { | |
| 14583 /* | |
| 14584 * (3.2.2.1.1) "If the `complete wildcard` is `absent`, | |
| 14585 * then the `base wildcard`." | |
| 14586 */ | |
| 14587 type->attributeWildcard = baseType->attributeWildcard; | |
| 14588 } | |
| 14589 } else { | |
| 14590 /* | |
| 14591 * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the | |
| 14592 * `complete wildcard`" | |
| 14593 * NOOP | |
| 14594 */ | |
| 14595 } | |
| 14596 } else { | |
| 14597 /* | |
| 14598 * SPEC {attribute wildcard} | |
| 14599 * (3.1) "If the <restriction> alternative is chosen, then the | |
| 14600 * `complete wildcard`;" | |
| 14601 * NOOP | |
| 14602 */ | |
| 14603 } | |
| 14604 | |
| 14605 return (0); | |
| 14606 | |
| 14607 exit_failure: | |
| 14608 return(-1); | |
| 14609 } | |
| 14610 | |
| 14611 /** | |
| 14612 * xmlSchemaTypeFinalContains: | |
| 14613 * @schema: the schema | |
| 14614 * @type: the type definition | |
| 14615 * @final: the final | |
| 14616 * | |
| 14617 * Evaluates if a type definition contains the given "final". | |
| 14618 * This does take "finalDefault" into account as well. | |
| 14619 * | |
| 14620 * Returns 1 if the type does containt the given "final", | |
| 14621 * 0 otherwise. | |
| 14622 */ | |
| 14623 static int | |
| 14624 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final) | |
| 14625 { | |
| 14626 if (type == NULL) | |
| 14627 return (0); | |
| 14628 if (type->flags & final) | |
| 14629 return (1); | |
| 14630 else | |
| 14631 return (0); | |
| 14632 } | |
| 14633 | |
| 14634 /** | |
| 14635 * xmlSchemaGetUnionSimpleTypeMemberTypes: | |
| 14636 * @type: the Union Simple Type | |
| 14637 * | |
| 14638 * Returns a list of member types of @type if existing, | |
| 14639 * returns NULL otherwise. | |
| 14640 */ | |
| 14641 static xmlSchemaTypeLinkPtr | |
| 14642 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type) | |
| 14643 { | |
| 14644 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) { | |
| 14645 if (type->memberTypes != NULL) | |
| 14646 return (type->memberTypes); | |
| 14647 else | |
| 14648 type = type->baseType; | |
| 14649 } | |
| 14650 return (NULL); | |
| 14651 } | |
| 14652 | |
| 14653 /** | |
| 14654 * xmlSchemaGetParticleTotalRangeMin: | |
| 14655 * @particle: the particle | |
| 14656 * | |
| 14657 * Schema Component Constraint: Effective Total Range | |
| 14658 * (all and sequence) + (choice) | |
| 14659 * | |
| 14660 * Returns the minimun Effective Total Range. | |
| 14661 */ | |
| 14662 static int | |
| 14663 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle) | |
| 14664 { | |
| 14665 if ((particle->children == NULL) || | |
| 14666 (particle->minOccurs == 0)) | |
| 14667 return (0); | |
| 14668 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) { | |
| 14669 int min = -1, cur; | |
| 14670 xmlSchemaParticlePtr part = | |
| 14671 (xmlSchemaParticlePtr) particle->children->children; | |
| 14672 | |
| 14673 if (part == NULL) | |
| 14674 return (0); | |
| 14675 while (part != NULL) { | |
| 14676 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || | |
| 14677 (part->children->type == XML_SCHEMA_TYPE_ANY)) | |
| 14678 cur = part->minOccurs; | |
| 14679 else | |
| 14680 cur = xmlSchemaGetParticleTotalRangeMin(part); | |
| 14681 if (cur == 0) | |
| 14682 return (0); | |
| 14683 if ((min > cur) || (min == -1)) | |
| 14684 min = cur; | |
| 14685 part = (xmlSchemaParticlePtr) part->next; | |
| 14686 } | |
| 14687 return (particle->minOccurs * min); | |
| 14688 } else { | |
| 14689 /* <all> and <sequence> */ | |
| 14690 int sum = 0; | |
| 14691 xmlSchemaParticlePtr part = | |
| 14692 (xmlSchemaParticlePtr) particle->children->children; | |
| 14693 | |
| 14694 if (part == NULL) | |
| 14695 return (0); | |
| 14696 do { | |
| 14697 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || | |
| 14698 (part->children->type == XML_SCHEMA_TYPE_ANY)) | |
| 14699 sum += part->minOccurs; | |
| 14700 else | |
| 14701 sum += xmlSchemaGetParticleTotalRangeMin(part); | |
| 14702 part = (xmlSchemaParticlePtr) part->next; | |
| 14703 } while (part != NULL); | |
| 14704 return (particle->minOccurs * sum); | |
| 14705 } | |
| 14706 } | |
| 14707 | |
| 14708 #if 0 | |
| 14709 /** | |
| 14710 * xmlSchemaGetParticleTotalRangeMax: | |
| 14711 * @particle: the particle | |
| 14712 * | |
| 14713 * Schema Component Constraint: Effective Total Range | |
| 14714 * (all and sequence) + (choice) | |
| 14715 * | |
| 14716 * Returns the maximum Effective Total Range. | |
| 14717 */ | |
| 14718 static int | |
| 14719 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle) | |
| 14720 { | |
| 14721 if ((particle->children == NULL) || | |
| 14722 (particle->children->children == NULL)) | |
| 14723 return (0); | |
| 14724 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) { | |
| 14725 int max = -1, cur; | |
| 14726 xmlSchemaParticlePtr part = | |
| 14727 (xmlSchemaParticlePtr) particle->children->children; | |
| 14728 | |
| 14729 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) { | |
| 14730 if (part->children == NULL) | |
| 14731 continue; | |
| 14732 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || | |
| 14733 (part->children->type == XML_SCHEMA_TYPE_ANY)) | |
| 14734 cur = part->maxOccurs; | |
| 14735 else | |
| 14736 cur = xmlSchemaGetParticleTotalRangeMax(part); | |
| 14737 if (cur == UNBOUNDED) | |
| 14738 return (UNBOUNDED); | |
| 14739 if ((max < cur) || (max == -1)) | |
| 14740 max = cur; | |
| 14741 } | |
| 14742 /* TODO: Handle overflows? */ | |
| 14743 return (particle->maxOccurs * max); | |
| 14744 } else { | |
| 14745 /* <all> and <sequence> */ | |
| 14746 int sum = 0, cur; | |
| 14747 xmlSchemaParticlePtr part = | |
| 14748 (xmlSchemaParticlePtr) particle->children->children; | |
| 14749 | |
| 14750 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) { | |
| 14751 if (part->children == NULL) | |
| 14752 continue; | |
| 14753 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || | |
| 14754 (part->children->type == XML_SCHEMA_TYPE_ANY)) | |
| 14755 cur = part->maxOccurs; | |
| 14756 else | |
| 14757 cur = xmlSchemaGetParticleTotalRangeMax(part); | |
| 14758 if (cur == UNBOUNDED) | |
| 14759 return (UNBOUNDED); | |
| 14760 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED)) | |
| 14761 return (UNBOUNDED); | |
| 14762 sum += cur; | |
| 14763 } | |
| 14764 /* TODO: Handle overflows? */ | |
| 14765 return (particle->maxOccurs * sum); | |
| 14766 } | |
| 14767 } | |
| 14768 #endif | |
| 14769 | |
| 14770 /** | |
| 14771 * xmlSchemaIsParticleEmptiable: | |
| 14772 * @particle: the particle | |
| 14773 * | |
| 14774 * Schema Component Constraint: Particle Emptiable | |
| 14775 * Checks whether the given particle is emptiable. | |
| 14776 * | |
| 14777 * Returns 1 if emptiable, 0 otherwise. | |
| 14778 */ | |
| 14779 static int | |
| 14780 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle) | |
| 14781 { | |
| 14782 /* | |
| 14783 * SPEC (1) "Its {min occurs} is 0." | |
| 14784 */ | |
| 14785 if ((particle == NULL) || (particle->minOccurs == 0) || | |
| 14786 (particle->children == NULL)) | |
| 14787 return (1); | |
| 14788 /* | |
| 14789 * SPEC (2) "Its {term} is a group and the minimum part of the | |
| 14790 * effective total range of that group, [...] is 0." | |
| 14791 */ | |
| 14792 if (WXS_IS_MODEL_GROUP(particle->children)) { | |
| 14793 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0) | |
| 14794 return (1); | |
| 14795 } | |
| 14796 return (0); | |
| 14797 } | |
| 14798 | |
| 14799 /** | |
| 14800 * xmlSchemaCheckCOSSTDerivedOK: | |
| 14801 * @actxt: a context | |
| 14802 * @type: the derived simple type definition | |
| 14803 * @baseType: the base type definition | |
| 14804 * @subset: the subset of ('restriction', ect.) | |
| 14805 * | |
| 14806 * Schema Component Constraint: | |
| 14807 * Type Derivation OK (Simple) (cos-st-derived-OK) | |
| 14808 * | |
| 14809 * Checks wheter @type can be validly | |
| 14810 * derived from @baseType. | |
| 14811 * | |
| 14812 * Returns 0 on success, an positive error code otherwise. | |
| 14813 */ | |
| 14814 static int | |
| 14815 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt, | |
| 14816 xmlSchemaTypePtr type, | |
| 14817 xmlSchemaTypePtr baseType, | |
| 14818 int subset) | |
| 14819 { | |
| 14820 /* | |
| 14821 * 1 They are the same type definition. | |
| 14822 * TODO: The identy check might have to be more complex than this. | |
| 14823 */ | |
| 14824 if (type == baseType) | |
| 14825 return (0); | |
| 14826 /* | |
| 14827 * 2.1 restriction is not in the subset, or in the {final} | |
| 14828 * of its own {base type definition}; | |
| 14829 * | |
| 14830 * NOTE that this will be used also via "xsi:type". | |
| 14831 * | |
| 14832 * TODO: Revise this, it looks strange. How can the "type" | |
| 14833 * not be fixed or *in* fixing? | |
| 14834 */ | |
| 14835 if (WXS_IS_TYPE_NOT_FIXED(type)) | |
| 14836 if (xmlSchemaTypeFixup(type, actxt) == -1) | |
| 14837 return(-1); | |
| 14838 if (WXS_IS_TYPE_NOT_FIXED(baseType)) | |
| 14839 if (xmlSchemaTypeFixup(baseType, actxt) == -1) | |
| 14840 return(-1); | |
| 14841 if ((subset & SUBSET_RESTRICTION) || | |
| 14842 (xmlSchemaTypeFinalContains(type->baseType, | |
| 14843 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) { | |
| 14844 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1); | |
| 14845 } | |
| 14846 /* 2.2 */ | |
| 14847 if (type->baseType == baseType) { | |
| 14848 /* | |
| 14849 * 2.2.1 D's `base type definition` is B. | |
| 14850 */ | |
| 14851 return (0); | |
| 14852 } | |
| 14853 /* | |
| 14854 * 2.2.2 D's `base type definition` is not the `ur-type definition` | |
| 14855 * and is validly derived from B given the subset, as defined by this | |
| 14856 * constraint. | |
| 14857 */ | |
| 14858 if ((! WXS_IS_ANYTYPE(type->baseType)) && | |
| 14859 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType, | |
| 14860 baseType, subset) == 0)) { | |
| 14861 return (0); | |
| 14862 } | |
| 14863 /* | |
| 14864 * 2.2.3 D's {variety} is list or union and B is the `simple ur-type | |
| 14865 * definition`. | |
| 14866 */ | |
| 14867 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) && | |
| 14868 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) { | |
| 14869 return (0); | |
| 14870 } | |
| 14871 /* | |
| 14872 * 2.2.4 B's {variety} is union and D is validly derived from a type | |
| 14873 * definition in B's {member type definitions} given the subset, as | |
| 14874 * defined by this constraint. | |
| 14875 * | |
| 14876 * NOTE: This seems not to involve built-in types, since there is no | |
| 14877 * built-in Union Simple Type. | |
| 14878 */ | |
| 14879 if (WXS_IS_UNION(baseType)) { | |
| 14880 xmlSchemaTypeLinkPtr cur; | |
| 14881 | |
| 14882 cur = baseType->memberTypes; | |
| 14883 while (cur != NULL) { | |
| 14884 if (WXS_IS_TYPE_NOT_FIXED(cur->type)) | |
| 14885 if (xmlSchemaTypeFixup(cur->type, actxt) == -1) | |
| 14886 return(-1); | |
| 14887 if (xmlSchemaCheckCOSSTDerivedOK(actxt, | |
| 14888 type, cur->type, subset) == 0) | |
| 14889 { | |
| 14890 /* | |
| 14891 * It just has to be validly derived from at least one | |
| 14892 * member-type. | |
| 14893 */ | |
| 14894 return (0); | |
| 14895 } | |
| 14896 cur = cur->next; | |
| 14897 } | |
| 14898 } | |
| 14899 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2); | |
| 14900 } | |
| 14901 | |
| 14902 /** | |
| 14903 * xmlSchemaCheckTypeDefCircularInternal: | |
| 14904 * @pctxt: the schema parser context | |
| 14905 * @ctxtType: the type definition | |
| 14906 * @ancestor: an ancestor of @ctxtType | |
| 14907 * | |
| 14908 * Checks st-props-correct (2) + ct-props-correct (3). | |
| 14909 * Circular type definitions are not allowed. | |
| 14910 * | |
| 14911 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is | |
| 14912 * circular, 0 otherwise. | |
| 14913 */ | |
| 14914 static int | |
| 14915 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt, | |
| 14916 xmlSchemaTypePtr ctxtType, | |
| 14917 xmlSchemaTypePtr ancestor) | |
| 14918 { | |
| 14919 int ret; | |
| 14920 | |
| 14921 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC)) | |
| 14922 return (0); | |
| 14923 | |
| 14924 if (ctxtType == ancestor) { | |
| 14925 xmlSchemaPCustomErr(pctxt, | |
| 14926 XML_SCHEMAP_ST_PROPS_CORRECT_2, | |
| 14927 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType), | |
| 14928 "The definition is circular", NULL); | |
| 14929 return (XML_SCHEMAP_ST_PROPS_CORRECT_2); | |
| 14930 } | |
| 14931 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) { | |
| 14932 /* | |
| 14933 * Avoid inifinite recursion on circular types not yet checked. | |
| 14934 */ | |
| 14935 return (0); | |
| 14936 } | |
| 14937 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED; | |
| 14938 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType, | |
| 14939 ancestor->baseType); | |
| 14940 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED; | |
| 14941 return (ret); | |
| 14942 } | |
| 14943 | |
| 14944 /** | |
| 14945 * xmlSchemaCheckTypeDefCircular: | |
| 14946 * @item: the complex/simple type definition | |
| 14947 * @ctxt: the parser context | |
| 14948 * @name: the name | |
| 14949 * | |
| 14950 * Checks for circular type definitions. | |
| 14951 */ | |
| 14952 static void | |
| 14953 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item, | |
| 14954 xmlSchemaParserCtxtPtr ctxt) | |
| 14955 { | |
| 14956 if ((item == NULL) || | |
| 14957 (item->type == XML_SCHEMA_TYPE_BASIC) || | |
| 14958 (item->baseType == NULL)) | |
| 14959 return; | |
| 14960 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, | |
| 14961 item->baseType); | |
| 14962 } | |
| 14963 | |
| 14964 /* | |
| 14965 * Simple Type Definition Representation OK (src-simple-type) 4 | |
| 14966 * | |
| 14967 * "4 Circular union type definition is disallowed. That is, if the | |
| 14968 * <union> alternative is chosen, there must not be any entries in the | |
| 14969 * memberTypes [attribute] at any depth which resolve to the component | |
| 14970 * corresponding to the <simpleType>." | |
| 14971 * | |
| 14972 * Note that this should work on the *representation* of a component, | |
| 14973 * thus assumes any union types in the member types not being yet | |
| 14974 * substituted. At this stage we need the variety of the types | |
| 14975 * to be already computed. | |
| 14976 */ | |
| 14977 static int | |
| 14978 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt, | |
| 14979 xmlSchemaTypePtr ctxType, | |
| 14980 xmlSchemaTypeLinkPtr members) | |
| 14981 { | |
| 14982 xmlSchemaTypeLinkPtr member; | |
| 14983 xmlSchemaTypePtr memberType; | |
| 14984 | |
| 14985 member = members; | |
| 14986 while (member != NULL) { | |
| 14987 memberType = member->type; | |
| 14988 while ((memberType != NULL) && | |
| 14989 (memberType->type != XML_SCHEMA_TYPE_BASIC)) { | |
| 14990 if (memberType == ctxType) { | |
| 14991 xmlSchemaPCustomErr(pctxt, | |
| 14992 XML_SCHEMAP_SRC_SIMPLE_TYPE_4, | |
| 14993 WXS_BASIC_CAST ctxType, NULL, | |
| 14994 "The union type definition is circular", NULL); | |
| 14995 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4); | |
| 14996 } | |
| 14997 if ((WXS_IS_UNION(memberType)) && | |
| 14998 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0)) | |
| 14999 { | |
| 15000 int res; | |
| 15001 memberType->flags |= XML_SCHEMAS_TYPE_MARKED; | |
| 15002 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, | |
| 15003 ctxType, | |
| 15004 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType)); | |
| 15005 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED; | |
| 15006 if (res != 0) | |
| 15007 return(res); | |
| 15008 } | |
| 15009 memberType = memberType->baseType; | |
| 15010 } | |
| 15011 member = member->next; | |
| 15012 } | |
| 15013 return(0); | |
| 15014 } | |
| 15015 | |
| 15016 static int | |
| 15017 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt, | |
| 15018 xmlSchemaTypePtr type) | |
| 15019 { | |
| 15020 if (! WXS_IS_UNION(type)) | |
| 15021 return(0); | |
| 15022 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type, | |
| 15023 type->memberTypes)); | |
| 15024 } | |
| 15025 | |
| 15026 /** | |
| 15027 * xmlSchemaResolveTypeReferences: | |
| 15028 * @item: the complex/simple type definition | |
| 15029 * @ctxt: the parser context | |
| 15030 * @name: the name | |
| 15031 * | |
| 15032 * Resolvese type definition references | |
| 15033 */ | |
| 15034 static void | |
| 15035 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef, | |
| 15036 xmlSchemaParserCtxtPtr ctxt) | |
| 15037 { | |
| 15038 if (typeDef == NULL) | |
| 15039 return; | |
| 15040 | |
| 15041 /* | |
| 15042 * Resolve the base type. | |
| 15043 */ | |
| 15044 if (typeDef->baseType == NULL) { | |
| 15045 typeDef->baseType = xmlSchemaGetType(ctxt->schema, | |
| 15046 typeDef->base, typeDef->baseNs); | |
| 15047 if (typeDef->baseType == NULL) { | |
| 15048 xmlSchemaPResCompAttrErr(ctxt, | |
| 15049 XML_SCHEMAP_SRC_RESOLVE, | |
| 15050 WXS_BASIC_CAST typeDef, typeDef->node, | |
| 15051 "base", typeDef->base, typeDef->baseNs, | |
| 15052 XML_SCHEMA_TYPE_SIMPLE, NULL); | |
| 15053 return; | |
| 15054 } | |
| 15055 } | |
| 15056 if (WXS_IS_SIMPLE(typeDef)) { | |
| 15057 if (WXS_IS_UNION(typeDef)) { | |
| 15058 /* | |
| 15059 * Resolve the memberTypes. | |
| 15060 */ | |
| 15061 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef); | |
| 15062 return; | |
| 15063 } else if (WXS_IS_LIST(typeDef)) { | |
| 15064 /* | |
| 15065 * Resolve the itemType. | |
| 15066 */ | |
| 15067 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) { | |
| 15068 | |
| 15069 typeDef->subtypes = xmlSchemaGetType(ctxt->schema, | |
| 15070 typeDef->base, typeDef->baseNs); | |
| 15071 | |
| 15072 if ((typeDef->subtypes == NULL) || | |
| 15073 (! WXS_IS_SIMPLE(typeDef->subtypes))) | |
| 15074 { | |
| 15075 typeDef->subtypes = NULL; | |
| 15076 xmlSchemaPResCompAttrErr(ctxt, | |
| 15077 XML_SCHEMAP_SRC_RESOLVE, | |
| 15078 WXS_BASIC_CAST typeDef, typeDef->node, | |
| 15079 "itemType", typeDef->base, typeDef->baseNs, | |
| 15080 XML_SCHEMA_TYPE_SIMPLE, NULL); | |
| 15081 } | |
| 15082 } | |
| 15083 return; | |
| 15084 } | |
| 15085 } | |
| 15086 /* | |
| 15087 * The ball of letters below means, that if we have a particle | |
| 15088 * which has a QName-helper component as its {term}, we want | |
| 15089 * to resolve it... | |
| 15090 */ | |
| 15091 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) && | |
| 15092 ((WXS_TYPE_CONTENTTYPE(typeDef))->type == | |
| 15093 XML_SCHEMA_TYPE_PARTICLE) && | |
| 15094 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) && | |
| 15095 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type == | |
| 15096 XML_SCHEMA_EXTRA_QNAMEREF)) | |
| 15097 { | |
| 15098 xmlSchemaQNameRefPtr ref = | |
| 15099 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef); | |
| 15100 xmlSchemaModelGroupDefPtr groupDef; | |
| 15101 | |
| 15102 /* | |
| 15103 * URGENT TODO: Test this. | |
| 15104 */ | |
| 15105 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL; | |
| 15106 /* | |
| 15107 * Resolve the MG definition reference. | |
| 15108 */ | |
| 15109 groupDef = | |
| 15110 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema, | |
| 15111 ref->itemType, ref->name, ref->targetNamespace); | |
| 15112 if (groupDef == NULL) { | |
| 15113 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE, | |
| 15114 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), | |
| 15115 "ref", ref->name, ref->targetNamespace, ref->itemType, | |
| 15116 NULL); | |
| 15117 /* Remove the particle. */ | |
| 15118 WXS_TYPE_CONTENTTYPE(typeDef) = NULL; | |
| 15119 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL) | |
| 15120 /* Remove the particle. */ | |
| 15121 WXS_TYPE_CONTENTTYPE(typeDef) = NULL; | |
| 15122 else { | |
| 15123 /* | |
| 15124 * Assign the MG definition's {model group} to the | |
| 15125 * particle's {term}. | |
| 15126 */ | |
| 15127 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef); | |
| 15128 | |
| 15129 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL)
{ | |
| 15130 /* | |
| 15131 * SPEC cos-all-limited (1.2) | |
| 15132 * "1.2 the {term} property of a particle with | |
| 15133 * {max occurs}=1 which is part of a pair which constitutes | |
| 15134 * the {content type} of a complex type definition." | |
| 15135 */ | |
| 15136 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) { | |
| 15137 xmlSchemaCustomErr(ACTXT_CAST ctxt, | |
| 15138 /* TODO: error code */ | |
| 15139 XML_SCHEMAP_COS_ALL_LIMITED, | |
| 15140 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL, | |
| 15141 "The particle's {max occurs} must be 1, since the " | |
| 15142 "reference resolves to an 'all' model group", | |
| 15143 NULL, NULL); | |
| 15144 } | |
| 15145 } | |
| 15146 } | |
| 15147 } | |
| 15148 } | |
| 15149 | |
| 15150 | |
| 15151 | |
| 15152 /** | |
| 15153 * xmlSchemaCheckSTPropsCorrect: | |
| 15154 * @ctxt: the schema parser context | |
| 15155 * @type: the simple type definition | |
| 15156 * | |
| 15157 * Checks st-props-correct. | |
| 15158 * | |
| 15159 * Returns 0 if the properties are correct, | |
| 15160 * if not, a positive error code and -1 on internal | |
| 15161 * errors. | |
| 15162 */ | |
| 15163 static int | |
| 15164 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt, | |
| 15165 xmlSchemaTypePtr type) | |
| 15166 { | |
| 15167 xmlSchemaTypePtr baseType = type->baseType; | |
| 15168 xmlChar *str = NULL; | |
| 15169 | |
| 15170 /* STATE: error funcs converted. */ | |
| 15171 /* | |
| 15172 * Schema Component Constraint: Simple Type Definition Properties Correct | |
| 15173 * | |
| 15174 * NOTE: This is somehow redundant, since we actually built a simple type | |
| 15175 * to have all the needed information; this acts as an self test. | |
| 15176 */ | |
| 15177 /* Base type: If the datatype has been `derived` by `restriction` | |
| 15178 * then the Simple Type Definition component from which it is `derived`, | |
| 15179 * otherwise the Simple Type Definition for anySimpleType ($4.1.6). | |
| 15180 */ | |
| 15181 if (baseType == NULL) { | |
| 15182 /* | |
| 15183 * TODO: Think about: "modulo the impact of Missing | |
| 15184 * Sub-components ($5.3)." | |
| 15185 */ | |
| 15186 xmlSchemaPCustomErr(ctxt, | |
| 15187 XML_SCHEMAP_ST_PROPS_CORRECT_1, | |
| 15188 WXS_BASIC_CAST type, NULL, | |
| 15189 "No base type existent", NULL); | |
| 15190 return (XML_SCHEMAP_ST_PROPS_CORRECT_1); | |
| 15191 | |
| 15192 } | |
| 15193 if (! WXS_IS_SIMPLE(baseType)) { | |
| 15194 xmlSchemaPCustomErr(ctxt, | |
| 15195 XML_SCHEMAP_ST_PROPS_CORRECT_1, | |
| 15196 WXS_BASIC_CAST type, NULL, | |
| 15197 "The base type '%s' is not a simple type", | |
| 15198 xmlSchemaGetComponentQName(&str, baseType)); | |
| 15199 FREE_AND_NULL(str) | |
| 15200 return (XML_SCHEMAP_ST_PROPS_CORRECT_1); | |
| 15201 } | |
| 15202 if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) && | |
| 15203 (WXS_IS_RESTRICTION(type) == 0) && | |
| 15204 ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) && | |
| 15205 (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) { | |
| 15206 xmlSchemaPCustomErr(ctxt, | |
| 15207 XML_SCHEMAP_ST_PROPS_CORRECT_1, | |
| 15208 WXS_BASIC_CAST type, NULL, | |
| 15209 "A type, derived by list or union, must have " | |
| 15210 "the simple ur-type definition as base type, not '%s'", | |
| 15211 xmlSchemaGetComponentQName(&str, baseType)); | |
| 15212 FREE_AND_NULL(str) | |
| 15213 return (XML_SCHEMAP_ST_PROPS_CORRECT_1); | |
| 15214 } | |
| 15215 /* | |
| 15216 * Variety: One of {atomic, list, union}. | |
| 15217 */ | |
| 15218 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) && | |
| 15219 (! WXS_IS_LIST(type))) { | |
| 15220 xmlSchemaPCustomErr(ctxt, | |
| 15221 XML_SCHEMAP_ST_PROPS_CORRECT_1, | |
| 15222 WXS_BASIC_CAST type, NULL, | |
| 15223 "The variety is absent", NULL); | |
| 15224 return (XML_SCHEMAP_ST_PROPS_CORRECT_1); | |
| 15225 } | |
| 15226 /* TODO: Finish this. Hmm, is this finished? */ | |
| 15227 | |
| 15228 /* | |
| 15229 * 3 The {final} of the {base type definition} must not contain restriction. | |
| 15230 */ | |
| 15231 if (xmlSchemaTypeFinalContains(baseType, | |
| 15232 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { | |
| 15233 xmlSchemaPCustomErr(ctxt, | |
| 15234 XML_SCHEMAP_ST_PROPS_CORRECT_3, | |
| 15235 WXS_BASIC_CAST type, NULL, | |
| 15236 "The 'final' of its base type '%s' must not contain " | |
| 15237 "'restriction'", | |
| 15238 xmlSchemaGetComponentQName(&str, baseType)); | |
| 15239 FREE_AND_NULL(str) | |
| 15240 return (XML_SCHEMAP_ST_PROPS_CORRECT_3); | |
| 15241 } | |
| 15242 | |
| 15243 /* | |
| 15244 * 2 All simple type definitions must be derived ultimately from the `simple | |
| 15245 * ur-type definition` (so circular definitions are disallowed). That is, it | |
| 15246 * must be possible to reach a built-in primitive datatype or the `simple | |
| 15247 * ur-type definition` by repeatedly following the {base type definition}. | |
| 15248 * | |
| 15249 * NOTE: this is done in xmlSchemaCheckTypeDefCircular(). | |
| 15250 */ | |
| 15251 return (0); | |
| 15252 } | |
| 15253 | |
| 15254 /** | |
| 15255 * xmlSchemaCheckCOSSTRestricts: | |
| 15256 * @ctxt: the schema parser context | |
| 15257 * @type: the simple type definition | |
| 15258 * | |
| 15259 * Schema Component Constraint: | |
| 15260 * Derivation Valid (Restriction, Simple) (cos-st-restricts) | |
| 15261 | |
| 15262 * Checks if the given @type (simpleType) is derived validly by restriction. | |
| 15263 * STATUS: | |
| 15264 * | |
| 15265 * Returns -1 on internal errors, 0 if the type is validly derived, | |
| 15266 * a positive error code otherwise. | |
| 15267 */ | |
| 15268 static int | |
| 15269 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt, | |
| 15270 xmlSchemaTypePtr type) | |
| 15271 { | |
| 15272 xmlChar *str = NULL; | |
| 15273 | |
| 15274 if (type->type != XML_SCHEMA_TYPE_SIMPLE) { | |
| 15275 PERROR_INT("xmlSchemaCheckCOSSTRestricts", | |
| 15276 "given type is not a user-derived simpleType"); | |
| 15277 return (-1); | |
| 15278 } | |
| 15279 | |
| 15280 if (WXS_IS_ATOMIC(type)) { | |
| 15281 xmlSchemaTypePtr primitive; | |
| 15282 /* | |
| 15283 * 1.1 The {base type definition} must be an atomic simple | |
| 15284 * type definition or a built-in primitive datatype. | |
| 15285 */ | |
| 15286 if (! WXS_IS_ATOMIC(type->baseType)) { | |
| 15287 xmlSchemaPCustomErr(pctxt, | |
| 15288 XML_SCHEMAP_COS_ST_RESTRICTS_1_1, | |
| 15289 WXS_BASIC_CAST type, NULL, | |
| 15290 "The base type '%s' is not an atomic simple type", | |
| 15291 xmlSchemaGetComponentQName(&str, type->baseType)); | |
| 15292 FREE_AND_NULL(str) | |
| 15293 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1); | |
| 15294 } | |
| 15295 /* 1.2 The {final} of the {base type definition} must not contain | |
| 15296 * restriction. | |
| 15297 */ | |
| 15298 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect
*/ | |
| 15299 if (xmlSchemaTypeFinalContains(type->baseType, | |
| 15300 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { | |
| 15301 xmlSchemaPCustomErr(pctxt, | |
| 15302 XML_SCHEMAP_COS_ST_RESTRICTS_1_2, | |
| 15303 WXS_BASIC_CAST type, NULL, | |
| 15304 "The final of its base type '%s' must not contain 'restriction'"
, | |
| 15305 xmlSchemaGetComponentQName(&str, type->baseType)); | |
| 15306 FREE_AND_NULL(str) | |
| 15307 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2); | |
| 15308 } | |
| 15309 | |
| 15310 /* | |
| 15311 * 1.3.1 DF must be an allowed constraining facet for the {primitive | |
| 15312 * type definition}, as specified in the appropriate subsection of 3.2 | |
| 15313 * Primitive datatypes. | |
| 15314 */ | |
| 15315 if (type->facets != NULL) { | |
| 15316 xmlSchemaFacetPtr facet; | |
| 15317 int ok = 1; | |
| 15318 | |
| 15319 primitive = xmlSchemaGetPrimitiveType(type); | |
| 15320 if (primitive == NULL) { | |
| 15321 PERROR_INT("xmlSchemaCheckCOSSTRestricts", | |
| 15322 "failed to get primitive type"); | |
| 15323 return (-1); | |
| 15324 } | |
| 15325 facet = type->facets; | |
| 15326 do { | |
| 15327 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) { | |
| 15328 ok = 0; | |
| 15329 xmlSchemaPIllegalFacetAtomicErr(pctxt, | |
| 15330 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1, | |
| 15331 type, primitive, facet); | |
| 15332 } | |
| 15333 facet = facet->next; | |
| 15334 } while (facet != NULL); | |
| 15335 if (ok == 0) | |
| 15336 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1); | |
| 15337 } | |
| 15338 /* | |
| 15339 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets} | |
| 15340 * of the {base type definition} (call this BF),then the DF's {value} | |
| 15341 * must be a valid restriction of BF's {value} as defined in | |
| 15342 * [XML Schemas: Datatypes]." | |
| 15343 * | |
| 15344 * NOTE (1.3.2) Facet derivation constraints are currently handled in | |
| 15345 * xmlSchemaDeriveAndValidateFacets() | |
| 15346 */ | |
| 15347 } else if (WXS_IS_LIST(type)) { | |
| 15348 xmlSchemaTypePtr itemType = NULL; | |
| 15349 | |
| 15350 itemType = type->subtypes; | |
| 15351 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) { | |
| 15352 PERROR_INT("xmlSchemaCheckCOSSTRestricts", | |
| 15353 "failed to evaluate the item type"); | |
| 15354 return (-1); | |
| 15355 } | |
| 15356 if (WXS_IS_TYPE_NOT_FIXED(itemType)) | |
| 15357 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt); | |
| 15358 /* | |
| 15359 * 2.1 The {item type definition} must have a {variety} of atomic or | |
| 15360 * union (in which case all the {member type definitions} | |
| 15361 * must be atomic). | |
| 15362 */ | |
| 15363 if ((! WXS_IS_ATOMIC(itemType)) && | |
| 15364 (! WXS_IS_UNION(itemType))) { | |
| 15365 xmlSchemaPCustomErr(pctxt, | |
| 15366 XML_SCHEMAP_COS_ST_RESTRICTS_2_1, | |
| 15367 WXS_BASIC_CAST type, NULL, | |
| 15368 "The item type '%s' does not have a variety of atomic or union", | |
| 15369 xmlSchemaGetComponentQName(&str, itemType)); | |
| 15370 FREE_AND_NULL(str) | |
| 15371 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1); | |
| 15372 } else if (WXS_IS_UNION(itemType)) { | |
| 15373 xmlSchemaTypeLinkPtr member; | |
| 15374 | |
| 15375 member = itemType->memberTypes; | |
| 15376 while (member != NULL) { | |
| 15377 if (! WXS_IS_ATOMIC(member->type)) { | |
| 15378 xmlSchemaPCustomErr(pctxt, | |
| 15379 XML_SCHEMAP_COS_ST_RESTRICTS_2_1, | |
| 15380 WXS_BASIC_CAST type, NULL, | |
| 15381 "The item type is a union type, but the " | |
| 15382 "member type '%s' of this item type is not atomic", | |
| 15383 xmlSchemaGetComponentQName(&str, member->type)); | |
| 15384 FREE_AND_NULL(str) | |
| 15385 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1); | |
| 15386 } | |
| 15387 member = member->next; | |
| 15388 } | |
| 15389 } | |
| 15390 | |
| 15391 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) { | |
| 15392 xmlSchemaFacetPtr facet; | |
| 15393 /* | |
| 15394 * This is the case if we have: <simpleType><list .. | |
| 15395 */ | |
| 15396 /* | |
| 15397 * 2.3.1 | |
| 15398 * 2.3.1.1 The {final} of the {item type definition} must not | |
| 15399 * contain list. | |
| 15400 */ | |
| 15401 if (xmlSchemaTypeFinalContains(itemType, | |
| 15402 XML_SCHEMAS_TYPE_FINAL_LIST)) { | |
| 15403 xmlSchemaPCustomErr(pctxt, | |
| 15404 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1, | |
| 15405 WXS_BASIC_CAST type, NULL, | |
| 15406 "The final of its item type '%s' must not contain 'list'", | |
| 15407 xmlSchemaGetComponentQName(&str, itemType)); | |
| 15408 FREE_AND_NULL(str) | |
| 15409 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1); | |
| 15410 } | |
| 15411 /* | |
| 15412 * 2.3.1.2 The {facets} must only contain the whiteSpace | |
| 15413 * facet component. | |
| 15414 * OPTIMIZE TODO: the S4S already disallows any facet | |
| 15415 * to be specified. | |
| 15416 */ | |
| 15417 if (type->facets != NULL) { | |
| 15418 facet = type->facets; | |
| 15419 do { | |
| 15420 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) { | |
| 15421 xmlSchemaPIllegalFacetListUnionErr(pctxt, | |
| 15422 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2, | |
| 15423 type, facet); | |
| 15424 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2); | |
| 15425 } | |
| 15426 facet = facet->next; | |
| 15427 } while (facet != NULL); | |
| 15428 } | |
| 15429 /* | |
| 15430 * MAYBE TODO: (Hmm, not really) Datatypes states: | |
| 15431 * A `list` datatype can be `derived` from an `atomic` datatype | |
| 15432 * whose `lexical space` allows space (such as string or anyURI)or | |
| 15433 * a `union` datatype any of whose {member type definitions}'s | |
| 15434 * `lexical space` allows space. | |
| 15435 */ | |
| 15436 } else { | |
| 15437 /* | |
| 15438 * This is the case if we have: <simpleType><restriction ... | |
| 15439 * I.e. the variety of "list" is inherited. | |
| 15440 */ | |
| 15441 /* | |
| 15442 * 2.3.2 | |
| 15443 * 2.3.2.1 The {base type definition} must have a {variety} of list. | |
| 15444 */ | |
| 15445 if (! WXS_IS_LIST(type->baseType)) { | |
| 15446 xmlSchemaPCustomErr(pctxt, | |
| 15447 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1, | |
| 15448 WXS_BASIC_CAST type, NULL, | |
| 15449 "The base type '%s' must be a list type", | |
| 15450 xmlSchemaGetComponentQName(&str, type->baseType)); | |
| 15451 FREE_AND_NULL(str) | |
| 15452 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1); | |
| 15453 } | |
| 15454 /* | |
| 15455 * 2.3.2.2 The {final} of the {base type definition} must not | |
| 15456 * contain restriction. | |
| 15457 */ | |
| 15458 if (xmlSchemaTypeFinalContains(type->baseType, | |
| 15459 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { | |
| 15460 xmlSchemaPCustomErr(pctxt, | |
| 15461 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2, | |
| 15462 WXS_BASIC_CAST type, NULL, | |
| 15463 "The 'final' of the base type '%s' must not contain 'restric
tion'", | |
| 15464 xmlSchemaGetComponentQName(&str, type->baseType)); | |
| 15465 FREE_AND_NULL(str) | |
| 15466 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2); | |
| 15467 } | |
| 15468 /* | |
| 15469 * 2.3.2.3 The {item type definition} must be validly derived | |
| 15470 * from the {base type definition}'s {item type definition} given | |
| 15471 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6)
. | |
| 15472 */ | |
| 15473 { | |
| 15474 xmlSchemaTypePtr baseItemType; | |
| 15475 | |
| 15476 baseItemType = type->baseType->subtypes; | |
| 15477 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) { | |
| 15478 PERROR_INT("xmlSchemaCheckCOSSTRestricts", | |
| 15479 "failed to eval the item type of a base type"); | |
| 15480 return (-1); | |
| 15481 } | |
| 15482 if ((itemType != baseItemType) && | |
| 15483 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType, | |
| 15484 baseItemType, 0) != 0)) { | |
| 15485 xmlChar *strBIT = NULL, *strBT = NULL; | |
| 15486 xmlSchemaPCustomErrExt(pctxt, | |
| 15487 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3, | |
| 15488 WXS_BASIC_CAST type, NULL, | |
| 15489 "The item type '%s' is not validly derived from " | |
| 15490 "the item type '%s' of the base type '%s'", | |
| 15491 xmlSchemaGetComponentQName(&str, itemType), | |
| 15492 xmlSchemaGetComponentQName(&strBIT, baseItemType), | |
| 15493 xmlSchemaGetComponentQName(&strBT, type->baseType)); | |
| 15494 | |
| 15495 FREE_AND_NULL(str) | |
| 15496 FREE_AND_NULL(strBIT) | |
| 15497 FREE_AND_NULL(strBT) | |
| 15498 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3); | |
| 15499 } | |
| 15500 } | |
| 15501 | |
| 15502 if (type->facets != NULL) { | |
| 15503 xmlSchemaFacetPtr facet; | |
| 15504 int ok = 1; | |
| 15505 /* | |
| 15506 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern | |
| 15507 * and enumeration facet components are allowed among the {facets
}. | |
| 15508 */ | |
| 15509 facet = type->facets; | |
| 15510 do { | |
| 15511 switch (facet->type) { | |
| 15512 case XML_SCHEMA_FACET_LENGTH: | |
| 15513 case XML_SCHEMA_FACET_MINLENGTH: | |
| 15514 case XML_SCHEMA_FACET_MAXLENGTH: | |
| 15515 case XML_SCHEMA_FACET_WHITESPACE: | |
| 15516 /* | |
| 15517 * TODO: 2.5.1.2 List datatypes | |
| 15518 * The value of `whiteSpace` is fixed to the value co
llapse. | |
| 15519 */ | |
| 15520 case XML_SCHEMA_FACET_PATTERN: | |
| 15521 case XML_SCHEMA_FACET_ENUMERATION: | |
| 15522 break; | |
| 15523 default: { | |
| 15524 xmlSchemaPIllegalFacetListUnionErr(pctxt, | |
| 15525 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4, | |
| 15526 type, facet); | |
| 15527 /* | |
| 15528 * We could return, but it's nicer to report all | |
| 15529 * invalid facets. | |
| 15530 */ | |
| 15531 ok = 0; | |
| 15532 } | |
| 15533 } | |
| 15534 facet = facet->next; | |
| 15535 } while (facet != NULL); | |
| 15536 if (ok == 0) | |
| 15537 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4); | |
| 15538 /* | |
| 15539 * SPEC (2.3.2.5) (same as 1.3.2) | |
| 15540 * | |
| 15541 * NOTE (2.3.2.5) This is currently done in | |
| 15542 * xmlSchemaDeriveAndValidateFacets() | |
| 15543 */ | |
| 15544 } | |
| 15545 } | |
| 15546 } else if (WXS_IS_UNION(type)) { | |
| 15547 /* | |
| 15548 * 3.1 The {member type definitions} must all have {variety} of | |
| 15549 * atomic or list. | |
| 15550 */ | |
| 15551 xmlSchemaTypeLinkPtr member; | |
| 15552 | |
| 15553 member = type->memberTypes; | |
| 15554 while (member != NULL) { | |
| 15555 if (WXS_IS_TYPE_NOT_FIXED(member->type)) | |
| 15556 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt); | |
| 15557 | |
| 15558 if ((! WXS_IS_ATOMIC(member->type)) && | |
| 15559 (! WXS_IS_LIST(member->type))) { | |
| 15560 xmlSchemaPCustomErr(pctxt, | |
| 15561 XML_SCHEMAP_COS_ST_RESTRICTS_3_1, | |
| 15562 WXS_BASIC_CAST type, NULL, | |
| 15563 "The member type '%s' is neither an atomic, nor a list type"
, | |
| 15564 xmlSchemaGetComponentQName(&str, member->type)); | |
| 15565 FREE_AND_NULL(str) | |
| 15566 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1); | |
| 15567 } | |
| 15568 member = member->next; | |
| 15569 } | |
| 15570 /* | |
| 15571 * 3.3.1 If the {base type definition} is the `simple ur-type | |
| 15572 * definition` | |
| 15573 */ | |
| 15574 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) { | |
| 15575 /* | |
| 15576 * 3.3.1.1 All of the {member type definitions} must have a | |
| 15577 * {final} which does not contain union. | |
| 15578 */ | |
| 15579 member = type->memberTypes; | |
| 15580 while (member != NULL) { | |
| 15581 if (xmlSchemaTypeFinalContains(member->type, | |
| 15582 XML_SCHEMAS_TYPE_FINAL_UNION)) { | |
| 15583 xmlSchemaPCustomErr(pctxt, | |
| 15584 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1, | |
| 15585 WXS_BASIC_CAST type, NULL, | |
| 15586 "The 'final' of member type '%s' contains 'union'", | |
| 15587 xmlSchemaGetComponentQName(&str, member->type)); | |
| 15588 FREE_AND_NULL(str) | |
| 15589 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1); | |
| 15590 } | |
| 15591 member = member->next; | |
| 15592 } | |
| 15593 /* | |
| 15594 * 3.3.1.2 The {facets} must be empty. | |
| 15595 */ | |
| 15596 if (type->facetSet != NULL) { | |
| 15597 xmlSchemaPCustomErr(pctxt, | |
| 15598 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2, | |
| 15599 WXS_BASIC_CAST type, NULL, | |
| 15600 "No facets allowed", NULL); | |
| 15601 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2); | |
| 15602 } | |
| 15603 } else { | |
| 15604 /* | |
| 15605 * 3.3.2.1 The {base type definition} must have a {variety} of union. | |
| 15606 * I.e. the variety of "list" is inherited. | |
| 15607 */ | |
| 15608 if (! WXS_IS_UNION(type->baseType)) { | |
| 15609 xmlSchemaPCustomErr(pctxt, | |
| 15610 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1, | |
| 15611 WXS_BASIC_CAST type, NULL, | |
| 15612 "The base type '%s' is not a union type", | |
| 15613 xmlSchemaGetComponentQName(&str, type->baseType)); | |
| 15614 FREE_AND_NULL(str) | |
| 15615 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1); | |
| 15616 } | |
| 15617 /* | |
| 15618 * 3.3.2.2 The {final} of the {base type definition} must not contain
restriction. | |
| 15619 */ | |
| 15620 if (xmlSchemaTypeFinalContains(type->baseType, | |
| 15621 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { | |
| 15622 xmlSchemaPCustomErr(pctxt, | |
| 15623 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2, | |
| 15624 WXS_BASIC_CAST type, NULL, | |
| 15625 "The 'final' of its base type '%s' must not contain 'restric
tion'", | |
| 15626 xmlSchemaGetComponentQName(&str, type->baseType)); | |
| 15627 FREE_AND_NULL(str) | |
| 15628 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2); | |
| 15629 } | |
| 15630 /* | |
| 15631 * 3.3.2.3 The {member type definitions}, in order, must be validly | |
| 15632 * derived from the corresponding type definitions in the {base | |
| 15633 * type definition}'s {member type definitions} given the empty set, | |
| 15634 * as defined in Type Derivation OK (Simple) ($3.14.6). | |
| 15635 */ | |
| 15636 { | |
| 15637 xmlSchemaTypeLinkPtr baseMember; | |
| 15638 | |
| 15639 /* | |
| 15640 * OPTIMIZE: if the type is restricting, it has no local defined | |
| 15641 * member types and inherits the member types of the base type; | |
| 15642 * thus a check for equality can be skipped. | |
| 15643 */ | |
| 15644 /* | |
| 15645 * Even worse: I cannot see a scenario where a restricting | |
| 15646 * union simple type can have other member types as the member | |
| 15647 * types of it's base type. This check seems not necessary with | |
| 15648 * respect to the derivation process in libxml2. | |
| 15649 * But necessary if constructing types with an API. | |
| 15650 */ | |
| 15651 if (type->memberTypes != NULL) { | |
| 15652 member = type->memberTypes; | |
| 15653 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->ba
seType); | |
| 15654 if ((member == NULL) && (baseMember != NULL)) { | |
| 15655 PERROR_INT("xmlSchemaCheckCOSSTRestricts", | |
| 15656 "different number of member types in base"); | |
| 15657 } | |
| 15658 while (member != NULL) { | |
| 15659 if (baseMember == NULL) { | |
| 15660 PERROR_INT("xmlSchemaCheckCOSSTRestricts", | |
| 15661 "different number of member types in base"); | |
| 15662 } else if ((member->type != baseMember->type) && | |
| 15663 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, | |
| 15664 member->type, baseMember->type, 0) != 0)) { | |
| 15665 xmlChar *strBMT = NULL, *strBT = NULL; | |
| 15666 | |
| 15667 xmlSchemaPCustomErrExt(pctxt, | |
| 15668 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3, | |
| 15669 WXS_BASIC_CAST type, NULL, | |
| 15670 "The member type %s is not validly " | |
| 15671 "derived from its corresponding member " | |
| 15672 "type %s of the base type %s", | |
| 15673 xmlSchemaGetComponentQName(&str, member->type), | |
| 15674 xmlSchemaGetComponentQName(&strBMT, baseMember->
type), | |
| 15675 xmlSchemaGetComponentQName(&strBT, type->baseTyp
e)); | |
| 15676 FREE_AND_NULL(str) | |
| 15677 FREE_AND_NULL(strBMT) | |
| 15678 FREE_AND_NULL(strBT) | |
| 15679 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3); | |
| 15680 } | |
| 15681 member = member->next; | |
| 15682 if (baseMember != NULL) | |
| 15683 baseMember = baseMember->next; | |
| 15684 } | |
| 15685 } | |
| 15686 } | |
| 15687 /* | |
| 15688 * 3.3.2.4 Only pattern and enumeration facet components are | |
| 15689 * allowed among the {facets}. | |
| 15690 */ | |
| 15691 if (type->facets != NULL) { | |
| 15692 xmlSchemaFacetPtr facet; | |
| 15693 int ok = 1; | |
| 15694 | |
| 15695 facet = type->facets; | |
| 15696 do { | |
| 15697 if ((facet->type != XML_SCHEMA_FACET_PATTERN) && | |
| 15698 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) { | |
| 15699 xmlSchemaPIllegalFacetListUnionErr(pctxt, | |
| 15700 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4, | |
| 15701 type, facet); | |
| 15702 ok = 0; | |
| 15703 } | |
| 15704 facet = facet->next; | |
| 15705 } while (facet != NULL); | |
| 15706 if (ok == 0) | |
| 15707 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4); | |
| 15708 | |
| 15709 } | |
| 15710 /* | |
| 15711 * SPEC (3.3.2.5) (same as 1.3.2) | |
| 15712 * | |
| 15713 * NOTE (3.3.2.5) This is currently done in | |
| 15714 * xmlSchemaDeriveAndValidateFacets() | |
| 15715 */ | |
| 15716 } | |
| 15717 } | |
| 15718 | |
| 15719 return (0); | |
| 15720 } | |
| 15721 | |
| 15722 /** | |
| 15723 * xmlSchemaCheckSRCSimpleType: | |
| 15724 * @ctxt: the schema parser context | |
| 15725 * @type: the simple type definition | |
| 15726 * | |
| 15727 * Checks crc-simple-type constraints. | |
| 15728 * | |
| 15729 * Returns 0 if the constraints are satisfied, | |
| 15730 * if not a positive error code and -1 on internal | |
| 15731 * errors. | |
| 15732 */ | |
| 15733 #if 0 | |
| 15734 static int | |
| 15735 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt, | |
| 15736 xmlSchemaTypePtr type) | |
| 15737 { | |
| 15738 /* | |
| 15739 * src-simple-type.1 The corresponding simple type definition, if any, | |
| 15740 * must satisfy the conditions set out in Constraints on Simple Type | |
| 15741 * Definition Schema Components ($3.14.6). | |
| 15742 */ | |
| 15743 if (WXS_IS_RESTRICTION(type)) { | |
| 15744 /* | |
| 15745 * src-simple-type.2 "If the <restriction> alternative is chosen, | |
| 15746 * either it must have a base [attribute] or a <simpleType> among its | |
| 15747 * [children], but not both." | |
| 15748 * NOTE: This is checked in the parse function of <restriction>. | |
| 15749 */ | |
| 15750 /* | |
| 15751 * | |
| 15752 */ | |
| 15753 } else if (WXS_IS_LIST(type)) { | |
| 15754 /* src-simple-type.3 "If the <list> alternative is chosen, either it mus
t have | |
| 15755 * an itemType [attribute] or a <simpleType> among its [children], | |
| 15756 * but not both." | |
| 15757 * | |
| 15758 * NOTE: This is checked in the parse function of <list>. | |
| 15759 */ | |
| 15760 } else if (WXS_IS_UNION(type)) { | |
| 15761 /* | |
| 15762 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular(). | |
| 15763 */ | |
| 15764 } | |
| 15765 return (0); | |
| 15766 } | |
| 15767 #endif | |
| 15768 | |
| 15769 static int | |
| 15770 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt) | |
| 15771 { | |
| 15772 if (ctxt->vctxt == NULL) { | |
| 15773 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL); | |
| 15774 if (ctxt->vctxt == NULL) { | |
| 15775 xmlSchemaPErr(ctxt, NULL, | |
| 15776 XML_SCHEMAP_INTERNAL, | |
| 15777 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, " | |
| 15778 "failed to create a temp. validation context.\n", | |
| 15779 NULL, NULL); | |
| 15780 return (-1); | |
| 15781 } | |
| 15782 /* TODO: Pass user data. */ | |
| 15783 xmlSchemaSetValidErrors(ctxt->vctxt, | |
| 15784 ctxt->error, ctxt->warning, ctxt->errCtxt); | |
| 15785 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, | |
| 15786 ctxt->serror, ctxt->errCtxt); | |
| 15787 } | |
| 15788 return (0); | |
| 15789 } | |
| 15790 | |
| 15791 static int | |
| 15792 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt, | |
| 15793 xmlNodePtr node, | |
| 15794 xmlSchemaTypePtr type, | |
| 15795 const xmlChar *value, | |
| 15796 xmlSchemaValPtr *retVal, | |
| 15797 int fireErrors, | |
| 15798 int normalize, | |
| 15799 int isNormalized); | |
| 15800 | |
| 15801 /** | |
| 15802 * xmlSchemaParseCheckCOSValidDefault: | |
| 15803 * @pctxt: the schema parser context | |
| 15804 * @type: the simple type definition | |
| 15805 * @value: the default value | |
| 15806 * @node: an optional node (the holder of the value) | |
| 15807 * | |
| 15808 * Schema Component Constraint: Element Default Valid (Immediate) | |
| 15809 * (cos-valid-default) | |
| 15810 * This will be used by the parser only. For the validator there's | |
| 15811 * an other version. | |
| 15812 * | |
| 15813 * Returns 0 if the constraints are satisfied, | |
| 15814 * if not, a positive error code and -1 on internal | |
| 15815 * errors. | |
| 15816 */ | |
| 15817 static int | |
| 15818 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt, | |
| 15819 xmlNodePtr node, | |
| 15820 xmlSchemaTypePtr type, | |
| 15821 const xmlChar *value, | |
| 15822 xmlSchemaValPtr *val) | |
| 15823 { | |
| 15824 int ret = 0; | |
| 15825 | |
| 15826 /* | |
| 15827 * cos-valid-default: | |
| 15828 * Schema Component Constraint: Element Default Valid (Immediate) | |
| 15829 * For a string to be a valid default with respect to a type | |
| 15830 * definition the appropriate case among the following must be true: | |
| 15831 */ | |
| 15832 if WXS_IS_COMPLEX(type) { | |
| 15833 /* | |
| 15834 * Complex type. | |
| 15835 * | |
| 15836 * SPEC (2.1) "its {content type} must be a simple type definition | |
| 15837 * or mixed." | |
| 15838 * SPEC (2.2.2) "If the {content type} is mixed, then the {content | |
| 15839 * type}'s particle must be `emptiable` as defined by | |
| 15840 * Particle Emptiable ($3.9.6)." | |
| 15841 */ | |
| 15842 if ((! WXS_HAS_SIMPLE_CONTENT(type)) && | |
| 15843 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) { | |
| 15844 /* NOTE that this covers (2.2.2) as well. */ | |
| 15845 xmlSchemaPCustomErr(pctxt, | |
| 15846 XML_SCHEMAP_COS_VALID_DEFAULT_2_1, | |
| 15847 WXS_BASIC_CAST type, type->node, | |
| 15848 "For a string to be a valid default, the type definition " | |
| 15849 "must be a simple type or a complex type with mixed content " | |
| 15850 "and a particle emptiable", NULL); | |
| 15851 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1); | |
| 15852 } | |
| 15853 } | |
| 15854 /* | |
| 15855 * 1 If the type definition is a simple type definition, then the string | |
| 15856 * must be `valid` with respect to that definition as defined by String | |
| 15857 * Valid ($3.14.4). | |
| 15858 * | |
| 15859 * AND | |
| 15860 * | |
| 15861 * 2.2.1 If the {content type} is a simple type definition, then the | |
| 15862 * string must be `valid` with respect to that simple type definition | |
| 15863 * as defined by String Valid ($3.14.4). | |
| 15864 */ | |
| 15865 if (WXS_IS_SIMPLE(type)) | |
| 15866 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node, | |
| 15867 type, value, val, 1, 1, 0); | |
| 15868 else if (WXS_HAS_SIMPLE_CONTENT(type)) | |
| 15869 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node, | |
| 15870 type->contentTypeDef, value, val, 1, 1, 0); | |
| 15871 else | |
| 15872 return (ret); | |
| 15873 | |
| 15874 if (ret < 0) { | |
| 15875 PERROR_INT("xmlSchemaParseCheckCOSValidDefault", | |
| 15876 "calling xmlSchemaVCheckCVCSimpleType()"); | |
| 15877 } | |
| 15878 | |
| 15879 return (ret); | |
| 15880 } | |
| 15881 | |
| 15882 /** | |
| 15883 * xmlSchemaCheckCTPropsCorrect: | |
| 15884 * @ctxt: the schema parser context | |
| 15885 * @type: the complex type definition | |
| 15886 * | |
| 15887 *.(4.6) Constraints on Complex Type Definition Schema Components | |
| 15888 * Schema Component Constraint: | |
| 15889 * Complex Type Definition Properties Correct (ct-props-correct) | |
| 15890 * STATUS: (seems) complete | |
| 15891 * | |
| 15892 * Returns 0 if the constraints are satisfied, a positive | |
| 15893 * error code if not and -1 if an internal error occured. | |
| 15894 */ | |
| 15895 static int | |
| 15896 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt, | |
| 15897 xmlSchemaTypePtr type) | |
| 15898 { | |
| 15899 /* | |
| 15900 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily. | |
| 15901 * | |
| 15902 * SPEC (1) "The values of the properties of a complex type definition must | |
| 15903 * be as described in the property tableau in The Complex Type Definition | |
| 15904 * Schema Component ($3.4.1), modulo the impact of Missing | |
| 15905 * Sub-components ($5.3)." | |
| 15906 */ | |
| 15907 if ((type->baseType != NULL) && | |
| 15908 (WXS_IS_SIMPLE(type->baseType)) && | |
| 15909 (WXS_IS_EXTENSION(type) == 0)) { | |
| 15910 /* | |
| 15911 * SPEC (2) "If the {base type definition} is a simple type definition, | |
| 15912 * the {derivation method} must be extension." | |
| 15913 */ | |
| 15914 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 15915 XML_SCHEMAP_SRC_CT_1, | |
| 15916 NULL, WXS_BASIC_CAST type, | |
| 15917 "If the base type is a simple type, the derivation method must be " | |
| 15918 "'extension'", NULL, NULL); | |
| 15919 return (XML_SCHEMAP_SRC_CT_1); | |
| 15920 } | |
| 15921 /* | |
| 15922 * SPEC (3) "Circular definitions are disallowed, except for the `ur-type | |
| 15923 * definition`. That is, it must be possible to reach the `ur-type | |
| 15924 * definition` by repeatedly following the {base type definition}." | |
| 15925 * | |
| 15926 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular(). | |
| 15927 */ | |
| 15928 /* | |
| 15929 * NOTE that (4) and (5) need the following: | |
| 15930 * - attribute uses need to be already inherited (apply attr. prohibitions) | |
| 15931 * - attribute group references need to be expanded already | |
| 15932 * - simple types need to be typefixed already | |
| 15933 */ | |
| 15934 if (type->attrUses && | |
| 15935 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1)) | |
| 15936 { | |
| 15937 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses; | |
| 15938 xmlSchemaAttributeUsePtr use, tmp; | |
| 15939 int i, j, hasId = 0; | |
| 15940 | |
| 15941 for (i = uses->nbItems -1; i >= 0; i--) { | |
| 15942 use = uses->items[i]; | |
| 15943 | |
| 15944 /* | |
| 15945 * SPEC ct-props-correct | |
| 15946 * (4) "Two distinct attribute declarations in the | |
| 15947 * {attribute uses} must not have identical {name}s and | |
| 15948 * {target namespace}s." | |
| 15949 */ | |
| 15950 if (i > 0) { | |
| 15951 for (j = i -1; j >= 0; j--) { | |
| 15952 tmp = uses->items[j]; | |
| 15953 if ((WXS_ATTRUSE_DECL_NAME(use) == | |
| 15954 WXS_ATTRUSE_DECL_NAME(tmp)) && | |
| 15955 (WXS_ATTRUSE_DECL_TNS(use) == | |
| 15956 WXS_ATTRUSE_DECL_TNS(tmp))) | |
| 15957 { | |
| 15958 xmlChar *str = NULL; | |
| 15959 | |
| 15960 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 15961 XML_SCHEMAP_AG_PROPS_CORRECT, | |
| 15962 NULL, WXS_BASIC_CAST type, | |
| 15963 "Duplicate %s", | |
| 15964 xmlSchemaGetComponentDesignation(&str, use), | |
| 15965 NULL); | |
| 15966 FREE_AND_NULL(str); | |
| 15967 /* | |
| 15968 * Remove the duplicate. | |
| 15969 */ | |
| 15970 if (xmlSchemaItemListRemove(uses, i) == -1) | |
| 15971 goto exit_failure; | |
| 15972 goto next_use; | |
| 15973 } | |
| 15974 } | |
| 15975 } | |
| 15976 /* | |
| 15977 * SPEC ct-props-correct | |
| 15978 * (5) "Two distinct attribute declarations in the | |
| 15979 * {attribute uses} must not have {type definition}s which | |
| 15980 * are or are derived from ID." | |
| 15981 */ | |
| 15982 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) { | |
| 15983 if (xmlSchemaIsDerivedFromBuiltInType( | |
| 15984 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID)) | |
| 15985 { | |
| 15986 if (hasId) { | |
| 15987 xmlChar *str = NULL; | |
| 15988 | |
| 15989 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 15990 XML_SCHEMAP_AG_PROPS_CORRECT, | |
| 15991 NULL, WXS_BASIC_CAST type, | |
| 15992 "There must not exist more than one attribute " | |
| 15993 "declaration of type 'xs:ID' " | |
| 15994 "(or derived from 'xs:ID'). The %s violates this " | |
| 15995 "constraint", | |
| 15996 xmlSchemaGetComponentDesignation(&str, use), | |
| 15997 NULL); | |
| 15998 FREE_AND_NULL(str); | |
| 15999 if (xmlSchemaItemListRemove(uses, i) == -1) | |
| 16000 goto exit_failure; | |
| 16001 } | |
| 16002 | |
| 16003 hasId = 1; | |
| 16004 } | |
| 16005 } | |
| 16006 next_use: {} | |
| 16007 } | |
| 16008 } | |
| 16009 return (0); | |
| 16010 exit_failure: | |
| 16011 return(-1); | |
| 16012 } | |
| 16013 | |
| 16014 static int | |
| 16015 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA, | |
| 16016 xmlSchemaTypePtr typeB) | |
| 16017 { | |
| 16018 /* | |
| 16019 * TODO: This should implement component-identity | |
| 16020 * in the future. | |
| 16021 */ | |
| 16022 if ((typeA == NULL) || (typeB == NULL)) | |
| 16023 return (0); | |
| 16024 return (typeA == typeB); | |
| 16025 } | |
| 16026 | |
| 16027 /** | |
| 16028 * xmlSchemaCheckCOSCTDerivedOK: | |
| 16029 * @ctxt: the schema parser context | |
| 16030 * @type: the to-be derived complex type definition | |
| 16031 * @baseType: the base complex type definition | |
| 16032 * @set: the given set | |
| 16033 * | |
| 16034 * Schema Component Constraint: | |
| 16035 * Type Derivation OK (Complex) (cos-ct-derived-ok) | |
| 16036 * | |
| 16037 * STATUS: completed | |
| 16038 * | |
| 16039 * Returns 0 if the constraints are satisfied, or 1 | |
| 16040 * if not. | |
| 16041 */ | |
| 16042 static int | |
| 16043 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt, | |
| 16044 xmlSchemaTypePtr type, | |
| 16045 xmlSchemaTypePtr baseType, | |
| 16046 int set) | |
| 16047 { | |
| 16048 int equal = xmlSchemaAreEqualTypes(type, baseType); | |
| 16049 /* TODO: Error codes. */ | |
| 16050 /* | |
| 16051 * SPEC "For a complex type definition (call it D, for derived) | |
| 16052 * to be validly derived from a type definition (call this | |
| 16053 * B, for base) given a subset of {extension, restriction} | |
| 16054 * all of the following must be true:" | |
| 16055 */ | |
| 16056 if (! equal) { | |
| 16057 /* | |
| 16058 * SPEC (1) "If B and D are not the same type definition, then the | |
| 16059 * {derivation method} of D must not be in the subset." | |
| 16060 */ | |
| 16061 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) || | |
| 16062 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type)))) | |
| 16063 return (1); | |
| 16064 } else { | |
| 16065 /* | |
| 16066 * SPEC (2.1) "B and D must be the same type definition." | |
| 16067 */ | |
| 16068 return (0); | |
| 16069 } | |
| 16070 /* | |
| 16071 * SPEC (2.2) "B must be D's {base type definition}." | |
| 16072 */ | |
| 16073 if (type->baseType == baseType) | |
| 16074 return (0); | |
| 16075 /* | |
| 16076 * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type | |
| 16077 * definition`." | |
| 16078 */ | |
| 16079 if (WXS_IS_ANYTYPE(type->baseType)) | |
| 16080 return (1); | |
| 16081 | |
| 16082 if (WXS_IS_COMPLEX(type->baseType)) { | |
| 16083 /* | |
| 16084 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it | |
| 16085 * must be validly derived from B given the subset as defined by this | |
| 16086 * constraint." | |
| 16087 */ | |
| 16088 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType, | |
| 16089 baseType, set)); | |
| 16090 } else { | |
| 16091 /* | |
| 16092 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it | |
| 16093 * must be validly derived from B given the subset as defined in Type | |
| 16094 * Derivation OK (Simple) ($3.14.6). | |
| 16095 */ | |
| 16096 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType, | |
| 16097 baseType, set)); | |
| 16098 } | |
| 16099 } | |
| 16100 | |
| 16101 /** | |
| 16102 * xmlSchemaCheckCOSDerivedOK: | |
| 16103 * @type: the derived simple type definition | |
| 16104 * @baseType: the base type definition | |
| 16105 * | |
| 16106 * Calls: | |
| 16107 * Type Derivation OK (Simple) AND Type Derivation OK (Complex) | |
| 16108 * | |
| 16109 * Checks wheter @type can be validly derived from @baseType. | |
| 16110 * | |
| 16111 * Returns 0 on success, an positive error code otherwise. | |
| 16112 */ | |
| 16113 static int | |
| 16114 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt, | |
| 16115 xmlSchemaTypePtr type, | |
| 16116 xmlSchemaTypePtr baseType, | |
| 16117 int set) | |
| 16118 { | |
| 16119 if (WXS_IS_SIMPLE(type)) | |
| 16120 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set)); | |
| 16121 else | |
| 16122 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set)); | |
| 16123 } | |
| 16124 | |
| 16125 /** | |
| 16126 * xmlSchemaCheckCOSCTExtends: | |
| 16127 * @ctxt: the schema parser context | |
| 16128 * @type: the complex type definition | |
| 16129 * | |
| 16130 * (3.4.6) Constraints on Complex Type Definition Schema Components | |
| 16131 * Schema Component Constraint: | |
| 16132 * Derivation Valid (Extension) (cos-ct-extends) | |
| 16133 * | |
| 16134 * STATUS: | |
| 16135 * missing: | |
| 16136 * (1.5) | |
| 16137 * (1.4.3.2.2.2) "Particle Valid (Extension)" | |
| 16138 * | |
| 16139 * Returns 0 if the constraints are satisfied, a positive | |
| 16140 * error code if not and -1 if an internal error occured. | |
| 16141 */ | |
| 16142 static int | |
| 16143 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt, | |
| 16144 xmlSchemaTypePtr type) | |
| 16145 { | |
| 16146 xmlSchemaTypePtr base = type->baseType; | |
| 16147 /* | |
| 16148 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used | |
| 16149 * temporarily only. | |
| 16150 */ | |
| 16151 /* | |
| 16152 * SPEC (1) "If the {base type definition} is a complex type definition, | |
| 16153 * then all of the following must be true:" | |
| 16154 */ | |
| 16155 if (WXS_IS_COMPLEX(base)) { | |
| 16156 /* | |
| 16157 * SPEC (1.1) "The {final} of the {base type definition} must not | |
| 16158 * contain extension." | |
| 16159 */ | |
| 16160 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) { | |
| 16161 xmlSchemaPCustomErr(ctxt, | |
| 16162 XML_SCHEMAP_COS_CT_EXTENDS_1_1, | |
| 16163 WXS_BASIC_CAST type, NULL, | |
| 16164 "The 'final' of the base type definition " | |
| 16165 "contains 'extension'", NULL); | |
| 16166 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); | |
| 16167 } | |
| 16168 | |
| 16169 /* | |
| 16170 * ATTENTION: The constrains (1.2) and (1.3) are not applied, | |
| 16171 * since they are automatically satisfied through the | |
| 16172 * inheriting mechanism. | |
| 16173 * Note that even if redefining components, the inheriting mechanism | |
| 16174 * is used. | |
| 16175 */ | |
| 16176 #if 0 | |
| 16177 /* | |
| 16178 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute | |
| 16179 * uses} | |
| 16180 * of the complex type definition itself, that is, for every attribute | |
| 16181 * use in the {attribute uses} of the {base type definition}, there | |
| 16182 * must be an attribute use in the {attribute uses} of the complex | |
| 16183 * type definition itself whose {attribute declaration} has the same | |
| 16184 * {name}, {target namespace} and {type definition} as its attribute | |
| 16185 * declaration" | |
| 16186 */ | |
| 16187 if (base->attrUses != NULL) { | |
| 16188 int i, j, found; | |
| 16189 xmlSchemaAttributeUsePtr use, buse; | |
| 16190 | |
| 16191 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) { | |
| 16192 buse = (WXS_LIST_CAST base->attrUses)->items[i]; | |
| 16193 found = 0; | |
| 16194 if (type->attrUses != NULL) { | |
| 16195 use = (WXS_LIST_CAST type->attrUses)->items[j]; | |
| 16196 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j +
+) | |
| 16197 { | |
| 16198 if ((WXS_ATTRUSE_DECL_NAME(use) == | |
| 16199 WXS_ATTRUSE_DECL_NAME(buse)) && | |
| 16200 (WXS_ATTRUSE_DECL_TNS(use) == | |
| 16201 WXS_ATTRUSE_DECL_TNS(buse)) && | |
| 16202 (WXS_ATTRUSE_TYPEDEF(use) == | |
| 16203 WXS_ATTRUSE_TYPEDEF(buse)) | |
| 16204 { | |
| 16205 found = 1; | |
| 16206 break; | |
| 16207 } | |
| 16208 } | |
| 16209 } | |
| 16210 if (! found) { | |
| 16211 xmlChar *str = NULL; | |
| 16212 | |
| 16213 xmlSchemaCustomErr(ACTXT_CAST ctxt, | |
| 16214 XML_SCHEMAP_COS_CT_EXTENDS_1_2, | |
| 16215 NULL, WXS_BASIC_CAST type, | |
| 16216 /* | |
| 16217 * TODO: The report does not indicate that also the | |
| 16218 * type needs to be the same. | |
| 16219 */ | |
| 16220 "This type is missing a matching correspondent " | |
| 16221 "for its {base type}'s %s in its {attribute uses}", | |
| 16222 xmlSchemaGetComponentDesignation(&str, | |
| 16223 buse->children), | |
| 16224 NULL); | |
| 16225 FREE_AND_NULL(str) | |
| 16226 } | |
| 16227 } | |
| 16228 } | |
| 16229 /* | |
| 16230 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type | |
| 16231 * definition must also have one, and the base type definition's | |
| 16232 * {attribute wildcard}'s {namespace constraint} must be a subset | |
| 16233 * of the complex type definition's {attribute wildcard}'s {namespace | |
| 16234 * constraint}, as defined by Wildcard Subset ($3.10.6)." | |
| 16235 */ | |
| 16236 | |
| 16237 /* | |
| 16238 * MAYBE TODO: Enable if ever needed. But this will be needed only | |
| 16239 * if created the type via a schema construction API. | |
| 16240 */ | |
| 16241 if (base->attributeWildcard != NULL) { | |
| 16242 if (type->attributeWilcard == NULL) { | |
| 16243 xmlChar *str = NULL; | |
| 16244 | |
| 16245 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 16246 XML_SCHEMAP_COS_CT_EXTENDS_1_3, | |
| 16247 NULL, type, | |
| 16248 "The base %s has an attribute wildcard, " | |
| 16249 "but this type is missing an attribute wildcard", | |
| 16250 xmlSchemaGetComponentDesignation(&str, base)); | |
| 16251 FREE_AND_NULL(str) | |
| 16252 | |
| 16253 } else if (xmlSchemaCheckCOSNSSubset( | |
| 16254 base->attributeWildcard, type->attributeWildcard)) | |
| 16255 { | |
| 16256 xmlChar *str = NULL; | |
| 16257 | |
| 16258 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 16259 XML_SCHEMAP_COS_CT_EXTENDS_1_3, | |
| 16260 NULL, type, | |
| 16261 "The attribute wildcard is not a valid " | |
| 16262 "superset of the one in the base %s", | |
| 16263 xmlSchemaGetComponentDesignation(&str, base)); | |
| 16264 FREE_AND_NULL(str) | |
| 16265 } | |
| 16266 } | |
| 16267 #endif | |
| 16268 /* | |
| 16269 * SPEC (1.4) "One of the following must be true:" | |
| 16270 */ | |
| 16271 if ((type->contentTypeDef != NULL) && | |
| 16272 (type->contentTypeDef == base->contentTypeDef)) { | |
| 16273 /* | |
| 16274 * SPEC (1.4.1) "The {content type} of the {base type definition} | |
| 16275 * and the {content type} of the complex type definition itself | |
| 16276 * must be the same simple type definition" | |
| 16277 * PASS | |
| 16278 */ | |
| 16279 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) && | |
| 16280 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) { | |
| 16281 /* | |
| 16282 * SPEC (1.4.2) "The {content type} of both the {base type | |
| 16283 * definition} and the complex type definition itself must | |
| 16284 * be empty." | |
| 16285 * PASS | |
| 16286 */ | |
| 16287 } else { | |
| 16288 /* | |
| 16289 * SPEC (1.4.3) "All of the following must be true:" | |
| 16290 */ | |
| 16291 if (type->subtypes == NULL) { | |
| 16292 /* | |
| 16293 * SPEC 1.4.3.1 The {content type} of the complex type | |
| 16294 * definition itself must specify a particle. | |
| 16295 */ | |
| 16296 xmlSchemaPCustomErr(ctxt, | |
| 16297 XML_SCHEMAP_COS_CT_EXTENDS_1_1, | |
| 16298 WXS_BASIC_CAST type, NULL, | |
| 16299 "The content type must specify a particle", NULL); | |
| 16300 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); | |
| 16301 } | |
| 16302 /* | |
| 16303 * SPEC (1.4.3.2) "One of the following must be true:" | |
| 16304 */ | |
| 16305 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) { | |
| 16306 /* | |
| 16307 * SPEC (1.4.3.2.1) "The {content type} of the {base type | |
| 16308 * definition} must be empty. | |
| 16309 * PASS | |
| 16310 */ | |
| 16311 } else { | |
| 16312 /* | |
| 16313 * SPEC (1.4.3.2.2) "All of the following must be true:" | |
| 16314 */ | |
| 16315 if ((type->contentType != base->contentType) || | |
| 16316 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) && | |
| 16317 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) { | |
| 16318 /* | |
| 16319 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed | |
| 16320 * or both must be element-only." | |
| 16321 */ | |
| 16322 xmlSchemaPCustomErr(ctxt, | |
| 16323 XML_SCHEMAP_COS_CT_EXTENDS_1_1, | |
| 16324 WXS_BASIC_CAST type, NULL, | |
| 16325 "The content type of both, the type and its base " | |
| 16326 "type, must either 'mixed' or 'element-only'", NULL); | |
| 16327 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); | |
| 16328 } | |
| 16329 /* | |
| 16330 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the | |
| 16331 * complex type definition must be a `valid extension` | |
| 16332 * of the {base type definition}'s particle, as defined | |
| 16333 * in Particle Valid (Extension) ($3.9.6)." | |
| 16334 * | |
| 16335 * NOTE that we won't check "Particle Valid (Extension)", | |
| 16336 * since it is ensured by the derivation process in | |
| 16337 * xmlSchemaTypeFixup(). We need to implement this when heading | |
| 16338 * for a construction API | |
| 16339 * TODO: !! This is needed to be checked if redefining a type !! | |
| 16340 */ | |
| 16341 } | |
| 16342 /* | |
| 16343 * URGENT TODO (1.5) | |
| 16344 */ | |
| 16345 } | |
| 16346 } else { | |
| 16347 /* | |
| 16348 * SPEC (2) "If the {base type definition} is a simple type definition, | |
| 16349 * then all of the following must be true:" | |
| 16350 */ | |
| 16351 if (type->contentTypeDef != base) { | |
| 16352 /* | |
| 16353 * SPEC (2.1) "The {content type} must be the same simple type | |
| 16354 * definition." | |
| 16355 */ | |
| 16356 xmlSchemaPCustomErr(ctxt, | |
| 16357 XML_SCHEMAP_COS_CT_EXTENDS_1_1, | |
| 16358 WXS_BASIC_CAST type, NULL, | |
| 16359 "The content type must be the simple base type", NULL); | |
| 16360 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); | |
| 16361 } | |
| 16362 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) { | |
| 16363 /* | |
| 16364 * SPEC (2.2) "The {final} of the {base type definition} must not | |
| 16365 * contain extension" | |
| 16366 * NOTE that this is the same as (1.1). | |
| 16367 */ | |
| 16368 xmlSchemaPCustomErr(ctxt, | |
| 16369 XML_SCHEMAP_COS_CT_EXTENDS_1_1, | |
| 16370 WXS_BASIC_CAST type, NULL, | |
| 16371 "The 'final' of the base type definition " | |
| 16372 "contains 'extension'", NULL); | |
| 16373 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); | |
| 16374 } | |
| 16375 } | |
| 16376 return (0); | |
| 16377 } | |
| 16378 | |
| 16379 /** | |
| 16380 * xmlSchemaCheckDerivationOKRestriction: | |
| 16381 * @ctxt: the schema parser context | |
| 16382 * @type: the complex type definition | |
| 16383 * | |
| 16384 * (3.4.6) Constraints on Complex Type Definition Schema Components | |
| 16385 * Schema Component Constraint: | |
| 16386 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction) | |
| 16387 * | |
| 16388 * STATUS: | |
| 16389 * missing: | |
| 16390 * (5.4.2) ??? | |
| 16391 * | |
| 16392 * ATTENTION: | |
| 16393 * In XML Schema 1.1 this will be: | |
| 16394 * Validation Rule: Checking complex type subsumption | |
| 16395 * | |
| 16396 * Returns 0 if the constraints are satisfied, a positive | |
| 16397 * error code if not and -1 if an internal error occured. | |
| 16398 */ | |
| 16399 static int | |
| 16400 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt, | |
| 16401 xmlSchemaTypePtr type) | |
| 16402 { | |
| 16403 xmlSchemaTypePtr base; | |
| 16404 | |
| 16405 /* | |
| 16406 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is u
sed | |
| 16407 * temporarily only. | |
| 16408 */ | |
| 16409 base = type->baseType; | |
| 16410 if (! WXS_IS_COMPLEX(base)) { | |
| 16411 xmlSchemaCustomErr(ACTXT_CAST ctxt, | |
| 16412 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | |
| 16413 type->node, WXS_BASIC_CAST type, | |
| 16414 "The base type must be a complex type", NULL, NULL); | |
| 16415 return(ctxt->err); | |
| 16416 } | |
| 16417 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) { | |
| 16418 /* | |
| 16419 * SPEC (1) "The {base type definition} must be a complex type | |
| 16420 * definition whose {final} does not contain restriction." | |
| 16421 */ | |
| 16422 xmlSchemaCustomErr(ACTXT_CAST ctxt, | |
| 16423 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | |
| 16424 type->node, WXS_BASIC_CAST type, | |
| 16425 "The 'final' of the base type definition " | |
| 16426 "contains 'restriction'", NULL, NULL); | |
| 16427 return (ctxt->err); | |
| 16428 } | |
| 16429 /* | |
| 16430 * SPEC (2), (3) and (4) | |
| 16431 * Those are handled in a separate function, since the | |
| 16432 * same constraints are needed for redefinition of | |
| 16433 * attribute groups as well. | |
| 16434 */ | |
| 16435 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt, | |
| 16436 XML_SCHEMA_ACTION_DERIVE, | |
| 16437 WXS_BASIC_CAST type, WXS_BASIC_CAST base, | |
| 16438 type->attrUses, base->attrUses, | |
| 16439 type->attributeWildcard, | |
| 16440 base->attributeWildcard) == -1) | |
| 16441 { | |
| 16442 return(-1); | |
| 16443 } | |
| 16444 /* | |
| 16445 * SPEC (5) "One of the following must be true:" | |
| 16446 */ | |
| 16447 if (base->builtInType == XML_SCHEMAS_ANYTYPE) { | |
| 16448 /* | |
| 16449 * SPEC (5.1) "The {base type definition} must be the | |
| 16450 * `ur-type definition`." | |
| 16451 * PASS | |
| 16452 */ | |
| 16453 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) || | |
| 16454 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) { | |
| 16455 /* | |
| 16456 * SPEC (5.2.1) "The {content type} of the complex type definition | |
| 16457 * must be a simple type definition" | |
| 16458 * | |
| 16459 * SPEC (5.2.2) "One of the following must be true:" | |
| 16460 */ | |
| 16461 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) || | |
| 16462 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) | |
| 16463 { | |
| 16464 int err; | |
| 16465 /* | |
| 16466 * SPEC (5.2.2.1) "The {content type} of the {base type | |
| 16467 * definition} must be a simple type definition from which | |
| 16468 * the {content type} is validly derived given the empty | |
| 16469 * set as defined in Type Derivation OK (Simple) ($3.14.6)." | |
| 16470 * | |
| 16471 * ATTENTION TODO: This seems not needed if the type implicitely | |
| 16472 * derived from the base type. | |
| 16473 * | |
| 16474 */ | |
| 16475 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt, | |
| 16476 type->contentTypeDef, base->contentTypeDef, 0); | |
| 16477 if (err != 0) { | |
| 16478 xmlChar *strA = NULL, *strB = NULL; | |
| 16479 | |
| 16480 if (err == -1) | |
| 16481 return(-1); | |
| 16482 xmlSchemaCustomErr(ACTXT_CAST ctxt, | |
| 16483 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | |
| 16484 NULL, WXS_BASIC_CAST type, | |
| 16485 "The {content type} %s is not validly derived from the " | |
| 16486 "base type's {content type} %s", | |
| 16487 xmlSchemaGetComponentDesignation(&strA, | |
| 16488 type->contentTypeDef), | |
| 16489 xmlSchemaGetComponentDesignation(&strB, | |
| 16490 base->contentTypeDef)); | |
| 16491 FREE_AND_NULL(strA); | |
| 16492 FREE_AND_NULL(strB); | |
| 16493 return(ctxt->err); | |
| 16494 } | |
| 16495 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) && | |
| 16496 (xmlSchemaIsParticleEmptiable( | |
| 16497 (xmlSchemaParticlePtr) base->subtypes))) { | |
| 16498 /* | |
| 16499 * SPEC (5.2.2.2) "The {base type definition} must be mixed | |
| 16500 * and have a particle which is `emptiable` as defined in | |
| 16501 * Particle Emptiable ($3.9.6)." | |
| 16502 * PASS | |
| 16503 */ | |
| 16504 } else { | |
| 16505 xmlSchemaPCustomErr(ctxt, | |
| 16506 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | |
| 16507 WXS_BASIC_CAST type, NULL, | |
| 16508 "The content type of the base type must be either " | |
| 16509 "a simple type or 'mixed' and an emptiable particle", NULL); | |
| 16510 return (ctxt->err); | |
| 16511 } | |
| 16512 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) { | |
| 16513 /* | |
| 16514 * SPEC (5.3.1) "The {content type} of the complex type itself must | |
| 16515 * be empty" | |
| 16516 */ | |
| 16517 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) { | |
| 16518 /* | |
| 16519 * SPEC (5.3.2.1) "The {content type} of the {base type | |
| 16520 * definition} must also be empty." | |
| 16521 * PASS | |
| 16522 */ | |
| 16523 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) || | |
| 16524 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) && | |
| 16525 xmlSchemaIsParticleEmptiable( | |
| 16526 (xmlSchemaParticlePtr) base->subtypes)) { | |
| 16527 /* | |
| 16528 * SPEC (5.3.2.2) "The {content type} of the {base type | |
| 16529 * definition} must be elementOnly or mixed and have a particle | |
| 16530 * which is `emptiable` as defined in Particle Emptiable ($3.9.6)." | |
| 16531 * PASS | |
| 16532 */ | |
| 16533 } else { | |
| 16534 xmlSchemaPCustomErr(ctxt, | |
| 16535 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | |
| 16536 WXS_BASIC_CAST type, NULL, | |
| 16537 "The content type of the base type must be either " | |
| 16538 "empty or 'mixed' (or 'elements-only') and an emptiable " | |
| 16539 "particle", NULL); | |
| 16540 return (ctxt->err); | |
| 16541 } | |
| 16542 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) || | |
| 16543 WXS_HAS_MIXED_CONTENT(type)) { | |
| 16544 /* | |
| 16545 * SPEC (5.4.1.1) "The {content type} of the complex type definition | |
| 16546 * itself must be element-only" | |
| 16547 */ | |
| 16548 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) { | |
| 16549 /* | |
| 16550 * SPEC (5.4.1.2) "The {content type} of the complex type | |
| 16551 * definition itself and of the {base type definition} must be | |
| 16552 * mixed" | |
| 16553 */ | |
| 16554 xmlSchemaPCustomErr(ctxt, | |
| 16555 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | |
| 16556 WXS_BASIC_CAST type, NULL, | |
| 16557 "If the content type is 'mixed', then the content type of the " | |
| 16558 "base type must also be 'mixed'", NULL); | |
| 16559 return (ctxt->err); | |
| 16560 } | |
| 16561 /* | |
| 16562 * SPEC (5.4.2) "The particle of the complex type definition itself | |
| 16563 * must be a `valid restriction` of the particle of the {content | |
| 16564 * type} of the {base type definition} as defined in Particle Valid | |
| 16565 * (Restriction) ($3.9.6). | |
| 16566 * | |
| 16567 * URGENT TODO: (5.4.2) | |
| 16568 */ | |
| 16569 } else { | |
| 16570 xmlSchemaPCustomErr(ctxt, | |
| 16571 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | |
| 16572 WXS_BASIC_CAST type, NULL, | |
| 16573 "The type is not a valid restriction of its base type", NULL); | |
| 16574 return (ctxt->err); | |
| 16575 } | |
| 16576 return (0); | |
| 16577 } | |
| 16578 | |
| 16579 /** | |
| 16580 * xmlSchemaCheckCTComponent: | |
| 16581 * @ctxt: the schema parser context | |
| 16582 * @type: the complex type definition | |
| 16583 * | |
| 16584 * (3.4.6) Constraints on Complex Type Definition Schema Components | |
| 16585 * | |
| 16586 * Returns 0 if the constraints are satisfied, a positive | |
| 16587 * error code if not and -1 if an internal error occured. | |
| 16588 */ | |
| 16589 static int | |
| 16590 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt, | |
| 16591 xmlSchemaTypePtr type) | |
| 16592 { | |
| 16593 int ret; | |
| 16594 /* | |
| 16595 * Complex Type Definition Properties Correct | |
| 16596 */ | |
| 16597 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type); | |
| 16598 if (ret != 0) | |
| 16599 return (ret); | |
| 16600 if (WXS_IS_EXTENSION(type)) | |
| 16601 ret = xmlSchemaCheckCOSCTExtends(ctxt, type); | |
| 16602 else | |
| 16603 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type); | |
| 16604 return (ret); | |
| 16605 } | |
| 16606 | |
| 16607 /** | |
| 16608 * xmlSchemaCheckSRCCT: | |
| 16609 * @ctxt: the schema parser context | |
| 16610 * @type: the complex type definition | |
| 16611 * | |
| 16612 * (3.4.3) Constraints on XML Representations of Complex Type Definitions: | |
| 16613 * Schema Representation Constraint: | |
| 16614 * Complex Type Definition Representation OK (src-ct) | |
| 16615 * | |
| 16616 * Returns 0 if the constraints are satisfied, a positive | |
| 16617 * error code if not and -1 if an internal error occured. | |
| 16618 */ | |
| 16619 static int | |
| 16620 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt, | |
| 16621 xmlSchemaTypePtr type) | |
| 16622 { | |
| 16623 xmlSchemaTypePtr base; | |
| 16624 int ret = 0; | |
| 16625 | |
| 16626 /* | |
| 16627 * TODO: Adjust the error codes here, as I used | |
| 16628 * XML_SCHEMAP_SRC_CT_1 only yet. | |
| 16629 */ | |
| 16630 base = type->baseType; | |
| 16631 if (! WXS_HAS_SIMPLE_CONTENT(type)) { | |
| 16632 /* | |
| 16633 * 1 If the <complexContent> alternative is chosen, the type definition | |
| 16634 * `resolved` to by the `actual value` of the base [attribute] | |
| 16635 * must be a complex type definition; | |
| 16636 */ | |
| 16637 if (! WXS_IS_COMPLEX(base)) { | |
| 16638 xmlChar *str = NULL; | |
| 16639 xmlSchemaPCustomErr(ctxt, | |
| 16640 XML_SCHEMAP_SRC_CT_1, | |
| 16641 WXS_BASIC_CAST type, type->node, | |
| 16642 "If using <complexContent>, the base type is expected to be " | |
| 16643 "a complex type. The base type '%s' is a simple type", | |
| 16644 xmlSchemaFormatQName(&str, base->targetNamespace, | |
| 16645 base->name)); | |
| 16646 FREE_AND_NULL(str) | |
| 16647 return (XML_SCHEMAP_SRC_CT_1); | |
| 16648 } | |
| 16649 } else { | |
| 16650 /* | |
| 16651 * SPEC | |
| 16652 * 2 If the <simpleContent> alternative is chosen, all of the | |
| 16653 * following must be true: | |
| 16654 * 2.1 The type definition `resolved` to by the `actual value` of the | |
| 16655 * base [attribute] must be one of the following: | |
| 16656 */ | |
| 16657 if (WXS_IS_SIMPLE(base)) { | |
| 16658 if (WXS_IS_EXTENSION(type) == 0) { | |
| 16659 xmlChar *str = NULL; | |
| 16660 /* | |
| 16661 * 2.1.3 only if the <extension> alternative is also | |
| 16662 * chosen, a simple type definition. | |
| 16663 */ | |
| 16664 /* TODO: Change error code to ..._SRC_CT_2_1_3. */ | |
| 16665 xmlSchemaPCustomErr(ctxt, | |
| 16666 XML_SCHEMAP_SRC_CT_1, | |
| 16667 WXS_BASIC_CAST type, NULL, | |
| 16668 "If using <simpleContent> and <restriction>, the base " | |
| 16669 "type must be a complex type. The base type '%s' is " | |
| 16670 "a simple type", | |
| 16671 xmlSchemaFormatQName(&str, base->targetNamespace, | |
| 16672 base->name)); | |
| 16673 FREE_AND_NULL(str) | |
| 16674 return (XML_SCHEMAP_SRC_CT_1); | |
| 16675 } | |
| 16676 } else { | |
| 16677 /* Base type is a complex type. */ | |
| 16678 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) || | |
| 16679 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) { | |
| 16680 /* | |
| 16681 * 2.1.1 a complex type definition whose {content type} is a | |
| 16682 * simple type definition; | |
| 16683 * PASS | |
| 16684 */ | |
| 16685 if (base->contentTypeDef == NULL) { | |
| 16686 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, | |
| 16687 WXS_BASIC_CAST type, NULL, | |
| 16688 "Internal error: xmlSchemaCheckSRCCT, " | |
| 16689 "'%s', base type has no content type", | |
| 16690 type->name); | |
| 16691 return (-1); | |
| 16692 } | |
| 16693 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) && | |
| 16694 (WXS_IS_RESTRICTION(type))) { | |
| 16695 | |
| 16696 /* | |
| 16697 * 2.1.2 only if the <restriction> alternative is also | |
| 16698 * chosen, a complex type definition whose {content type} | |
| 16699 * is mixed and a particle emptiable. | |
| 16700 */ | |
| 16701 if (! xmlSchemaIsParticleEmptiable( | |
| 16702 (xmlSchemaParticlePtr) base->subtypes)) { | |
| 16703 ret = XML_SCHEMAP_SRC_CT_1; | |
| 16704 } else | |
| 16705 /* | |
| 16706 * Attention: at this point the <simpleType> child is in | |
| 16707 * ->contentTypeDef (put there during parsing). | |
| 16708 */ | |
| 16709 if (type->contentTypeDef == NULL) { | |
| 16710 xmlChar *str = NULL; | |
| 16711 /* | |
| 16712 * 2.2 If clause 2.1.2 above is satisfied, then there | |
| 16713 * must be a <simpleType> among the [children] of | |
| 16714 * <restriction>. | |
| 16715 */ | |
| 16716 /* TODO: Change error code to ..._SRC_CT_2_2. */ | |
| 16717 xmlSchemaPCustomErr(ctxt, | |
| 16718 XML_SCHEMAP_SRC_CT_1, | |
| 16719 WXS_BASIC_CAST type, NULL, | |
| 16720 "A <simpleType> is expected among the children " | |
| 16721 "of <restriction>, if <simpleContent> is used and " | |
| 16722 "the base type '%s' is a complex type", | |
| 16723 xmlSchemaFormatQName(&str, base->targetNamespace, | |
| 16724 base->name)); | |
| 16725 FREE_AND_NULL(str) | |
| 16726 return (XML_SCHEMAP_SRC_CT_1); | |
| 16727 } | |
| 16728 } else { | |
| 16729 ret = XML_SCHEMAP_SRC_CT_1; | |
| 16730 } | |
| 16731 } | |
| 16732 if (ret > 0) { | |
| 16733 xmlChar *str = NULL; | |
| 16734 if (WXS_IS_RESTRICTION(type)) { | |
| 16735 xmlSchemaPCustomErr(ctxt, | |
| 16736 XML_SCHEMAP_SRC_CT_1, | |
| 16737 WXS_BASIC_CAST type, NULL, | |
| 16738 "If <simpleContent> and <restriction> is used, the " | |
| 16739 "base type must be a simple type or a complex type with " | |
| 16740 "mixed content and particle emptiable. The base type " | |
| 16741 "'%s' is none of those", | |
| 16742 xmlSchemaFormatQName(&str, base->targetNamespace, | |
| 16743 base->name)); | |
| 16744 } else { | |
| 16745 xmlSchemaPCustomErr(ctxt, | |
| 16746 XML_SCHEMAP_SRC_CT_1, | |
| 16747 WXS_BASIC_CAST type, NULL, | |
| 16748 "If <simpleContent> and <extension> is used, the " | |
| 16749 "base type must be a simple type. The base type '%s' " | |
| 16750 "is a complex type", | |
| 16751 xmlSchemaFormatQName(&str, base->targetNamespace, | |
| 16752 base->name)); | |
| 16753 } | |
| 16754 FREE_AND_NULL(str) | |
| 16755 } | |
| 16756 } | |
| 16757 /* | |
| 16758 * SPEC (3) "The corresponding complex type definition component must | |
| 16759 * satisfy the conditions set out in Constraints on Complex Type | |
| 16760 * Definition Schema Components ($3.4.6);" | |
| 16761 * NOTE (3) will be done in xmlSchemaTypeFixup(). | |
| 16762 */ | |
| 16763 /* | |
| 16764 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specificati
on | |
| 16765 * above for {attribute wildcard} is satisfied, the intensional | |
| 16766 * intersection must be expressible, as defined in Attribute Wildcard | |
| 16767 * Intersection ($3.10.6). | |
| 16768 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses(). | |
| 16769 */ | |
| 16770 return (ret); | |
| 16771 } | |
| 16772 | |
| 16773 #ifdef ENABLE_PARTICLE_RESTRICTION | |
| 16774 /** | |
| 16775 * xmlSchemaCheckParticleRangeOK: | |
| 16776 * @ctxt: the schema parser context | |
| 16777 * @type: the complex type definition | |
| 16778 * | |
| 16779 * (3.9.6) Constraints on Particle Schema Components | |
| 16780 * Schema Component Constraint: | |
| 16781 * Occurrence Range OK (range-ok) | |
| 16782 * | |
| 16783 * STATUS: complete | |
| 16784 * | |
| 16785 * Returns 0 if the constraints are satisfied, a positive | |
| 16786 * error code if not and -1 if an internal error occured. | |
| 16787 */ | |
| 16788 static int | |
| 16789 xmlSchemaCheckParticleRangeOK(int rmin, int rmax, | |
| 16790 int bmin, int bmax) | |
| 16791 { | |
| 16792 if (rmin < bmin) | |
| 16793 return (1); | |
| 16794 if ((bmax != UNBOUNDED) && | |
| 16795 (rmax > bmax)) | |
| 16796 return (1); | |
| 16797 return (0); | |
| 16798 } | |
| 16799 | |
| 16800 /** | |
| 16801 * xmlSchemaCheckRCaseNameAndTypeOK: | |
| 16802 * @ctxt: the schema parser context | |
| 16803 * @r: the restricting element declaration particle | |
| 16804 * @b: the base element declaration particle | |
| 16805 * | |
| 16806 * (3.9.6) Constraints on Particle Schema Components | |
| 16807 * Schema Component Constraint: | |
| 16808 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK) | |
| 16809 * (rcase-NameAndTypeOK) | |
| 16810 * | |
| 16811 * STATUS: | |
| 16812 * MISSING (3.2.3) | |
| 16813 * CLARIFY: (3.2.2) | |
| 16814 * | |
| 16815 * Returns 0 if the constraints are satisfied, a positive | |
| 16816 * error code if not and -1 if an internal error occured. | |
| 16817 */ | |
| 16818 static int | |
| 16819 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt, | |
| 16820 xmlSchemaParticlePtr r, | |
| 16821 xmlSchemaParticlePtr b) | |
| 16822 { | |
| 16823 xmlSchemaElementPtr elemR, elemB; | |
| 16824 | |
| 16825 /* TODO: Error codes (rcase-NameAndTypeOK). */ | |
| 16826 elemR = (xmlSchemaElementPtr) r->children; | |
| 16827 elemB = (xmlSchemaElementPtr) b->children; | |
| 16828 /* | |
| 16829 * SPEC (1) "The declarations' {name}s and {target namespace}s are | |
| 16830 * the same." | |
| 16831 */ | |
| 16832 if ((elemR != elemB) && | |
| 16833 ((! xmlStrEqual(elemR->name, elemB->name)) || | |
| 16834 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace)))) | |
| 16835 return (1); | |
| 16836 /* | |
| 16837 * SPEC (2) "R's occurrence range is a valid restriction of B's | |
| 16838 * occurrence range as defined by Occurrence Range OK ($3.9.6)." | |
| 16839 */ | |
| 16840 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, | |
| 16841 b->minOccurs, b->maxOccurs) != 0) | |
| 16842 return (1); | |
| 16843 /* | |
| 16844 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's | |
| 16845 * {scope} are global." | |
| 16846 */ | |
| 16847 if (elemR == elemB) | |
| 16848 return (0); | |
| 16849 /* | |
| 16850 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false." | |
| 16851 */ | |
| 16852 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) && | |
| 16853 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE)) | |
| 16854 return (1); | |
| 16855 /* | |
| 16856 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent, | |
| 16857 * or is not fixed, or R's declaration's {value constraint} is fixed | |
| 16858 * with the same value." | |
| 16859 */ | |
| 16860 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) && | |
| 16861 ((elemR->value == NULL) || | |
| 16862 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) || | |
| 16863 /* TODO: Equality of the initial value or normalized or canonical? */ | |
| 16864 (! xmlStrEqual(elemR->value, elemB->value)))) | |
| 16865 return (1); | |
| 16866 /* | |
| 16867 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint | |
| 16868 * definitions} is a subset of B's declaration's {identity-constraint | |
| 16869 * definitions}, if any." | |
| 16870 */ | |
| 16871 if (elemB->idcs != NULL) { | |
| 16872 /* TODO */ | |
| 16873 } | |
| 16874 /* | |
| 16875 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a | |
| 16876 * superset of B's declaration's {disallowed substitutions}." | |
| 16877 */ | |
| 16878 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) && | |
| 16879 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) || | |
| 16880 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) && | |
| 16881 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) || | |
| 16882 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) && | |
| 16883 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0))) | |
| 16884 return (1); | |
| 16885 /* | |
| 16886 * SPEC (3.2.5) "R's {type definition} is validly derived given | |
| 16887 * {extension, list, union} from B's {type definition}" | |
| 16888 * | |
| 16889 * BADSPEC TODO: What's the point of adding "list" and "union" to the | |
| 16890 * set, if the corresponding constraints handle "restriction" and | |
| 16891 * "extension" only? | |
| 16892 * | |
| 16893 */ | |
| 16894 { | |
| 16895 int set = 0; | |
| 16896 | |
| 16897 set |= SUBSET_EXTENSION; | |
| 16898 set |= SUBSET_LIST; | |
| 16899 set |= SUBSET_UNION; | |
| 16900 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes, | |
| 16901 elemB->subtypes, set) != 0) | |
| 16902 return (1); | |
| 16903 } | |
| 16904 return (0); | |
| 16905 } | |
| 16906 | |
| 16907 /** | |
| 16908 * xmlSchemaCheckRCaseNSCompat: | |
| 16909 * @ctxt: the schema parser context | |
| 16910 * @r: the restricting element declaration particle | |
| 16911 * @b: the base wildcard particle | |
| 16912 * | |
| 16913 * (3.9.6) Constraints on Particle Schema Components | |
| 16914 * Schema Component Constraint: | |
| 16915 * Particle Derivation OK (Elt:Any -- NSCompat) | |
| 16916 * (rcase-NSCompat) | |
| 16917 * | |
| 16918 * STATUS: complete | |
| 16919 * | |
| 16920 * Returns 0 if the constraints are satisfied, a positive | |
| 16921 * error code if not and -1 if an internal error occured. | |
| 16922 */ | |
| 16923 static int | |
| 16924 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt, | |
| 16925 xmlSchemaParticlePtr r, | |
| 16926 xmlSchemaParticlePtr b) | |
| 16927 { | |
| 16928 /* TODO:Error codes (rcase-NSCompat). */ | |
| 16929 /* | |
| 16930 * SPEC "For an element declaration particle to be a `valid restriction` | |
| 16931 * of a wildcard particle all of the following must be true:" | |
| 16932 * | |
| 16933 * SPEC (1) "The element declaration's {target namespace} is `valid` | |
| 16934 * with respect to the wildcard's {namespace constraint} as defined by | |
| 16935 * Wildcard allows Namespace Name ($3.10.4)." | |
| 16936 */ | |
| 16937 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children, | |
| 16938 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0) | |
| 16939 return (1); | |
| 16940 /* | |
| 16941 * SPEC (2) "R's occurrence range is a valid restriction of B's | |
| 16942 * occurrence range as defined by Occurrence Range OK ($3.9.6)." | |
| 16943 */ | |
| 16944 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, | |
| 16945 b->minOccurs, b->maxOccurs) != 0) | |
| 16946 return (1); | |
| 16947 | |
| 16948 return (0); | |
| 16949 } | |
| 16950 | |
| 16951 /** | |
| 16952 * xmlSchemaCheckRCaseRecurseAsIfGroup: | |
| 16953 * @ctxt: the schema parser context | |
| 16954 * @r: the restricting element declaration particle | |
| 16955 * @b: the base model group particle | |
| 16956 * | |
| 16957 * (3.9.6) Constraints on Particle Schema Components | |
| 16958 * Schema Component Constraint: | |
| 16959 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup) | |
| 16960 * (rcase-RecurseAsIfGroup) | |
| 16961 * | |
| 16962 * STATUS: TODO | |
| 16963 * | |
| 16964 * Returns 0 if the constraints are satisfied, a positive | |
| 16965 * error code if not and -1 if an internal error occured. | |
| 16966 */ | |
| 16967 static int | |
| 16968 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt, | |
| 16969 xmlSchemaParticlePtr r, | |
| 16970 xmlSchemaParticlePtr b) | |
| 16971 { | |
| 16972 /* TODO: Error codes (rcase-RecurseAsIfGroup). */ | |
| 16973 TODO | |
| 16974 return (0); | |
| 16975 } | |
| 16976 | |
| 16977 /** | |
| 16978 * xmlSchemaCheckRCaseNSSubset: | |
| 16979 * @ctxt: the schema parser context | |
| 16980 * @r: the restricting wildcard particle | |
| 16981 * @b: the base wildcard particle | |
| 16982 * | |
| 16983 * (3.9.6) Constraints on Particle Schema Components | |
| 16984 * Schema Component Constraint: | |
| 16985 * Particle Derivation OK (Any:Any -- NSSubset) | |
| 16986 * (rcase-NSSubset) | |
| 16987 * | |
| 16988 * STATUS: complete | |
| 16989 * | |
| 16990 * Returns 0 if the constraints are satisfied, a positive | |
| 16991 * error code if not and -1 if an internal error occured. | |
| 16992 */ | |
| 16993 static int | |
| 16994 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt, | |
| 16995 xmlSchemaParticlePtr r, | |
| 16996 xmlSchemaParticlePtr b, | |
| 16997 int isAnyTypeBase) | |
| 16998 { | |
| 16999 /* TODO: Error codes (rcase-NSSubset). */ | |
| 17000 /* | |
| 17001 * SPEC (1) "R's occurrence range is a valid restriction of B's | |
| 17002 * occurrence range as defined by Occurrence Range OK ($3.9.6)." | |
| 17003 */ | |
| 17004 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, | |
| 17005 b->minOccurs, b->maxOccurs)) | |
| 17006 return (1); | |
| 17007 /* | |
| 17008 * SPEC (2) "R's {namespace constraint} must be an intensional subset | |
| 17009 * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)." | |
| 17010 */ | |
| 17011 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children, | |
| 17012 (xmlSchemaWildcardPtr) b->children)) | |
| 17013 return (1); | |
| 17014 /* | |
| 17015 * SPEC (3) "Unless B is the content model wildcard of the `ur-type | |
| 17016 * definition`, R's {process contents} must be identical to or stronger | |
| 17017 * than B's {process contents}, where strict is stronger than lax is | |
| 17018 * stronger than skip." | |
| 17019 */ | |
| 17020 if (! isAnyTypeBase) { | |
| 17021 if ( ((xmlSchemaWildcardPtr) r->children)->processContents < | |
| 17022 ((xmlSchemaWildcardPtr) b->children)->processContents) | |
| 17023 return (1); | |
| 17024 } | |
| 17025 | |
| 17026 return (0); | |
| 17027 } | |
| 17028 | |
| 17029 /** | |
| 17030 * xmlSchemaCheckCOSParticleRestrict: | |
| 17031 * @ctxt: the schema parser context | |
| 17032 * @type: the complex type definition | |
| 17033 * | |
| 17034 * (3.9.6) Constraints on Particle Schema Components | |
| 17035 * Schema Component Constraint: | |
| 17036 * Particle Valid (Restriction) (cos-particle-restrict) | |
| 17037 * | |
| 17038 * STATUS: TODO | |
| 17039 * | |
| 17040 * Returns 0 if the constraints are satisfied, a positive | |
| 17041 * error code if not and -1 if an internal error occured. | |
| 17042 */ | |
| 17043 static int | |
| 17044 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt, | |
| 17045 xmlSchemaParticlePtr r, | |
| 17046 xmlSchemaParticlePtr b) | |
| 17047 { | |
| 17048 int ret = 0; | |
| 17049 | |
| 17050 /*part = WXS_TYPE_PARTICLE(type); | |
| 17051 basePart = WXS_TYPE_PARTICLE(base); | |
| 17052 */ | |
| 17053 | |
| 17054 TODO | |
| 17055 | |
| 17056 /* | |
| 17057 * SPEC (1) "They are the same particle." | |
| 17058 */ | |
| 17059 if (r == b) | |
| 17060 return (0); | |
| 17061 | |
| 17062 | |
| 17063 return (0); | |
| 17064 } | |
| 17065 | |
| 17066 #if 0 | |
| 17067 /** | |
| 17068 * xmlSchemaCheckRCaseNSRecurseCheckCardinality: | |
| 17069 * @ctxt: the schema parser context | |
| 17070 * @r: the model group particle | |
| 17071 * @b: the base wildcard particle | |
| 17072 * | |
| 17073 * (3.9.6) Constraints on Particle Schema Components | |
| 17074 * Schema Component Constraint: | |
| 17075 * Particle Derivation OK (All/Choice/Sequence:Any -- | |
| 17076 * NSRecurseCheckCardinality) | |
| 17077 * (rcase-NSRecurseCheckCardinality) | |
| 17078 * | |
| 17079 * STATUS: TODO: subst-groups | |
| 17080 * | |
| 17081 * Returns 0 if the constraints are satisfied, a positive | |
| 17082 * error code if not and -1 if an internal error occured. | |
| 17083 */ | |
| 17084 static int | |
| 17085 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt, | |
| 17086 xmlSchemaParticlePtr r, | |
| 17087 xmlSchemaParticlePtr b) | |
| 17088 { | |
| 17089 xmlSchemaParticlePtr part; | |
| 17090 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */ | |
| 17091 if ((r->children == NULL) || (r->children->children == NULL)) | |
| 17092 return (-1); | |
| 17093 /* | |
| 17094 * SPEC "For a group particle to be a `valid restriction` of a | |
| 17095 * wildcard particle..." | |
| 17096 * | |
| 17097 * SPEC (1) "Every member of the {particles} of the group is a `valid | |
| 17098 * restriction` of the wildcard as defined by | |
| 17099 * Particle Valid (Restriction) ($3.9.6)." | |
| 17100 */ | |
| 17101 part = (xmlSchemaParticlePtr) r->children->children; | |
| 17102 do { | |
| 17103 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b)) | |
| 17104 return (1); | |
| 17105 part = (xmlSchemaParticlePtr) part->next; | |
| 17106 } while (part != NULL); | |
| 17107 /* | |
| 17108 * SPEC (2) "The effective total range of the group [...] is a | |
| 17109 * valid restriction of B's occurrence range as defined by | |
| 17110 * Occurrence Range OK ($3.9.6)." | |
| 17111 */ | |
| 17112 if (xmlSchemaCheckParticleRangeOK( | |
| 17113 xmlSchemaGetParticleTotalRangeMin(r), | |
| 17114 xmlSchemaGetParticleTotalRangeMax(r), | |
| 17115 b->minOccurs, b->maxOccurs) != 0) | |
| 17116 return (1); | |
| 17117 return (0); | |
| 17118 } | |
| 17119 #endif | |
| 17120 | |
| 17121 /** | |
| 17122 * xmlSchemaCheckRCaseRecurse: | |
| 17123 * @ctxt: the schema parser context | |
| 17124 * @r: the <all> or <sequence> model group particle | |
| 17125 * @b: the base <all> or <sequence> model group particle | |
| 17126 * | |
| 17127 * (3.9.6) Constraints on Particle Schema Components | |
| 17128 * Schema Component Constraint: | |
| 17129 * Particle Derivation OK (All:All,Sequence:Sequence -- | |
| 17130 Recurse) | |
| 17131 * (rcase-Recurse) | |
| 17132 * | |
| 17133 * STATUS: ? | |
| 17134 * TODO: subst-groups | |
| 17135 * | |
| 17136 * Returns 0 if the constraints are satisfied, a positive | |
| 17137 * error code if not and -1 if an internal error occured. | |
| 17138 */ | |
| 17139 static int | |
| 17140 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt, | |
| 17141 xmlSchemaParticlePtr r, | |
| 17142 xmlSchemaParticlePtr b) | |
| 17143 { | |
| 17144 /* xmlSchemaParticlePtr part; */ | |
| 17145 /* TODO: Error codes (rcase-Recurse). */ | |
| 17146 if ((r->children == NULL) || (b->children == NULL) || | |
| 17147 (r->children->type != b->children->type)) | |
| 17148 return (-1); | |
| 17149 /* | |
| 17150 * SPEC "For an all or sequence group particle to be a `valid | |
| 17151 * restriction` of another group particle with the same {compositor}..." | |
| 17152 * | |
| 17153 * SPEC (1) "R's occurrence range is a valid restriction of B's | |
| 17154 * occurrence range as defined by Occurrence Range OK ($3.9.6)." | |
| 17155 */ | |
| 17156 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, | |
| 17157 b->minOccurs, b->maxOccurs)) | |
| 17158 return (1); | |
| 17159 | |
| 17160 | |
| 17161 return (0); | |
| 17162 } | |
| 17163 | |
| 17164 #endif | |
| 17165 | |
| 17166 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \ | |
| 17167 xmlSchemaPCustomErrExt(pctxt, \ | |
| 17168 XML_SCHEMAP_INVALID_FACET_VALUE, \ | |
| 17169 WXS_BASIC_CAST fac1, fac1->node, \ | |
| 17170 "It is an error for both '%s' and '%s' to be specified on the "\ | |
| 17171 "same type definition", \ | |
| 17172 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \ | |
| 17173 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL); | |
| 17174 | |
| 17175 #define FACET_RESTR_ERR(fac1, msg) \ | |
| 17176 xmlSchemaPCustomErr(pctxt, \ | |
| 17177 XML_SCHEMAP_INVALID_FACET_VALUE, \ | |
| 17178 WXS_BASIC_CAST fac1, fac1->node, \ | |
| 17179 msg, NULL); | |
| 17180 | |
| 17181 #define FACET_RESTR_FIXED_ERR(fac) \ | |
| 17182 xmlSchemaPCustomErr(pctxt, \ | |
| 17183 XML_SCHEMAP_INVALID_FACET_VALUE, \ | |
| 17184 WXS_BASIC_CAST fac, fac->node, \ | |
| 17185 "The base type's facet is 'fixed', thus the value must not " \ | |
| 17186 "differ", NULL); | |
| 17187 | |
| 17188 static void | |
| 17189 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt, | |
| 17190 xmlSchemaFacetPtr facet1, | |
| 17191 xmlSchemaFacetPtr facet2, | |
| 17192 int lessGreater, | |
| 17193 int orEqual, | |
| 17194 int ofBase) | |
| 17195 { | |
| 17196 xmlChar *msg = NULL; | |
| 17197 | |
| 17198 msg = xmlStrdup(BAD_CAST "'"); | |
| 17199 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type)); | |
| 17200 msg = xmlStrcat(msg, BAD_CAST "' has to be"); | |
| 17201 if (lessGreater == 0) | |
| 17202 msg = xmlStrcat(msg, BAD_CAST " equal to"); | |
| 17203 if (lessGreater == 1) | |
| 17204 msg = xmlStrcat(msg, BAD_CAST " greater than"); | |
| 17205 else | |
| 17206 msg = xmlStrcat(msg, BAD_CAST " less than"); | |
| 17207 | |
| 17208 if (orEqual) | |
| 17209 msg = xmlStrcat(msg, BAD_CAST " or equal to"); | |
| 17210 msg = xmlStrcat(msg, BAD_CAST " '"); | |
| 17211 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type)); | |
| 17212 if (ofBase) | |
| 17213 msg = xmlStrcat(msg, BAD_CAST "' of the base type"); | |
| 17214 else | |
| 17215 msg = xmlStrcat(msg, BAD_CAST "'"); | |
| 17216 | |
| 17217 xmlSchemaPCustomErr(pctxt, | |
| 17218 XML_SCHEMAP_INVALID_FACET_VALUE, | |
| 17219 WXS_BASIC_CAST facet1, NULL, | |
| 17220 (const char *) msg, NULL); | |
| 17221 | |
| 17222 if (msg != NULL) | |
| 17223 xmlFree(msg); | |
| 17224 } | |
| 17225 | |
| 17226 /* | |
| 17227 * xmlSchemaDeriveAndValidateFacets: | |
| 17228 * | |
| 17229 * Schema Component Constraint: Simple Type Restriction (Facets) | |
| 17230 * (st-restrict-facets) | |
| 17231 */ | |
| 17232 static int | |
| 17233 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt, | |
| 17234 xmlSchemaTypePtr type) | |
| 17235 { | |
| 17236 xmlSchemaTypePtr base = type->baseType; | |
| 17237 xmlSchemaFacetLinkPtr link, cur, last = NULL; | |
| 17238 xmlSchemaFacetPtr facet, bfacet, | |
| 17239 flength = NULL, ftotdig = NULL, ffracdig = NULL, | |
| 17240 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */ | |
| 17241 fmininc = NULL, fmaxinc = NULL, | |
| 17242 fminexc = NULL, fmaxexc = NULL, | |
| 17243 bflength = NULL, bftotdig = NULL, bffracdig = NULL, | |
| 17244 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */ | |
| 17245 bfmininc = NULL, bfmaxinc = NULL, | |
| 17246 bfminexc = NULL, bfmaxexc = NULL; | |
| 17247 int res; /* err = 0, fixedErr; */ | |
| 17248 | |
| 17249 /* | |
| 17250 * SPEC st-restrict-facets 1: | |
| 17251 * "The {variety} of R is the same as that of B." | |
| 17252 */ | |
| 17253 /* | |
| 17254 * SPEC st-restrict-facets 2: | |
| 17255 * "If {variety} is atomic, the {primitive type definition} | |
| 17256 * of R is the same as that of B." | |
| 17257 * | |
| 17258 * NOTE: we leave 1 & 2 out for now, since this will be | |
| 17259 * satisfied by the derivation process. | |
| 17260 * CONSTRUCTION TODO: Maybe needed if using a construction API. | |
| 17261 */ | |
| 17262 /* | |
| 17263 * SPEC st-restrict-facets 3: | |
| 17264 * "The {facets} of R are the union of S and the {facets} | |
| 17265 * of B, eliminating duplicates. To eliminate duplicates, | |
| 17266 * when a facet of the same kind occurs in both S and the | |
| 17267 * {facets} of B, the one in the {facets} of B is not | |
| 17268 * included, with the exception of enumeration and pattern | |
| 17269 * facets, for which multiple occurrences with distinct values | |
| 17270 * are allowed." | |
| 17271 */ | |
| 17272 | |
| 17273 if ((type->facetSet == NULL) && (base->facetSet == NULL)) | |
| 17274 return (0); | |
| 17275 | |
| 17276 last = type->facetSet; | |
| 17277 if (last != NULL) | |
| 17278 while (last->next != NULL) | |
| 17279 last = last->next; | |
| 17280 | |
| 17281 for (cur = type->facetSet; cur != NULL; cur = cur->next) { | |
| 17282 facet = cur->facet; | |
| 17283 switch (facet->type) { | |
| 17284 case XML_SCHEMA_FACET_LENGTH: | |
| 17285 flength = facet; break; | |
| 17286 case XML_SCHEMA_FACET_MINLENGTH: | |
| 17287 fminlen = facet; break; | |
| 17288 case XML_SCHEMA_FACET_MININCLUSIVE: | |
| 17289 fmininc = facet; break; | |
| 17290 case XML_SCHEMA_FACET_MINEXCLUSIVE: | |
| 17291 fminexc = facet; break; | |
| 17292 case XML_SCHEMA_FACET_MAXLENGTH: | |
| 17293 fmaxlen = facet; break; | |
| 17294 case XML_SCHEMA_FACET_MAXINCLUSIVE: | |
| 17295 fmaxinc = facet; break; | |
| 17296 case XML_SCHEMA_FACET_MAXEXCLUSIVE: | |
| 17297 fmaxexc = facet; break; | |
| 17298 case XML_SCHEMA_FACET_TOTALDIGITS: | |
| 17299 ftotdig = facet; break; | |
| 17300 case XML_SCHEMA_FACET_FRACTIONDIGITS: | |
| 17301 ffracdig = facet; break; | |
| 17302 default: | |
| 17303 break; | |
| 17304 } | |
| 17305 } | |
| 17306 for (cur = base->facetSet; cur != NULL; cur = cur->next) { | |
| 17307 facet = cur->facet; | |
| 17308 switch (facet->type) { | |
| 17309 case XML_SCHEMA_FACET_LENGTH: | |
| 17310 bflength = facet; break; | |
| 17311 case XML_SCHEMA_FACET_MINLENGTH: | |
| 17312 bfminlen = facet; break; | |
| 17313 case XML_SCHEMA_FACET_MININCLUSIVE: | |
| 17314 bfmininc = facet; break; | |
| 17315 case XML_SCHEMA_FACET_MINEXCLUSIVE: | |
| 17316 bfminexc = facet; break; | |
| 17317 case XML_SCHEMA_FACET_MAXLENGTH: | |
| 17318 bfmaxlen = facet; break; | |
| 17319 case XML_SCHEMA_FACET_MAXINCLUSIVE: | |
| 17320 bfmaxinc = facet; break; | |
| 17321 case XML_SCHEMA_FACET_MAXEXCLUSIVE: | |
| 17322 bfmaxexc = facet; break; | |
| 17323 case XML_SCHEMA_FACET_TOTALDIGITS: | |
| 17324 bftotdig = facet; break; | |
| 17325 case XML_SCHEMA_FACET_FRACTIONDIGITS: | |
| 17326 bffracdig = facet; break; | |
| 17327 default: | |
| 17328 break; | |
| 17329 } | |
| 17330 } | |
| 17331 /* | |
| 17332 * length and minLength or maxLength (2.2) + (3.2) | |
| 17333 */ | |
| 17334 if (flength && (fminlen || fmaxlen)) { | |
| 17335 FACET_RESTR_ERR(flength, "It is an error for both 'length' and " | |
| 17336 "either of 'minLength' or 'maxLength' to be specified on " | |
| 17337 "the same type definition") | |
| 17338 } | |
| 17339 /* | |
| 17340 * Mutual exclusions in the same derivation step. | |
| 17341 */ | |
| 17342 if ((fmaxinc) && (fmaxexc)) { | |
| 17343 /* | |
| 17344 * SCC "maxInclusive and maxExclusive" | |
| 17345 */ | |
| 17346 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc) | |
| 17347 } | |
| 17348 if ((fmininc) && (fminexc)) { | |
| 17349 /* | |
| 17350 * SCC "minInclusive and minExclusive" | |
| 17351 */ | |
| 17352 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc) | |
| 17353 } | |
| 17354 | |
| 17355 if (flength && bflength) { | |
| 17356 /* | |
| 17357 * SCC "length valid restriction" | |
| 17358 * The values have to be equal. | |
| 17359 */ | |
| 17360 res = xmlSchemaCompareValues(flength->val, bflength->val); | |
| 17361 if (res == -2) | |
| 17362 goto internal_error; | |
| 17363 if (res != 0) | |
| 17364 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1); | |
| 17365 if ((res != 0) && (bflength->fixed)) { | |
| 17366 FACET_RESTR_FIXED_ERR(flength) | |
| 17367 } | |
| 17368 | |
| 17369 } | |
| 17370 if (fminlen && bfminlen) { | |
| 17371 /* | |
| 17372 * SCC "minLength valid restriction" | |
| 17373 * minLength >= BASE minLength | |
| 17374 */ | |
| 17375 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val); | |
| 17376 if (res == -2) | |
| 17377 goto internal_error; | |
| 17378 if (res == -1) | |
| 17379 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1); | |
| 17380 if ((res != 0) && (bfminlen->fixed)) { | |
| 17381 FACET_RESTR_FIXED_ERR(fminlen) | |
| 17382 } | |
| 17383 } | |
| 17384 if (fmaxlen && bfmaxlen) { | |
| 17385 /* | |
| 17386 * SCC "maxLength valid restriction" | |
| 17387 * maxLength <= BASE minLength | |
| 17388 */ | |
| 17389 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val); | |
| 17390 if (res == -2) | |
| 17391 goto internal_error; | |
| 17392 if (res == 1) | |
| 17393 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1); | |
| 17394 if ((res != 0) && (bfmaxlen->fixed)) { | |
| 17395 FACET_RESTR_FIXED_ERR(fmaxlen) | |
| 17396 } | |
| 17397 } | |
| 17398 /* | |
| 17399 * SCC "length and minLength or maxLength" | |
| 17400 */ | |
| 17401 if (! flength) | |
| 17402 flength = bflength; | |
| 17403 if (flength) { | |
| 17404 if (! fminlen) | |
| 17405 fminlen = bfminlen; | |
| 17406 if (fminlen) { | |
| 17407 /* (1.1) length >= minLength */ | |
| 17408 res = xmlSchemaCompareValues(flength->val, fminlen->val); | |
| 17409 if (res == -2) | |
| 17410 goto internal_error; | |
| 17411 if (res == -1) | |
| 17412 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0); | |
| 17413 } | |
| 17414 if (! fmaxlen) | |
| 17415 fmaxlen = bfmaxlen; | |
| 17416 if (fmaxlen) { | |
| 17417 /* (2.1) length <= maxLength */ | |
| 17418 res = xmlSchemaCompareValues(flength->val, fmaxlen->val); | |
| 17419 if (res == -2) | |
| 17420 goto internal_error; | |
| 17421 if (res == 1) | |
| 17422 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0); | |
| 17423 } | |
| 17424 } | |
| 17425 if (fmaxinc) { | |
| 17426 /* | |
| 17427 * "maxInclusive" | |
| 17428 */ | |
| 17429 if (fmininc) { | |
| 17430 /* SCC "maxInclusive >= minInclusive" */ | |
| 17431 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val); | |
| 17432 if (res == -2) | |
| 17433 goto internal_error; | |
| 17434 if (res == -1) { | |
| 17435 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0); | |
| 17436 } | |
| 17437 } | |
| 17438 /* | |
| 17439 * SCC "maxInclusive valid restriction" | |
| 17440 */ | |
| 17441 if (bfmaxinc) { | |
| 17442 /* maxInclusive <= BASE maxInclusive */ | |
| 17443 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val); | |
| 17444 if (res == -2) | |
| 17445 goto internal_error; | |
| 17446 if (res == 1) | |
| 17447 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1); | |
| 17448 if ((res != 0) && (bfmaxinc->fixed)) { | |
| 17449 FACET_RESTR_FIXED_ERR(fmaxinc) | |
| 17450 } | |
| 17451 } | |
| 17452 if (bfmaxexc) { | |
| 17453 /* maxInclusive < BASE maxExclusive */ | |
| 17454 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val); | |
| 17455 if (res == -2) | |
| 17456 goto internal_error; | |
| 17457 if (res != -1) { | |
| 17458 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1); | |
| 17459 } | |
| 17460 } | |
| 17461 if (bfmininc) { | |
| 17462 /* maxInclusive >= BASE minInclusive */ | |
| 17463 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val); | |
| 17464 if (res == -2) | |
| 17465 goto internal_error; | |
| 17466 if (res == -1) { | |
| 17467 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1); | |
| 17468 } | |
| 17469 } | |
| 17470 if (bfminexc) { | |
| 17471 /* maxInclusive > BASE minExclusive */ | |
| 17472 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val); | |
| 17473 if (res == -2) | |
| 17474 goto internal_error; | |
| 17475 if (res != 1) { | |
| 17476 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1); | |
| 17477 } | |
| 17478 } | |
| 17479 } | |
| 17480 if (fmaxexc) { | |
| 17481 /* | |
| 17482 * "maxExclusive >= minExclusive" | |
| 17483 */ | |
| 17484 if (fminexc) { | |
| 17485 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val); | |
| 17486 if (res == -2) | |
| 17487 goto internal_error; | |
| 17488 if (res == -1) { | |
| 17489 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0); | |
| 17490 } | |
| 17491 } | |
| 17492 /* | |
| 17493 * "maxExclusive valid restriction" | |
| 17494 */ | |
| 17495 if (bfmaxexc) { | |
| 17496 /* maxExclusive <= BASE maxExclusive */ | |
| 17497 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val); | |
| 17498 if (res == -2) | |
| 17499 goto internal_error; | |
| 17500 if (res == 1) { | |
| 17501 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1); | |
| 17502 } | |
| 17503 if ((res != 0) && (bfmaxexc->fixed)) { | |
| 17504 FACET_RESTR_FIXED_ERR(fmaxexc) | |
| 17505 } | |
| 17506 } | |
| 17507 if (bfmaxinc) { | |
| 17508 /* maxExclusive <= BASE maxInclusive */ | |
| 17509 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val); | |
| 17510 if (res == -2) | |
| 17511 goto internal_error; | |
| 17512 if (res == 1) { | |
| 17513 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1); | |
| 17514 } | |
| 17515 } | |
| 17516 if (bfmininc) { | |
| 17517 /* maxExclusive > BASE minInclusive */ | |
| 17518 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val); | |
| 17519 if (res == -2) | |
| 17520 goto internal_error; | |
| 17521 if (res != 1) { | |
| 17522 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1); | |
| 17523 } | |
| 17524 } | |
| 17525 if (bfminexc) { | |
| 17526 /* maxExclusive > BASE minExclusive */ | |
| 17527 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val); | |
| 17528 if (res == -2) | |
| 17529 goto internal_error; | |
| 17530 if (res != 1) { | |
| 17531 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1); | |
| 17532 } | |
| 17533 } | |
| 17534 } | |
| 17535 if (fminexc) { | |
| 17536 /* | |
| 17537 * "minExclusive < maxInclusive" | |
| 17538 */ | |
| 17539 if (fmaxinc) { | |
| 17540 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val); | |
| 17541 if (res == -2) | |
| 17542 goto internal_error; | |
| 17543 if (res != -1) { | |
| 17544 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0); | |
| 17545 } | |
| 17546 } | |
| 17547 /* | |
| 17548 * "minExclusive valid restriction" | |
| 17549 */ | |
| 17550 if (bfminexc) { | |
| 17551 /* minExclusive >= BASE minExclusive */ | |
| 17552 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val); | |
| 17553 if (res == -2) | |
| 17554 goto internal_error; | |
| 17555 if (res == -1) { | |
| 17556 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1); | |
| 17557 } | |
| 17558 if ((res != 0) && (bfminexc->fixed)) { | |
| 17559 FACET_RESTR_FIXED_ERR(fminexc) | |
| 17560 } | |
| 17561 } | |
| 17562 if (bfmaxinc) { | |
| 17563 /* minExclusive <= BASE maxInclusive */ | |
| 17564 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val); | |
| 17565 if (res == -2) | |
| 17566 goto internal_error; | |
| 17567 if (res == 1) { | |
| 17568 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1); | |
| 17569 } | |
| 17570 } | |
| 17571 if (bfmininc) { | |
| 17572 /* minExclusive >= BASE minInclusive */ | |
| 17573 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val); | |
| 17574 if (res == -2) | |
| 17575 goto internal_error; | |
| 17576 if (res == -1) { | |
| 17577 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1); | |
| 17578 } | |
| 17579 } | |
| 17580 if (bfmaxexc) { | |
| 17581 /* minExclusive < BASE maxExclusive */ | |
| 17582 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val); | |
| 17583 if (res == -2) | |
| 17584 goto internal_error; | |
| 17585 if (res != -1) { | |
| 17586 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1); | |
| 17587 } | |
| 17588 } | |
| 17589 } | |
| 17590 if (fmininc) { | |
| 17591 /* | |
| 17592 * "minInclusive < maxExclusive" | |
| 17593 */ | |
| 17594 if (fmaxexc) { | |
| 17595 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val); | |
| 17596 if (res == -2) | |
| 17597 goto internal_error; | |
| 17598 if (res != -1) { | |
| 17599 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0); | |
| 17600 } | |
| 17601 } | |
| 17602 /* | |
| 17603 * "minExclusive valid restriction" | |
| 17604 */ | |
| 17605 if (bfmininc) { | |
| 17606 /* minInclusive >= BASE minInclusive */ | |
| 17607 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val); | |
| 17608 if (res == -2) | |
| 17609 goto internal_error; | |
| 17610 if (res == -1) { | |
| 17611 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1); | |
| 17612 } | |
| 17613 if ((res != 0) && (bfmininc->fixed)) { | |
| 17614 FACET_RESTR_FIXED_ERR(fmininc) | |
| 17615 } | |
| 17616 } | |
| 17617 if (bfmaxinc) { | |
| 17618 /* minInclusive <= BASE maxInclusive */ | |
| 17619 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val); | |
| 17620 if (res == -2) | |
| 17621 goto internal_error; | |
| 17622 if (res == 1) { | |
| 17623 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1); | |
| 17624 } | |
| 17625 } | |
| 17626 if (bfminexc) { | |
| 17627 /* minInclusive > BASE minExclusive */ | |
| 17628 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val); | |
| 17629 if (res == -2) | |
| 17630 goto internal_error; | |
| 17631 if (res != 1) | |
| 17632 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1); | |
| 17633 } | |
| 17634 if (bfmaxexc) { | |
| 17635 /* minInclusive < BASE maxExclusive */ | |
| 17636 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val); | |
| 17637 if (res == -2) | |
| 17638 goto internal_error; | |
| 17639 if (res != -1) | |
| 17640 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1); | |
| 17641 } | |
| 17642 } | |
| 17643 if (ftotdig && bftotdig) { | |
| 17644 /* | |
| 17645 * SCC " totalDigits valid restriction" | |
| 17646 * totalDigits <= BASE totalDigits | |
| 17647 */ | |
| 17648 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val); | |
| 17649 if (res == -2) | |
| 17650 goto internal_error; | |
| 17651 if (res == 1) | |
| 17652 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig, | |
| 17653 -1, 1, 1); | |
| 17654 if ((res != 0) && (bftotdig->fixed)) { | |
| 17655 FACET_RESTR_FIXED_ERR(ftotdig) | |
| 17656 } | |
| 17657 } | |
| 17658 if (ffracdig && bffracdig) { | |
| 17659 /* | |
| 17660 * SCC "fractionDigits valid restriction" | |
| 17661 * fractionDigits <= BASE fractionDigits | |
| 17662 */ | |
| 17663 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val); | |
| 17664 if (res == -2) | |
| 17665 goto internal_error; | |
| 17666 if (res == 1) | |
| 17667 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig, | |
| 17668 -1, 1, 1); | |
| 17669 if ((res != 0) && (bffracdig->fixed)) { | |
| 17670 FACET_RESTR_FIXED_ERR(ffracdig) | |
| 17671 } | |
| 17672 } | |
| 17673 /* | |
| 17674 * SCC "fractionDigits less than or equal to totalDigits" | |
| 17675 */ | |
| 17676 if (! ftotdig) | |
| 17677 ftotdig = bftotdig; | |
| 17678 if (! ffracdig) | |
| 17679 ffracdig = bffracdig; | |
| 17680 if (ftotdig && ffracdig) { | |
| 17681 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val); | |
| 17682 if (res == -2) | |
| 17683 goto internal_error; | |
| 17684 if (res == 1) | |
| 17685 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig, | |
| 17686 -1, 1, 0); | |
| 17687 } | |
| 17688 /* | |
| 17689 * *Enumerations* won' be added here, since only the first set | |
| 17690 * of enumerations in the ancestor-or-self axis is used | |
| 17691 * for validation, plus we need to use the base type of those | |
| 17692 * enumerations for whitespace. | |
| 17693 * | |
| 17694 * *Patterns*: won't be add here, since they are ORed at | |
| 17695 * type level and ANDed at ancestor level. This will | |
| 17696 * happed during validation by walking the base axis | |
| 17697 * of the type. | |
| 17698 */ | |
| 17699 for (cur = base->facetSet; cur != NULL; cur = cur->next) { | |
| 17700 bfacet = cur->facet; | |
| 17701 /* | |
| 17702 * Special handling of enumerations and patterns. | |
| 17703 * TODO: hmm, they should not appear in the set, so remove this. | |
| 17704 */ | |
| 17705 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) || | |
| 17706 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION)) | |
| 17707 continue; | |
| 17708 /* | |
| 17709 * Search for a duplicate facet in the current type. | |
| 17710 */ | |
| 17711 link = type->facetSet; | |
| 17712 /* err = 0; */ | |
| 17713 /* fixedErr = 0; */ | |
| 17714 while (link != NULL) { | |
| 17715 facet = link->facet; | |
| 17716 if (facet->type == bfacet->type) { | |
| 17717 switch (facet->type) { | |
| 17718 case XML_SCHEMA_FACET_WHITESPACE: | |
| 17719 /* | |
| 17720 * The whitespace must be stronger. | |
| 17721 */ | |
| 17722 if (facet->whitespace < bfacet->whitespace) { | |
| 17723 FACET_RESTR_ERR(facet, | |
| 17724 "The 'whitespace' value has to be equal to " | |
| 17725 "or stronger than the 'whitespace' value of " | |
| 17726 "the base type") | |
| 17727 } | |
| 17728 if ((bfacet->fixed) && | |
| 17729 (facet->whitespace != bfacet->whitespace)) { | |
| 17730 FACET_RESTR_FIXED_ERR(facet) | |
| 17731 } | |
| 17732 break; | |
| 17733 default: | |
| 17734 break; | |
| 17735 } | |
| 17736 /* Duplicate found. */ | |
| 17737 break; | |
| 17738 } | |
| 17739 link = link->next; | |
| 17740 } | |
| 17741 /* | |
| 17742 * If no duplicate was found: add the base types's facet | |
| 17743 * to the set. | |
| 17744 */ | |
| 17745 if (link == NULL) { | |
| 17746 link = (xmlSchemaFacetLinkPtr) | |
| 17747 xmlMalloc(sizeof(xmlSchemaFacetLink)); | |
| 17748 if (link == NULL) { | |
| 17749 xmlSchemaPErrMemory(pctxt, | |
| 17750 "deriving facets, creating a facet link", NULL); | |
| 17751 return (-1); | |
| 17752 } | |
| 17753 link->facet = cur->facet; | |
| 17754 link->next = NULL; | |
| 17755 if (last == NULL) | |
| 17756 type->facetSet = link; | |
| 17757 else | |
| 17758 last->next = link; | |
| 17759 last = link; | |
| 17760 } | |
| 17761 | |
| 17762 } | |
| 17763 | |
| 17764 return (0); | |
| 17765 internal_error: | |
| 17766 PERROR_INT("xmlSchemaDeriveAndValidateFacets", | |
| 17767 "an error occured"); | |
| 17768 return (-1); | |
| 17769 } | |
| 17770 | |
| 17771 static int | |
| 17772 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt, | |
| 17773 xmlSchemaTypePtr type) | |
| 17774 { | |
| 17775 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink; | |
| 17776 /* | |
| 17777 * The actual value is then formed by replacing any union type | |
| 17778 * definition in the `explicit members` with the members of their | |
| 17779 * {member type definitions}, in order. | |
| 17780 * | |
| 17781 * TODO: There's a bug entry at | |
| 17782 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/02
87.html" | |
| 17783 * which indicates that we'll keep the union types the future. | |
| 17784 */ | |
| 17785 link = type->memberTypes; | |
| 17786 while (link != NULL) { | |
| 17787 | |
| 17788 if (WXS_IS_TYPE_NOT_FIXED(link->type)) | |
| 17789 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt); | |
| 17790 | |
| 17791 if (WXS_IS_UNION(link->type)) { | |
| 17792 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type); | |
| 17793 if (subLink != NULL) { | |
| 17794 link->type = subLink->type; | |
| 17795 if (subLink->next != NULL) { | |
| 17796 lastLink = link->next; | |
| 17797 subLink = subLink->next; | |
| 17798 prevLink = link; | |
| 17799 while (subLink != NULL) { | |
| 17800 newLink = (xmlSchemaTypeLinkPtr) | |
| 17801 xmlMalloc(sizeof(xmlSchemaTypeLink)); | |
| 17802 if (newLink == NULL) { | |
| 17803 xmlSchemaPErrMemory(pctxt, "allocating a type link", | |
| 17804 NULL); | |
| 17805 return (-1); | |
| 17806 } | |
| 17807 newLink->type = subLink->type; | |
| 17808 prevLink->next = newLink; | |
| 17809 prevLink = newLink; | |
| 17810 newLink->next = lastLink; | |
| 17811 | |
| 17812 subLink = subLink->next; | |
| 17813 } | |
| 17814 } | |
| 17815 } | |
| 17816 } | |
| 17817 link = link->next; | |
| 17818 } | |
| 17819 return (0); | |
| 17820 } | |
| 17821 | |
| 17822 static void | |
| 17823 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type) | |
| 17824 { | |
| 17825 int has = 0, needVal = 0, normVal = 0; | |
| 17826 | |
| 17827 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0; | |
| 17828 if (has) { | |
| 17829 needVal = (type->baseType->flags & | |
| 17830 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0; | |
| 17831 normVal = (type->baseType->flags & | |
| 17832 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0; | |
| 17833 } | |
| 17834 if (type->facets != NULL) { | |
| 17835 xmlSchemaFacetPtr fac; | |
| 17836 | |
| 17837 for (fac = type->facets; fac != NULL; fac = fac->next) { | |
| 17838 switch (fac->type) { | |
| 17839 case XML_SCHEMA_FACET_WHITESPACE: | |
| 17840 break; | |
| 17841 case XML_SCHEMA_FACET_PATTERN: | |
| 17842 normVal = 1; | |
| 17843 has = 1; | |
| 17844 break; | |
| 17845 case XML_SCHEMA_FACET_ENUMERATION: | |
| 17846 needVal = 1; | |
| 17847 normVal = 1; | |
| 17848 has = 1; | |
| 17849 break; | |
| 17850 default: | |
| 17851 has = 1; | |
| 17852 break; | |
| 17853 } | |
| 17854 } | |
| 17855 } | |
| 17856 if (normVal) | |
| 17857 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED; | |
| 17858 if (needVal) | |
| 17859 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE; | |
| 17860 if (has) | |
| 17861 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS; | |
| 17862 | |
| 17863 if (has && (! needVal) && WXS_IS_ATOMIC(type)) { | |
| 17864 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type); | |
| 17865 /* | |
| 17866 * OPTIMIZE VAL TODO: Some facets need a computed value. | |
| 17867 */ | |
| 17868 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) && | |
| 17869 (prim->builtInType != XML_SCHEMAS_STRING)) { | |
| 17870 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE; | |
| 17871 } | |
| 17872 } | |
| 17873 } | |
| 17874 | |
| 17875 static int | |
| 17876 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type) | |
| 17877 { | |
| 17878 | |
| 17879 | |
| 17880 /* | |
| 17881 * Evaluate the whitespace-facet value. | |
| 17882 */ | |
| 17883 if (WXS_IS_LIST(type)) { | |
| 17884 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE; | |
| 17885 return (0); | |
| 17886 } else if (WXS_IS_UNION(type)) | |
| 17887 return (0); | |
| 17888 | |
| 17889 if (type->facetSet != NULL) { | |
| 17890 xmlSchemaFacetLinkPtr lin; | |
| 17891 | |
| 17892 for (lin = type->facetSet; lin != NULL; lin = lin->next) { | |
| 17893 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) { | |
| 17894 switch (lin->facet->whitespace) { | |
| 17895 case XML_SCHEMAS_FACET_PRESERVE: | |
| 17896 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE; | |
| 17897 break; | |
| 17898 case XML_SCHEMAS_FACET_REPLACE: | |
| 17899 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE; | |
| 17900 break; | |
| 17901 case XML_SCHEMAS_FACET_COLLAPSE: | |
| 17902 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE; | |
| 17903 break; | |
| 17904 default: | |
| 17905 return (-1); | |
| 17906 } | |
| 17907 return (0); | |
| 17908 } | |
| 17909 } | |
| 17910 } | |
| 17911 /* | |
| 17912 * For all `atomic` datatypes other than string (and types `derived` | |
| 17913 * by `restriction` from it) the value of whiteSpace is fixed to | |
| 17914 * collapse | |
| 17915 */ | |
| 17916 { | |
| 17917 xmlSchemaTypePtr anc; | |
| 17918 | |
| 17919 for (anc = type->baseType; anc != NULL && | |
| 17920 anc->builtInType != XML_SCHEMAS_ANYTYPE; | |
| 17921 anc = anc->baseType) { | |
| 17922 | |
| 17923 if (anc->type == XML_SCHEMA_TYPE_BASIC) { | |
| 17924 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) { | |
| 17925 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE; | |
| 17926 | |
| 17927 } else if ((anc->builtInType == XML_SCHEMAS_STRING) || | |
| 17928 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) { | |
| 17929 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE; | |
| 17930 | |
| 17931 } else | |
| 17932 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE; | |
| 17933 break; | |
| 17934 } | |
| 17935 } | |
| 17936 } | |
| 17937 return (0); | |
| 17938 } | |
| 17939 | |
| 17940 static int | |
| 17941 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt, | |
| 17942 xmlSchemaTypePtr type) | |
| 17943 { | |
| 17944 if (type->type != XML_SCHEMA_TYPE_SIMPLE) | |
| 17945 return(0); | |
| 17946 if (! WXS_IS_TYPE_NOT_FIXED_1(type)) | |
| 17947 return(0); | |
| 17948 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1; | |
| 17949 | |
| 17950 if (WXS_IS_LIST(type)) { | |
| 17951 /* | |
| 17952 * Corresponds to <simpleType><list>... | |
| 17953 */ | |
| 17954 if (type->subtypes == NULL) { | |
| 17955 /* | |
| 17956 * This one is really needed, so get out. | |
| 17957 */ | |
| 17958 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne", | |
| 17959 "list type has no item-type assigned"); | |
| 17960 return(-1); | |
| 17961 } | |
| 17962 } else if (WXS_IS_UNION(type)) { | |
| 17963 /* | |
| 17964 * Corresponds to <simpleType><union>... | |
| 17965 */ | |
| 17966 if (type->memberTypes == NULL) { | |
| 17967 /* | |
| 17968 * This one is really needed, so get out. | |
| 17969 */ | |
| 17970 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne", | |
| 17971 "union type has no member-types assigned"); | |
| 17972 return(-1); | |
| 17973 } | |
| 17974 } else { | |
| 17975 /* | |
| 17976 * Corresponds to <simpleType><restriction>... | |
| 17977 */ | |
| 17978 if (type->baseType == NULL) { | |
| 17979 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne", | |
| 17980 "type has no base-type assigned"); | |
| 17981 return(-1); | |
| 17982 } | |
| 17983 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType)) | |
| 17984 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1) | |
| 17985 return(-1); | |
| 17986 /* | |
| 17987 * Variety | |
| 17988 * If the <restriction> alternative is chosen, then the | |
| 17989 * {variety} of the {base type definition}. | |
| 17990 */ | |
| 17991 if (WXS_IS_ATOMIC(type->baseType)) | |
| 17992 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC; | |
| 17993 else if (WXS_IS_LIST(type->baseType)) { | |
| 17994 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST; | |
| 17995 /* | |
| 17996 * Inherit the itemType. | |
| 17997 */ | |
| 17998 type->subtypes = type->baseType->subtypes; | |
| 17999 } else if (WXS_IS_UNION(type->baseType)) { | |
| 18000 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION; | |
| 18001 /* | |
| 18002 * NOTE that we won't assign the memberTypes of the base, | |
| 18003 * since this will make trouble when freeing them; we will | |
| 18004 * use a lookup function to access them instead. | |
| 18005 */ | |
| 18006 } | |
| 18007 } | |
| 18008 return(0); | |
| 18009 } | |
| 18010 | |
| 18011 #ifdef DEBUG_TYPE | |
| 18012 static void | |
| 18013 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt, | |
| 18014 xmlSchemaTypePtr type) | |
| 18015 { | |
| 18016 if (type->node != NULL) { | |
| 18017 xmlGenericError(xmlGenericErrorContext, | |
| 18018 "Type of %s : %s:%d :", name, | |
| 18019 type->node->doc->URL, | |
| 18020 xmlGetLineNo(type->node)); | |
| 18021 } else { | |
| 18022 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name); | |
| 18023 } | |
| 18024 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) { | |
| 18025 switch (type->contentType) { | |
| 18026 case XML_SCHEMA_CONTENT_SIMPLE: | |
| 18027 xmlGenericError(xmlGenericErrorContext, "simple\n"); | |
| 18028 break; | |
| 18029 case XML_SCHEMA_CONTENT_ELEMENTS: | |
| 18030 xmlGenericError(xmlGenericErrorContext, "elements\n"); | |
| 18031 break; | |
| 18032 case XML_SCHEMA_CONTENT_UNKNOWN: | |
| 18033 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n"); | |
| 18034 break; | |
| 18035 case XML_SCHEMA_CONTENT_EMPTY: | |
| 18036 xmlGenericError(xmlGenericErrorContext, "empty\n"); | |
| 18037 break; | |
| 18038 case XML_SCHEMA_CONTENT_MIXED: | |
| 18039 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) | |
| 18040 type->subtypes)) | |
| 18041 xmlGenericError(xmlGenericErrorContext, | |
| 18042 "mixed as emptiable particle\n"); | |
| 18043 else | |
| 18044 xmlGenericError(xmlGenericErrorContext, "mixed\n"); | |
| 18045 break; | |
| 18046 /* Removed, since not used. */ | |
| 18047 /* | |
| 18048 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS: | |
| 18049 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n"); | |
| 18050 break; | |
| 18051 */ | |
| 18052 case XML_SCHEMA_CONTENT_BASIC: | |
| 18053 xmlGenericError(xmlGenericErrorContext, "basic\n"); | |
| 18054 break; | |
| 18055 default: | |
| 18056 xmlGenericError(xmlGenericErrorContext, | |
| 18057 "not registered !!!\n"); | |
| 18058 break; | |
| 18059 } | |
| 18060 } | |
| 18061 } | |
| 18062 #endif | |
| 18063 | |
| 18064 /* | |
| 18065 * 3.14.6 Constraints on Simple Type Definition Schema Components | |
| 18066 */ | |
| 18067 static int | |
| 18068 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt, | |
| 18069 xmlSchemaTypePtr type) | |
| 18070 { | |
| 18071 int res, olderrs = pctxt->nberrors; | |
| 18072 | |
| 18073 if (type->type != XML_SCHEMA_TYPE_SIMPLE) | |
| 18074 return(-1); | |
| 18075 | |
| 18076 if (! WXS_IS_TYPE_NOT_FIXED(type)) | |
| 18077 return(0); | |
| 18078 | |
| 18079 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED; | |
| 18080 type->contentType = XML_SCHEMA_CONTENT_SIMPLE; | |
| 18081 | |
| 18082 if (type->baseType == NULL) { | |
| 18083 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo", | |
| 18084 "missing baseType"); | |
| 18085 goto exit_failure; | |
| 18086 } | |
| 18087 if (WXS_IS_TYPE_NOT_FIXED(type->baseType)) | |
| 18088 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt); | |
| 18089 /* | |
| 18090 * If a member type of a union is a union itself, we need to substitute | |
| 18091 * that member type for its member types. | |
| 18092 * NOTE that this might change in WXS 1.1; i.e. we will keep the union | |
| 18093 * types in WXS 1.1. | |
| 18094 */ | |
| 18095 if ((type->memberTypes != NULL) && | |
| 18096 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)) | |
| 18097 return(-1); | |
| 18098 /* | |
| 18099 * SPEC src-simple-type 1 | |
| 18100 * "The corresponding simple type definition, if any, must satisfy | |
| 18101 * the conditions set out in Constraints on Simple Type Definition | |
| 18102 * Schema Components ($3.14.6)." | |
| 18103 */ | |
| 18104 /* | |
| 18105 * Schema Component Constraint: Simple Type Definition Properties Correct | |
| 18106 * (st-props-correct) | |
| 18107 */ | |
| 18108 res = xmlSchemaCheckSTPropsCorrect(pctxt, type); | |
| 18109 HFAILURE HERROR | |
| 18110 /* | |
| 18111 * Schema Component Constraint: Derivation Valid (Restriction, Simple) | |
| 18112 * (cos-st-restricts) | |
| 18113 */ | |
| 18114 res = xmlSchemaCheckCOSSTRestricts(pctxt, type); | |
| 18115 HFAILURE HERROR | |
| 18116 /* | |
| 18117 * TODO: Removed the error report, since it got annoying to get an | |
| 18118 * extra error report, if anything failed until now. | |
| 18119 * Enable this if needed. | |
| 18120 * | |
| 18121 * xmlSchemaPErr(ctxt, type->node, | |
| 18122 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1, | |
| 18123 * "Simple type '%s' does not satisfy the constraints " | |
| 18124 * "on simple type definitions.\n", | |
| 18125 * type->name, NULL); | |
| 18126 */ | |
| 18127 /* | |
| 18128 * Schema Component Constraint: Simple Type Restriction (Facets) | |
| 18129 * (st-restrict-facets) | |
| 18130 */ | |
| 18131 res = xmlSchemaCheckFacetValues(type, pctxt); | |
| 18132 HFAILURE HERROR | |
| 18133 if ((type->facetSet != NULL) || | |
| 18134 (type->baseType->facetSet != NULL)) { | |
| 18135 res = xmlSchemaDeriveAndValidateFacets(pctxt, type); | |
| 18136 HFAILURE HERROR | |
| 18137 } | |
| 18138 /* | |
| 18139 * Whitespace value. | |
| 18140 */ | |
| 18141 res = xmlSchemaTypeFixupWhitespace(type); | |
| 18142 HFAILURE HERROR | |
| 18143 xmlSchemaTypeFixupOptimFacets(type); | |
| 18144 | |
| 18145 exit_error: | |
| 18146 #ifdef DEBUG_TYPE | |
| 18147 xmlSchemaDebugFixedType(pctxt, type); | |
| 18148 #endif | |
| 18149 if (olderrs != pctxt->nberrors) | |
| 18150 return(pctxt->err); | |
| 18151 return(0); | |
| 18152 | |
| 18153 exit_failure: | |
| 18154 #ifdef DEBUG_TYPE | |
| 18155 xmlSchemaDebugFixedType(pctxt, type); | |
| 18156 #endif | |
| 18157 return(-1); | |
| 18158 } | |
| 18159 | |
| 18160 static int | |
| 18161 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt, | |
| 18162 xmlSchemaTypePtr type) | |
| 18163 { | |
| 18164 int res = 0, olderrs = pctxt->nberrors; | |
| 18165 xmlSchemaTypePtr baseType = type->baseType; | |
| 18166 | |
| 18167 if (! WXS_IS_TYPE_NOT_FIXED(type)) | |
| 18168 return(0); | |
| 18169 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED; | |
| 18170 if (baseType == NULL) { | |
| 18171 PERROR_INT("xmlSchemaFixupComplexType", | |
| 18172 "missing baseType"); | |
| 18173 goto exit_failure; | |
| 18174 } | |
| 18175 /* | |
| 18176 * Fixup the base type. | |
| 18177 */ | |
| 18178 if (WXS_IS_TYPE_NOT_FIXED(baseType)) | |
| 18179 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt); | |
| 18180 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) { | |
| 18181 /* | |
| 18182 * Skip fixup if the base type is invalid. | |
| 18183 * TODO: Generate a warning! | |
| 18184 */ | |
| 18185 return(0); | |
| 18186 } | |
| 18187 /* | |
| 18188 * This basically checks if the base type can be derived. | |
| 18189 */ | |
| 18190 res = xmlSchemaCheckSRCCT(pctxt, type); | |
| 18191 HFAILURE HERROR | |
| 18192 /* | |
| 18193 * Fixup the content type. | |
| 18194 */ | |
| 18195 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) { | |
| 18196 /* | |
| 18197 * Corresponds to <complexType><simpleContent>... | |
| 18198 */ | |
| 18199 if ((WXS_IS_COMPLEX(baseType)) && | |
| 18200 (baseType->contentTypeDef != NULL) && | |
| 18201 (WXS_IS_RESTRICTION(type))) { | |
| 18202 xmlSchemaTypePtr contentBase, content; | |
| 18203 #ifdef ENABLE_NAMED_LOCALS | |
| 18204 char buf[30]; | |
| 18205 const xmlChar *tmpname; | |
| 18206 #endif | |
| 18207 /* | |
| 18208 * SPEC (1) If <restriction> + base type is <complexType>, | |
| 18209 * "whose own {content type} is a simple type..." | |
| 18210 */ | |
| 18211 if (type->contentTypeDef != NULL) { | |
| 18212 /* | |
| 18213 * SPEC (1.1) "the simple type definition corresponding to the | |
| 18214 * <simpleType> among the [children] of <restriction> if there | |
| 18215 * is one;" | |
| 18216 * Note that this "<simpleType> among the [children]" was put | |
| 18217 * into ->contentTypeDef during parsing. | |
| 18218 */ | |
| 18219 contentBase = type->contentTypeDef; | |
| 18220 type->contentTypeDef = NULL; | |
| 18221 } else { | |
| 18222 /* | |
| 18223 * (1.2) "...otherwise (<restriction> has no <simpleType> | |
| 18224 * among its [children]), the simple type definition which | |
| 18225 * is the {content type} of the ... base type." | |
| 18226 */ | |
| 18227 contentBase = baseType->contentTypeDef; | |
| 18228 } | |
| 18229 /* | |
| 18230 * SPEC | |
| 18231 * "... a simple type definition which restricts the simple | |
| 18232 * type definition identified in clause 1.1 or clause 1.2 | |
| 18233 * with a set of facet components" | |
| 18234 * | |
| 18235 * Create the anonymous simple type, which will be the content | |
| 18236 * type of the complex type. | |
| 18237 */ | |
| 18238 #ifdef ENABLE_NAMED_LOCALS | |
| 18239 snprintf(buf, 29, "#scST%d", ++(pctxt->counter)); | |
| 18240 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1); | |
| 18241 content = xmlSchemaAddType(pctxt, pctxt->schema, | |
| 18242 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace, | |
| 18243 type->node, 0); | |
| 18244 #else | |
| 18245 content = xmlSchemaAddType(pctxt, pctxt->schema, | |
| 18246 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace, | |
| 18247 type->node, 0); | |
| 18248 #endif | |
| 18249 if (content == NULL) | |
| 18250 goto exit_failure; | |
| 18251 /* | |
| 18252 * We will use the same node as for the <complexType> | |
| 18253 * to have it somehow anchored in the schema doc. | |
| 18254 */ | |
| 18255 content->type = XML_SCHEMA_TYPE_SIMPLE; | |
| 18256 content->baseType = contentBase; | |
| 18257 /* | |
| 18258 * Move the facets, previously anchored on the | |
| 18259 * complexType during parsing. | |
| 18260 */ | |
| 18261 content->facets = type->facets; | |
| 18262 type->facets = NULL; | |
| 18263 content->facetSet = type->facetSet; | |
| 18264 type->facetSet = NULL; | |
| 18265 | |
| 18266 type->contentTypeDef = content; | |
| 18267 if (WXS_IS_TYPE_NOT_FIXED(contentBase)) | |
| 18268 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt); | |
| 18269 /* | |
| 18270 * Fixup the newly created type. We don't need to check | |
| 18271 * for circularity here. | |
| 18272 */ | |
| 18273 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content); | |
| 18274 HFAILURE HERROR | |
| 18275 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content); | |
| 18276 HFAILURE HERROR | |
| 18277 | |
| 18278 } else if ((WXS_IS_COMPLEX(baseType)) && | |
| 18279 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) && | |
| 18280 (WXS_IS_RESTRICTION(type))) { | |
| 18281 /* | |
| 18282 * SPEC (2) If <restriction> + base is a mixed <complexType> with | |
| 18283 * an emptiable particle, then a simple type definition which | |
| 18284 * restricts the <restriction>'s <simpleType> child. | |
| 18285 */ | |
| 18286 if ((type->contentTypeDef == NULL) || | |
| 18287 (type->contentTypeDef->baseType == NULL)) { | |
| 18288 /* | |
| 18289 * TODO: Check if this ever happens. | |
| 18290 */ | |
| 18291 xmlSchemaPCustomErr(pctxt, | |
| 18292 XML_SCHEMAP_INTERNAL, | |
| 18293 WXS_BASIC_CAST type, NULL, | |
| 18294 "Internal error: xmlSchemaTypeFixup, " | |
| 18295 "complex type '%s': the <simpleContent><restriction> " | |
| 18296 "is missing a <simpleType> child, but was not catched " | |
| 18297 "by xmlSchemaCheckSRCCT()", type->name); | |
| 18298 goto exit_failure; | |
| 18299 } | |
| 18300 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) { | |
| 18301 /* | |
| 18302 * SPEC (3) If <extension> + base is <complexType> with | |
| 18303 * <simpleType> content, "...then the {content type} of that | |
| 18304 * complex type definition" | |
| 18305 */ | |
| 18306 if (baseType->contentTypeDef == NULL) { | |
| 18307 /* | |
| 18308 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT | |
| 18309 * should have catched this already. | |
| 18310 */ | |
| 18311 xmlSchemaPCustomErr(pctxt, | |
| 18312 XML_SCHEMAP_INTERNAL, | |
| 18313 WXS_BASIC_CAST type, NULL, | |
| 18314 "Internal error: xmlSchemaTypeFixup, " | |
| 18315 "complex type '%s': the <extension>ed base type is " | |
| 18316 "a complex type with no simple content type", | |
| 18317 type->name); | |
| 18318 goto exit_failure; | |
| 18319 } | |
| 18320 type->contentTypeDef = baseType->contentTypeDef; | |
| 18321 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) { | |
| 18322 /* | |
| 18323 * SPEC (4) <extension> + base is <simpleType> | |
| 18324 * "... then that simple type definition" | |
| 18325 */ | |
| 18326 type->contentTypeDef = baseType; | |
| 18327 } else { | |
| 18328 /* | |
| 18329 * TODO: Check if this ever happens. | |
| 18330 */ | |
| 18331 xmlSchemaPCustomErr(pctxt, | |
| 18332 XML_SCHEMAP_INTERNAL, | |
| 18333 WXS_BASIC_CAST type, NULL, | |
| 18334 "Internal error: xmlSchemaTypeFixup, " | |
| 18335 "complex type '%s' with <simpleContent>: unhandled " | |
| 18336 "derivation case", type->name); | |
| 18337 goto exit_failure; | |
| 18338 } | |
| 18339 } else { | |
| 18340 int dummySequence = 0; | |
| 18341 xmlSchemaParticlePtr particle = | |
| 18342 (xmlSchemaParticlePtr) type->subtypes; | |
| 18343 /* | |
| 18344 * Corresponds to <complexType><complexContent>... | |
| 18345 * | |
| 18346 * NOTE that the effective mixed was already set during parsing of | |
| 18347 * <complexType> and <complexContent>; its flag value is | |
| 18348 * XML_SCHEMAS_TYPE_MIXED. | |
| 18349 * | |
| 18350 * Compute the "effective content": | |
| 18351 * (2.1.1) + (2.1.2) + (2.1.3) | |
| 18352 */ | |
| 18353 if ((particle == NULL) || | |
| 18354 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) && | |
| 18355 ((particle->children->type == XML_SCHEMA_TYPE_ALL) || | |
| 18356 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) || | |
| 18357 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) && | |
| 18358 (particle->minOccurs == 0))) && | |
| 18359 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) { | |
| 18360 if (type->flags & XML_SCHEMAS_TYPE_MIXED) { | |
| 18361 /* | |
| 18362 * SPEC (2.1.4) "If the `effective mixed` is true, then | |
| 18363 * a particle whose properties are as follows:..." | |
| 18364 * | |
| 18365 * Empty sequence model group with | |
| 18366 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable"). | |
| 18367 * NOTE that we sill assign it the <complexType> node to | |
| 18368 * somehow anchor it in the doc. | |
| 18369 */ | |
| 18370 if ((particle == NULL) || | |
| 18371 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) { | |
| 18372 /* | |
| 18373 * Create the particle. | |
| 18374 */ | |
| 18375 particle = xmlSchemaAddParticle(pctxt, | |
| 18376 type->node, 1, 1); | |
| 18377 if (particle == NULL) | |
| 18378 goto exit_failure; | |
| 18379 /* | |
| 18380 * Create the model group. | |
| 18381 */ /* URGENT TODO: avoid adding to pending items. */ | |
| 18382 particle->children = (xmlSchemaTreeItemPtr) | |
| 18383 xmlSchemaAddModelGroup(pctxt, pctxt->schema, | |
| 18384 XML_SCHEMA_TYPE_SEQUENCE, type->node); | |
| 18385 if (particle->children == NULL) | |
| 18386 goto exit_failure; | |
| 18387 | |
| 18388 type->subtypes = (xmlSchemaTypePtr) particle; | |
| 18389 } | |
| 18390 dummySequence = 1; | |
| 18391 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS; | |
| 18392 } else { | |
| 18393 /* | |
| 18394 * SPEC (2.1.5) "otherwise empty" | |
| 18395 */ | |
| 18396 type->contentType = XML_SCHEMA_CONTENT_EMPTY; | |
| 18397 } | |
| 18398 } else { | |
| 18399 /* | |
| 18400 * SPEC (2.2) "otherwise the particle corresponding to the | |
| 18401 * <all>, <choice>, <group> or <sequence> among the | |
| 18402 * [children]." | |
| 18403 */ | |
| 18404 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS; | |
| 18405 } | |
| 18406 /* | |
| 18407 * Compute the "content type". | |
| 18408 */ | |
| 18409 if (WXS_IS_RESTRICTION(type)) { | |
| 18410 /* | |
| 18411 * SPEC (3.1) "If <restriction>..." | |
| 18412 * (3.1.1) + (3.1.2) */ | |
| 18413 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) { | |
| 18414 if (type->flags & XML_SCHEMAS_TYPE_MIXED) | |
| 18415 type->contentType = XML_SCHEMA_CONTENT_MIXED; | |
| 18416 } | |
| 18417 } else { | |
| 18418 /* | |
| 18419 * SPEC (3.2) "If <extension>..." | |
| 18420 */ | |
| 18421 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) { | |
| 18422 /* | |
| 18423 * SPEC (3.2.1) | |
| 18424 * "If the `effective content` is empty, then the | |
| 18425 * {content type} of the [...] base ..." | |
| 18426 */ | |
| 18427 type->contentType = baseType->contentType; | |
| 18428 type->subtypes = baseType->subtypes; | |
| 18429 /* | |
| 18430 * Fixes bug #347316: | |
| 18431 * This is the case when the base type has a simple | |
| 18432 * type definition as content. | |
| 18433 */ | |
| 18434 type->contentTypeDef = baseType->contentTypeDef; | |
| 18435 /* | |
| 18436 * NOTE that the effective mixed is ignored here. | |
| 18437 */ | |
| 18438 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) { | |
| 18439 /* | |
| 18440 * SPEC (3.2.2) | |
| 18441 */ | |
| 18442 if (type->flags & XML_SCHEMAS_TYPE_MIXED) | |
| 18443 type->contentType = XML_SCHEMA_CONTENT_MIXED; | |
| 18444 } else { | |
| 18445 /* | |
| 18446 * SPEC (3.2.3) | |
| 18447 */ | |
| 18448 if (type->flags & XML_SCHEMAS_TYPE_MIXED) | |
| 18449 type->contentType = XML_SCHEMA_CONTENT_MIXED; | |
| 18450 /* | |
| 18451 * "A model group whose {compositor} is sequence and whose | |
| 18452 * {particles} are..." | |
| 18453 */ | |
| 18454 if ((WXS_TYPE_PARTICLE(type) != NULL) && | |
| 18455 (WXS_TYPE_PARTICLE_TERM(type) != NULL) && | |
| 18456 ((WXS_TYPE_PARTICLE_TERM(type))->type == | |
| 18457 XML_SCHEMA_TYPE_ALL)) | |
| 18458 { | |
| 18459 /* | |
| 18460 * SPEC cos-all-limited (1) | |
| 18461 */ | |
| 18462 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 18463 /* TODO: error code */ | |
| 18464 XML_SCHEMAP_COS_ALL_LIMITED, | |
| 18465 WXS_ITEM_NODE(type), NULL, | |
| 18466 "The type has an 'all' model group in its " | |
| 18467 "{content type} and thus cannot be derived from " | |
| 18468 "a non-empty type, since this would produce a " | |
| 18469 "'sequence' model group containing the 'all' " | |
| 18470 "model group; 'all' model groups are not " | |
| 18471 "allowed to appear inside other model groups", | |
| 18472 NULL, NULL); | |
| 18473 | |
| 18474 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) && | |
| 18475 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) && | |
| 18476 ((WXS_TYPE_PARTICLE_TERM(baseType))->type == | |
| 18477 XML_SCHEMA_TYPE_ALL)) | |
| 18478 { | |
| 18479 /* | |
| 18480 * SPEC cos-all-limited (1) | |
| 18481 */ | |
| 18482 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 18483 /* TODO: error code */ | |
| 18484 XML_SCHEMAP_COS_ALL_LIMITED, | |
| 18485 WXS_ITEM_NODE(type), NULL, | |
| 18486 "A type cannot be derived by extension from a type " | |
| 18487 "which has an 'all' model group in its " | |
| 18488 "{content type}, since this would produce a " | |
| 18489 "'sequence' model group containing the 'all' " | |
| 18490 "model group; 'all' model groups are not " | |
| 18491 "allowed to appear inside other model groups", | |
| 18492 NULL, NULL); | |
| 18493 | |
| 18494 } else if (! dummySequence) { | |
| 18495 xmlSchemaTreeItemPtr effectiveContent = | |
| 18496 (xmlSchemaTreeItemPtr) type->subtypes; | |
| 18497 /* | |
| 18498 * Create the particle. | |
| 18499 */ | |
| 18500 particle = xmlSchemaAddParticle(pctxt, | |
| 18501 type->node, 1, 1); | |
| 18502 if (particle == NULL) | |
| 18503 goto exit_failure; | |
| 18504 /* | |
| 18505 * Create the "sequence" model group. | |
| 18506 */ | |
| 18507 particle->children = (xmlSchemaTreeItemPtr) | |
| 18508 xmlSchemaAddModelGroup(pctxt, pctxt->schema, | |
| 18509 XML_SCHEMA_TYPE_SEQUENCE, type->node); | |
| 18510 if (particle->children == NULL) | |
| 18511 goto exit_failure; | |
| 18512 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle; | |
| 18513 /* | |
| 18514 * SPEC "the particle of the {content type} of | |
| 18515 * the ... base ..." | |
| 18516 * Create a duplicate of the base type's particle | |
| 18517 * and assign its "term" to it. | |
| 18518 */ | |
| 18519 particle->children->children = | |
| 18520 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt, | |
| 18521 type->node, | |
| 18522 ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs, | |
| 18523 ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs); | |
| 18524 if (particle->children->children == NULL) | |
| 18525 goto exit_failure; | |
| 18526 particle = (xmlSchemaParticlePtr) | |
| 18527 particle->children->children; | |
| 18528 particle->children = | |
| 18529 ((xmlSchemaParticlePtr) baseType->subtypes)->children; | |
| 18530 /* | |
| 18531 * SPEC "followed by the `effective content`." | |
| 18532 */ | |
| 18533 particle->next = effectiveContent; | |
| 18534 /* | |
| 18535 * This all will result in: | |
| 18536 * new-particle | |
| 18537 * --> new-sequence( | |
| 18538 * new-particle | |
| 18539 * --> base-model, | |
| 18540 * this-particle | |
| 18541 * --> this-model | |
| 18542 * ) | |
| 18543 */ | |
| 18544 } else { | |
| 18545 /* | |
| 18546 * This is the case when there is already an empty | |
| 18547 * <sequence> with minOccurs==maxOccurs==1. | |
| 18548 * Just add the base types's content type. | |
| 18549 * NOTE that, although we miss to add an intermediate | |
| 18550 * <sequence>, this should produce no difference to | |
| 18551 * neither the regex compilation of the content model, | |
| 18552 * nor to the complex type contraints. | |
| 18553 */ | |
| 18554 particle->children->children = | |
| 18555 (xmlSchemaTreeItemPtr) baseType->subtypes; | |
| 18556 } | |
| 18557 } | |
| 18558 } | |
| 18559 } | |
| 18560 /* | |
| 18561 * Now fixup attribute uses: | |
| 18562 * - expand attr. group references | |
| 18563 * - intersect attribute wildcards | |
| 18564 * - inherit attribute uses of the base type | |
| 18565 * - inherit or union attr. wildcards if extending | |
| 18566 * - apply attr. use prohibitions if restricting | |
| 18567 */ | |
| 18568 res = xmlSchemaFixupTypeAttributeUses(pctxt, type); | |
| 18569 HFAILURE HERROR | |
| 18570 /* | |
| 18571 * Apply the complex type component constraints; this will not | |
| 18572 * check attributes, since this is done in | |
| 18573 * xmlSchemaFixupTypeAttributeUses(). | |
| 18574 */ | |
| 18575 res = xmlSchemaCheckCTComponent(pctxt, type); | |
| 18576 HFAILURE HERROR | |
| 18577 | |
| 18578 #ifdef DEBUG_TYPE | |
| 18579 xmlSchemaDebugFixedType(pctxt, type); | |
| 18580 #endif | |
| 18581 if (olderrs != pctxt->nberrors) | |
| 18582 return(pctxt->err); | |
| 18583 else | |
| 18584 return(0); | |
| 18585 | |
| 18586 exit_error: | |
| 18587 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID; | |
| 18588 #ifdef DEBUG_TYPE | |
| 18589 xmlSchemaDebugFixedType(pctxt, type); | |
| 18590 #endif | |
| 18591 return(pctxt->err); | |
| 18592 | |
| 18593 exit_failure: | |
| 18594 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID; | |
| 18595 #ifdef DEBUG_TYPE | |
| 18596 xmlSchemaDebugFixedType(pctxt, type); | |
| 18597 #endif | |
| 18598 return(-1); | |
| 18599 } | |
| 18600 | |
| 18601 | |
| 18602 /** | |
| 18603 * xmlSchemaTypeFixup: | |
| 18604 * @typeDecl: the schema type definition | |
| 18605 * @ctxt: the schema parser context | |
| 18606 * | |
| 18607 * Fixes the content model of the type. | |
| 18608 * URGENT TODO: We need an int result! | |
| 18609 */ | |
| 18610 static int | |
| 18611 xmlSchemaTypeFixup(xmlSchemaTypePtr type, | |
| 18612 xmlSchemaAbstractCtxtPtr actxt) | |
| 18613 { | |
| 18614 if (type == NULL) | |
| 18615 return(0); | |
| 18616 if (actxt->type != XML_SCHEMA_CTXT_PARSER) { | |
| 18617 AERROR_INT("xmlSchemaTypeFixup", | |
| 18618 "this function needs a parser context"); | |
| 18619 return(-1); | |
| 18620 } | |
| 18621 if (! WXS_IS_TYPE_NOT_FIXED(type)) | |
| 18622 return(0); | |
| 18623 if (type->type == XML_SCHEMA_TYPE_COMPLEX) | |
| 18624 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type)); | |
| 18625 else if (type->type == XML_SCHEMA_TYPE_SIMPLE) | |
| 18626 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type)); | |
| 18627 return(0); | |
| 18628 } | |
| 18629 | |
| 18630 /** | |
| 18631 * xmlSchemaCheckFacet: | |
| 18632 * @facet: the facet | |
| 18633 * @typeDecl: the schema type definition | |
| 18634 * @pctxt: the schema parser context or NULL | |
| 18635 * @name: the optional name of the type | |
| 18636 * | |
| 18637 * Checks and computes the values of facets. | |
| 18638 * | |
| 18639 * Returns 0 if valid, a positive error code if not valid and | |
| 18640 * -1 in case of an internal or API error. | |
| 18641 */ | |
| 18642 int | |
| 18643 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet, | |
| 18644 xmlSchemaTypePtr typeDecl, | |
| 18645 xmlSchemaParserCtxtPtr pctxt, | |
| 18646 const xmlChar * name ATTRIBUTE_UNUSED) | |
| 18647 { | |
| 18648 int ret = 0, ctxtGiven; | |
| 18649 | |
| 18650 if ((facet == NULL) || (typeDecl == NULL)) | |
| 18651 return(-1); | |
| 18652 /* | |
| 18653 * TODO: will the parser context be given if used from | |
| 18654 * the relaxNG module? | |
| 18655 */ | |
| 18656 if (pctxt == NULL) | |
| 18657 ctxtGiven = 0; | |
| 18658 else | |
| 18659 ctxtGiven = 1; | |
| 18660 | |
| 18661 switch (facet->type) { | |
| 18662 case XML_SCHEMA_FACET_MININCLUSIVE: | |
| 18663 case XML_SCHEMA_FACET_MINEXCLUSIVE: | |
| 18664 case XML_SCHEMA_FACET_MAXINCLUSIVE: | |
| 18665 case XML_SCHEMA_FACET_MAXEXCLUSIVE: | |
| 18666 case XML_SCHEMA_FACET_ENUMERATION: { | |
| 18667 /* | |
| 18668 * Okay we need to validate the value | |
| 18669 * at that point. | |
| 18670 */ | |
| 18671 xmlSchemaTypePtr base; | |
| 18672 | |
| 18673 /* 4.3.5.5 Constraints on enumeration Schema Components | |
| 18674 * Schema Component Constraint: enumeration valid restriction | |
| 18675 * It is an `error` if any member of {value} is not in the | |
| 18676 * `value space` of {base type definition}. | |
| 18677 * | |
| 18678 * minInclusive, maxInclusive, minExclusive, maxExclusive: | |
| 18679 * The value `must` be in the | |
| 18680 * `value space` of the `base type`. | |
| 18681 */ | |
| 18682 /* | |
| 18683 * This function is intended to deliver a compiled value | |
| 18684 * on the facet. In this implementation of XML Schemata the | |
| 18685 * type holding a facet, won't be a built-in type. | |
| 18686 * Thus to ensure that other API | |
| 18687 * calls (relaxng) do work, if the given type is a built-in | |
| 18688 * type, we will assume that the given built-in type *is | |
| 18689 * already* the base type. | |
| 18690 */ | |
| 18691 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) { | |
| 18692 base = typeDecl->baseType; | |
| 18693 if (base == NULL) { | |
| 18694 PERROR_INT("xmlSchemaCheckFacet", | |
| 18695 "a type user derived type has no base type"); | |
| 18696 return (-1); | |
| 18697 } | |
| 18698 } else | |
| 18699 base = typeDecl; | |
| 18700 | |
| 18701 if (! ctxtGiven) { | |
| 18702 /* | |
| 18703 * A context is needed if called from RelaxNG. | |
| 18704 */ | |
| 18705 pctxt = xmlSchemaNewParserCtxt("*"); | |
| 18706 if (pctxt == NULL) | |
| 18707 return (-1); | |
| 18708 } | |
| 18709 /* | |
| 18710 * NOTE: This call does not check the content nodes, | |
| 18711 * since they are not available: | |
| 18712 * facet->node is just the node holding the facet | |
| 18713 * definition, *not* the attribute holding the *value* | |
| 18714 * of the facet. | |
| 18715 */ | |
| 18716 ret = xmlSchemaVCheckCVCSimpleType( | |
| 18717 ACTXT_CAST pctxt, facet->node, base, | |
| 18718 facet->value, &(facet->val), 1, 1, 0); | |
| 18719 if (ret != 0) { | |
| 18720 if (ret < 0) { | |
| 18721 /* No error message for RelaxNG. */ | |
| 18722 if (ctxtGiven) { | |
| 18723 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 18724 XML_SCHEMAP_INTERNAL, facet->node, NULL, | |
| 18725 "Internal error: xmlSchemaCheckFacet, " | |
| 18726 "failed to validate the value '%s' of the " | |
| 18727 "facet '%s' against the base type", | |
| 18728 facet->value, xmlSchemaFacetTypeToString(facet->
type)); | |
| 18729 } | |
| 18730 goto internal_error; | |
| 18731 } | |
| 18732 ret = XML_SCHEMAP_INVALID_FACET_VALUE; | |
| 18733 /* No error message for RelaxNG. */ | |
| 18734 if (ctxtGiven) { | |
| 18735 xmlChar *str = NULL; | |
| 18736 | |
| 18737 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 18738 ret, facet->node, WXS_BASIC_CAST facet, | |
| 18739 "The value '%s' of the facet does not validate " | |
| 18740 "against the base type '%s'", | |
| 18741 facet->value, | |
| 18742 xmlSchemaFormatQName(&str, | |
| 18743 base->targetNamespace, base->name)); | |
| 18744 FREE_AND_NULL(str); | |
| 18745 } | |
| 18746 goto exit; | |
| 18747 } else if (facet->val == NULL) { | |
| 18748 if (ctxtGiven) { | |
| 18749 PERROR_INT("xmlSchemaCheckFacet", | |
| 18750 "value was not computed"); | |
| 18751 } | |
| 18752 TODO | |
| 18753 } | |
| 18754 break; | |
| 18755 } | |
| 18756 case XML_SCHEMA_FACET_PATTERN: | |
| 18757 facet->regexp = xmlRegexpCompile(facet->value); | |
| 18758 if (facet->regexp == NULL) { | |
| 18759 ret = XML_SCHEMAP_REGEXP_INVALID; | |
| 18760 /* No error message for RelaxNG. */ | |
| 18761 if (ctxtGiven) { | |
| 18762 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 18763 ret, facet->node, WXS_BASIC_CAST typeDecl, | |
| 18764 "The value '%s' of the facet 'pattern' is not a " | |
| 18765 "valid regular expression", | |
| 18766 facet->value, NULL); | |
| 18767 } | |
| 18768 } | |
| 18769 break; | |
| 18770 case XML_SCHEMA_FACET_TOTALDIGITS: | |
| 18771 case XML_SCHEMA_FACET_FRACTIONDIGITS: | |
| 18772 case XML_SCHEMA_FACET_LENGTH: | |
| 18773 case XML_SCHEMA_FACET_MAXLENGTH: | |
| 18774 case XML_SCHEMA_FACET_MINLENGTH: | |
| 18775 | |
| 18776 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) { | |
| 18777 ret = xmlSchemaValidatePredefinedType( | |
| 18778 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER), | |
| 18779 facet->value, &(facet->val)); | |
| 18780 } else { | |
| 18781 ret = xmlSchemaValidatePredefinedType( | |
| 18782 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER), | |
| 18783 facet->value, &(facet->val)); | |
| 18784 } | |
| 18785 if (ret != 0) { | |
| 18786 if (ret < 0) { | |
| 18787 /* No error message for RelaxNG. */ | |
| 18788 if (ctxtGiven) { | |
| 18789 PERROR_INT("xmlSchemaCheckFacet", | |
| 18790 "validating facet value"); | |
| 18791 } | |
| 18792 goto internal_error; | |
| 18793 } | |
| 18794 ret = XML_SCHEMAP_INVALID_FACET_VALUE; | |
| 18795 /* No error message for RelaxNG. */ | |
| 18796 if (ctxtGiven) { | |
| 18797 /* error code */ | |
| 18798 xmlSchemaCustomErr4(ACTXT_CAST pctxt, | |
| 18799 ret, facet->node, WXS_BASIC_CAST typeDecl, | |
| 18800 "The value '%s' of the facet '%s' is not a valid '%s'", | |
| 18801 facet->value, | |
| 18802 xmlSchemaFacetTypeToString(facet->type), | |
| 18803 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ? | |
| 18804 BAD_CAST "nonNegativeInteger" : | |
| 18805 BAD_CAST "positiveInteger", | |
| 18806 NULL); | |
| 18807 } | |
| 18808 } | |
| 18809 break; | |
| 18810 | |
| 18811 case XML_SCHEMA_FACET_WHITESPACE:{ | |
| 18812 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) { | |
| 18813 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE; | |
| 18814 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) { | |
| 18815 facet->whitespace = XML_SCHEMAS_FACET_REPLACE; | |
| 18816 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) { | |
| 18817 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE; | |
| 18818 } else { | |
| 18819 ret = XML_SCHEMAP_INVALID_FACET_VALUE; | |
| 18820 /* No error message for RelaxNG. */ | |
| 18821 if (ctxtGiven) { | |
| 18822 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE
*/ | |
| 18823 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 18824 ret, facet->node, WXS_BASIC_CAST typeDecl, | |
| 18825 "The value '%s' of the facet 'whitespace' is not " | |
| 18826 "valid", facet->value, NULL); | |
| 18827 } | |
| 18828 } | |
| 18829 } | |
| 18830 default: | |
| 18831 break; | |
| 18832 } | |
| 18833 exit: | |
| 18834 if ((! ctxtGiven) && (pctxt != NULL)) | |
| 18835 xmlSchemaFreeParserCtxt(pctxt); | |
| 18836 return (ret); | |
| 18837 internal_error: | |
| 18838 if ((! ctxtGiven) && (pctxt != NULL)) | |
| 18839 xmlSchemaFreeParserCtxt(pctxt); | |
| 18840 return (-1); | |
| 18841 } | |
| 18842 | |
| 18843 /** | |
| 18844 * xmlSchemaCheckFacetValues: | |
| 18845 * @typeDecl: the schema type definition | |
| 18846 * @ctxt: the schema parser context | |
| 18847 * | |
| 18848 * Checks the default values types, especially for facets | |
| 18849 */ | |
| 18850 static int | |
| 18851 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl, | |
| 18852 xmlSchemaParserCtxtPtr pctxt) | |
| 18853 { | |
| 18854 int res, olderrs = pctxt->nberrors; | |
| 18855 const xmlChar *name = typeDecl->name; | |
| 18856 /* | |
| 18857 * NOTE: It is intended to use the facets list, instead | |
| 18858 * of facetSet. | |
| 18859 */ | |
| 18860 if (typeDecl->facets != NULL) { | |
| 18861 xmlSchemaFacetPtr facet = typeDecl->facets; | |
| 18862 | |
| 18863 /* | |
| 18864 * Temporarily assign the "schema" to the validation context | |
| 18865 * of the parser context. This is needed for NOTATION validation. | |
| 18866 */ | |
| 18867 if (pctxt->vctxt == NULL) { | |
| 18868 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1) | |
| 18869 return(-1); | |
| 18870 } | |
| 18871 pctxt->vctxt->schema = pctxt->schema; | |
| 18872 while (facet != NULL) { | |
| 18873 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name); | |
| 18874 HFAILURE | |
| 18875 facet = facet->next; | |
| 18876 } | |
| 18877 pctxt->vctxt->schema = NULL; | |
| 18878 } | |
| 18879 if (olderrs != pctxt->nberrors) | |
| 18880 return(pctxt->err); | |
| 18881 return(0); | |
| 18882 exit_failure: | |
| 18883 return(-1); | |
| 18884 } | |
| 18885 | |
| 18886 /** | |
| 18887 * xmlSchemaGetCircModelGrDefRef: | |
| 18888 * @ctxtMGroup: the searched model group | |
| 18889 * @selfMGroup: the second searched model group | |
| 18890 * @particle: the first particle | |
| 18891 * | |
| 18892 * This one is intended to be used by | |
| 18893 * xmlSchemaCheckGroupDefCircular only. | |
| 18894 * | |
| 18895 * Returns the particle with the circular model group definition reference, | |
| 18896 * otherwise NULL. | |
| 18897 */ | |
| 18898 static xmlSchemaTreeItemPtr | |
| 18899 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef, | |
| 18900 xmlSchemaTreeItemPtr particle) | |
| 18901 { | |
| 18902 xmlSchemaTreeItemPtr circ = NULL; | |
| 18903 xmlSchemaTreeItemPtr term; | |
| 18904 xmlSchemaModelGroupDefPtr gdef; | |
| 18905 | |
| 18906 for (; particle != NULL; particle = particle->next) { | |
| 18907 term = particle->children; | |
| 18908 if (term == NULL) | |
| 18909 continue; | |
| 18910 switch (term->type) { | |
| 18911 case XML_SCHEMA_TYPE_GROUP: | |
| 18912 gdef = (xmlSchemaModelGroupDefPtr) term; | |
| 18913 if (gdef == groupDef) | |
| 18914 return (particle); | |
| 18915 /* | |
| 18916 * Mark this model group definition to avoid infinite | |
| 18917 * recursion on circular references not yet examined. | |
| 18918 */ | |
| 18919 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED) | |
| 18920 continue; | |
| 18921 if (gdef->children != NULL) { | |
| 18922 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED; | |
| 18923 circ = xmlSchemaGetCircModelGrDefRef(groupDef, | |
| 18924 gdef->children->children); | |
| 18925 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED; | |
| 18926 if (circ != NULL) | |
| 18927 return (circ); | |
| 18928 } | |
| 18929 break; | |
| 18930 case XML_SCHEMA_TYPE_SEQUENCE: | |
| 18931 case XML_SCHEMA_TYPE_CHOICE: | |
| 18932 case XML_SCHEMA_TYPE_ALL: | |
| 18933 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children); | |
| 18934 if (circ != NULL) | |
| 18935 return (circ); | |
| 18936 break; | |
| 18937 default: | |
| 18938 break; | |
| 18939 } | |
| 18940 } | |
| 18941 return (NULL); | |
| 18942 } | |
| 18943 | |
| 18944 /** | |
| 18945 * xmlSchemaCheckGroupDefCircular: | |
| 18946 * @item: the model group definition | |
| 18947 * @ctxt: the parser context | |
| 18948 * @name: the name | |
| 18949 * | |
| 18950 * Checks for circular references to model group definitions. | |
| 18951 */ | |
| 18952 static void | |
| 18953 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item, | |
| 18954 xmlSchemaParserCtxtPtr ctxt) | |
| 18955 { | |
| 18956 /* | |
| 18957 * Schema Component Constraint: Model Group Correct | |
| 18958 * 2 Circular groups are disallowed. That is, within the {particles} | |
| 18959 * of a group there must not be at any depth a particle whose {term} | |
| 18960 * is the group itself. | |
| 18961 */ | |
| 18962 if ((item == NULL) || | |
| 18963 (item->type != XML_SCHEMA_TYPE_GROUP) || | |
| 18964 (item->children == NULL)) | |
| 18965 return; | |
| 18966 { | |
| 18967 xmlSchemaTreeItemPtr circ; | |
| 18968 | |
| 18969 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children); | |
| 18970 if (circ != NULL) { | |
| 18971 xmlChar *str = NULL; | |
| 18972 /* | |
| 18973 * TODO: The error report is not adequate: this constraint | |
| 18974 * is defined for model groups but not definitions, but since | |
| 18975 * there cannot be any circular model groups without a model group | |
| 18976 * definition (if not using a construction API), we check those | |
| 18977 * defintions only. | |
| 18978 */ | |
| 18979 xmlSchemaPCustomErr(ctxt, | |
| 18980 XML_SCHEMAP_MG_PROPS_CORRECT_2, | |
| 18981 NULL, WXS_ITEM_NODE(circ), | |
| 18982 "Circular reference to the model group definition '%s' " | |
| 18983 "defined", xmlSchemaFormatQName(&str, | |
| 18984 item->targetNamespace, item->name)); | |
| 18985 FREE_AND_NULL(str) | |
| 18986 /* | |
| 18987 * NOTE: We will cut the reference to avoid further | |
| 18988 * confusion of the processor. This is a fatal error. | |
| 18989 */ | |
| 18990 circ->children = NULL; | |
| 18991 } | |
| 18992 } | |
| 18993 } | |
| 18994 | |
| 18995 /** | |
| 18996 * xmlSchemaModelGroupToModelGroupDefFixup: | |
| 18997 * @ctxt: the parser context | |
| 18998 * @mg: the model group | |
| 18999 * | |
| 19000 * Assigns the model group of model group definitions to the "term" | |
| 19001 * of the referencing particle. | |
| 19002 * In xmlSchemaResolveModelGroupParticleReferences the model group | |
| 19003 * definitions were assigned to the "term", since needed for the | |
| 19004 * circularity check. | |
| 19005 * | |
| 19006 * Schema Component Constraint: | |
| 19007 * All Group Limited (cos-all-limited) (1.2) | |
| 19008 */ | |
| 19009 static void | |
| 19010 xmlSchemaModelGroupToModelGroupDefFixup( | |
| 19011 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED, | |
| 19012 xmlSchemaModelGroupPtr mg) | |
| 19013 { | |
| 19014 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg); | |
| 19015 | |
| 19016 while (particle != NULL) { | |
| 19017 if ((WXS_PARTICLE_TERM(particle) == NULL) || | |
| 19018 ((WXS_PARTICLE_TERM(particle))->type != | |
| 19019 XML_SCHEMA_TYPE_GROUP)) | |
| 19020 { | |
| 19021 particle = WXS_PTC_CAST particle->next; | |
| 19022 continue; | |
| 19023 } | |
| 19024 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) { | |
| 19025 /* | |
| 19026 * TODO: Remove the particle. | |
| 19027 */ | |
| 19028 WXS_PARTICLE_TERM(particle) = NULL; | |
| 19029 particle = WXS_PTC_CAST particle->next; | |
| 19030 continue; | |
| 19031 } | |
| 19032 /* | |
| 19033 * Assign the model group to the {term} of the particle. | |
| 19034 */ | |
| 19035 WXS_PARTICLE_TERM(particle) = | |
| 19036 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)); | |
| 19037 | |
| 19038 particle = WXS_PTC_CAST particle->next; | |
| 19039 } | |
| 19040 } | |
| 19041 | |
| 19042 /** | |
| 19043 * xmlSchemaCheckAttrGroupCircularRecur: | |
| 19044 * @ctxtGr: the searched attribute group | |
| 19045 * @attr: the current attribute list to be processed | |
| 19046 * | |
| 19047 * This one is intended to be used by | |
| 19048 * xmlSchemaCheckAttrGroupCircular only. | |
| 19049 * | |
| 19050 * Returns the circular attribute grou reference, otherwise NULL. | |
| 19051 */ | |
| 19052 static xmlSchemaQNameRefPtr | |
| 19053 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr, | |
| 19054 xmlSchemaItemListPtr list) | |
| 19055 { | |
| 19056 xmlSchemaAttributeGroupPtr gr; | |
| 19057 xmlSchemaQNameRefPtr ref, circ; | |
| 19058 int i; | |
| 19059 /* | |
| 19060 * We will search for an attribute group reference which | |
| 19061 * references the context attribute group. | |
| 19062 */ | |
| 19063 for (i = 0; i < list->nbItems; i++) { | |
| 19064 ref = list->items[i]; | |
| 19065 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) && | |
| 19066 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) && | |
| 19067 (ref->item != NULL)) | |
| 19068 { | |
| 19069 gr = WXS_ATTR_GROUP_CAST ref->item; | |
| 19070 if (gr == ctxtGr) | |
| 19071 return(ref); | |
| 19072 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED) | |
| 19073 continue; | |
| 19074 /* | |
| 19075 * Mark as visited to avoid infinite recursion on | |
| 19076 * circular references not yet examined. | |
| 19077 */ | |
| 19078 if ((gr->attrUses) && | |
| 19079 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)) | |
| 19080 { | |
| 19081 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED; | |
| 19082 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr, | |
| 19083 (xmlSchemaItemListPtr) gr->attrUses); | |
| 19084 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED; | |
| 19085 if (circ != NULL) | |
| 19086 return (circ); | |
| 19087 } | |
| 19088 | |
| 19089 } | |
| 19090 } | |
| 19091 return (NULL); | |
| 19092 } | |
| 19093 | |
| 19094 /** | |
| 19095 * xmlSchemaCheckAttrGroupCircular: | |
| 19096 * attrGr: the attribute group definition | |
| 19097 * @ctxt: the parser context | |
| 19098 * @name: the name | |
| 19099 * | |
| 19100 * Checks for circular references of attribute groups. | |
| 19101 */ | |
| 19102 static int | |
| 19103 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr, | |
| 19104 xmlSchemaParserCtxtPtr ctxt) | |
| 19105 { | |
| 19106 /* | |
| 19107 * Schema Representation Constraint: | |
| 19108 * Attribute Group Definition Representation OK | |
| 19109 * 3 Circular group reference is disallowed outside <redefine>. | |
| 19110 * That is, unless this element information item's parent is | |
| 19111 * <redefine>, then among the [children], if any, there must | |
| 19112 * not be an <attributeGroup> with ref [attribute] which resolves | |
| 19113 * to the component corresponding to this <attributeGroup>. Indirect | |
| 19114 * circularity is also ruled out. That is, when QName resolution | |
| 19115 * (Schema Document) ($3.15.3) is applied to a `QName` arising from | |
| 19116 * any <attributeGroup>s with a ref [attribute] among the [children], | |
| 19117 * it must not be the case that a `QName` is encountered at any depth | |
| 19118 * which resolves to the component corresponding to this <attributeGroup>. | |
| 19119 */ | |
| 19120 if (attrGr->attrUses == NULL) | |
| 19121 return(0); | |
| 19122 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0) | |
| 19123 return(0); | |
| 19124 else { | |
| 19125 xmlSchemaQNameRefPtr circ; | |
| 19126 | |
| 19127 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr, | |
| 19128 (xmlSchemaItemListPtr) attrGr->attrUses); | |
| 19129 if (circ != NULL) { | |
| 19130 xmlChar *str = NULL; | |
| 19131 /* | |
| 19132 * TODO: Report the referenced attr group as QName. | |
| 19133 */ | |
| 19134 xmlSchemaPCustomErr(ctxt, | |
| 19135 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3, | |
| 19136 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ), | |
| 19137 "Circular reference to the attribute group '%s' " | |
| 19138 "defined", xmlSchemaGetComponentQName(&str, attrGr)); | |
| 19139 FREE_AND_NULL(str); | |
| 19140 /* | |
| 19141 * NOTE: We will cut the reference to avoid further | |
| 19142 * confusion of the processor. | |
| 19143 * BADSPEC TODO: The spec should define how to process in this case. | |
| 19144 */ | |
| 19145 circ->item = NULL; | |
| 19146 return(ctxt->err); | |
| 19147 } | |
| 19148 } | |
| 19149 return(0); | |
| 19150 } | |
| 19151 | |
| 19152 static int | |
| 19153 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt, | |
| 19154 xmlSchemaAttributeGroupPtr attrGr); | |
| 19155 | |
| 19156 /** | |
| 19157 * xmlSchemaExpandAttributeGroupRefs: | |
| 19158 * @pctxt: the parser context | |
| 19159 * @node: the node of the component holding the attribute uses | |
| 19160 * @completeWild: the intersected wildcard to be returned | |
| 19161 * @list: the attribute uses | |
| 19162 * | |
| 19163 * Substitutes contained attribute group references | |
| 19164 * for their attribute uses. Wilcards are intersected. | |
| 19165 * Attribute use prohibitions are removed from the list | |
| 19166 * and returned via the @prohibs list. | |
| 19167 * Pointlessness of attr. prohibs, if a matching attr. decl | |
| 19168 * is existent a well, are checked. | |
| 19169 */ | |
| 19170 static int | |
| 19171 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt, | |
| 19172 xmlSchemaBasicItemPtr item, | |
| 19173 xmlSchemaWildcardPtr *completeWild, | |
| 19174 xmlSchemaItemListPtr list, | |
| 19175 xmlSchemaItemListPtr prohibs) | |
| 19176 { | |
| 19177 xmlSchemaAttributeGroupPtr gr; | |
| 19178 xmlSchemaAttributeUsePtr use; | |
| 19179 xmlSchemaItemListPtr sublist; | |
| 19180 int i, j; | |
| 19181 int created = (*completeWild == NULL) ? 0 : 1; | |
| 19182 | |
| 19183 if (prohibs) | |
| 19184 prohibs->nbItems = 0; | |
| 19185 | |
| 19186 for (i = 0; i < list->nbItems; i++) { | |
| 19187 use = list->items[i]; | |
| 19188 | |
| 19189 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) { | |
| 19190 if (prohibs == NULL) { | |
| 19191 PERROR_INT("xmlSchemaExpandAttributeGroupRefs", | |
| 19192 "unexpected attr prohibition found"); | |
| 19193 return(-1); | |
| 19194 } | |
| 19195 /* | |
| 19196 * Remove from attribute uses. | |
| 19197 */ | |
| 19198 if (xmlSchemaItemListRemove(list, i) == -1) | |
| 19199 return(-1); | |
| 19200 i--; | |
| 19201 /* | |
| 19202 * Note that duplicate prohibitions were already | |
| 19203 * handled at parsing time. | |
| 19204 */ | |
| 19205 /* | |
| 19206 * Add to list of prohibitions. | |
| 19207 */ | |
| 19208 xmlSchemaItemListAddSize(prohibs, 2, use); | |
| 19209 continue; | |
| 19210 } | |
| 19211 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) && | |
| 19212 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)) | |
| 19213 { | |
| 19214 if ((WXS_QNAME_CAST use)->item == NULL) | |
| 19215 return(-1); | |
| 19216 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item; | |
| 19217 /* | |
| 19218 * Expand the referenced attr. group. | |
| 19219 * TODO: remove this, this is done in a previous step, so | |
| 19220 * already done here. | |
| 19221 */ | |
| 19222 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) { | |
| 19223 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1) | |
| 19224 return(-1); | |
| 19225 } | |
| 19226 /* | |
| 19227 * Build the 'complete' wildcard; i.e. intersect multiple | |
| 19228 * wildcards. | |
| 19229 */ | |
| 19230 if (gr->attributeWildcard != NULL) { | |
| 19231 if (*completeWild == NULL) { | |
| 19232 *completeWild = gr->attributeWildcard; | |
| 19233 } else { | |
| 19234 if (! created) { | |
| 19235 xmlSchemaWildcardPtr tmpWild; | |
| 19236 | |
| 19237 /* | |
| 19238 * Copy the first encountered wildcard as context, | |
| 19239 * except for the annotation. | |
| 19240 * | |
| 19241 * Although the complete wildcard might not correspond | |
| 19242 * to any node in the schema, we will anchor it on | |
| 19243 * the node of the owner component. | |
| 19244 */ | |
| 19245 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema, | |
| 19246 XML_SCHEMA_TYPE_ANY_ATTRIBUTE, | |
| 19247 WXS_ITEM_NODE(item)); | |
| 19248 if (tmpWild == NULL) | |
| 19249 return(-1); | |
| 19250 if (xmlSchemaCloneWildcardNsConstraints(pctxt, | |
| 19251 tmpWild, *completeWild) == -1) | |
| 19252 return (-1); | |
| 19253 tmpWild->processContents = (*completeWild)->processConte
nts; | |
| 19254 *completeWild = tmpWild; | |
| 19255 created = 1; | |
| 19256 } | |
| 19257 | |
| 19258 if (xmlSchemaIntersectWildcards(pctxt, *completeWild, | |
| 19259 gr->attributeWildcard) == -1) | |
| 19260 return(-1); | |
| 19261 } | |
| 19262 } | |
| 19263 /* | |
| 19264 * Just remove the reference if the referenced group does not | |
| 19265 * contain any attribute uses. | |
| 19266 */ | |
| 19267 sublist = ((xmlSchemaItemListPtr) gr->attrUses); | |
| 19268 if ((sublist == NULL) || sublist->nbItems == 0) { | |
| 19269 if (xmlSchemaItemListRemove(list, i) == -1) | |
| 19270 return(-1); | |
| 19271 i--; | |
| 19272 continue; | |
| 19273 } | |
| 19274 /* | |
| 19275 * Add the attribute uses. | |
| 19276 */ | |
| 19277 list->items[i] = sublist->items[0]; | |
| 19278 if (sublist->nbItems != 1) { | |
| 19279 for (j = 1; j < sublist->nbItems; j++) { | |
| 19280 i++; | |
| 19281 if (xmlSchemaItemListInsert(list, | |
| 19282 sublist->items[j], i) == -1) | |
| 19283 return(-1); | |
| 19284 } | |
| 19285 } | |
| 19286 } | |
| 19287 | |
| 19288 } | |
| 19289 /* | |
| 19290 * Handle pointless prohibitions of declared attributes. | |
| 19291 */ | |
| 19292 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) { | |
| 19293 xmlSchemaAttributeUseProhibPtr prohib; | |
| 19294 | |
| 19295 for (i = prohibs->nbItems -1; i >= 0; i--) { | |
| 19296 prohib = prohibs->items[i]; | |
| 19297 for (j = 0; j < list->nbItems; j++) { | |
| 19298 use = list->items[j]; | |
| 19299 | |
| 19300 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) && | |
| 19301 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use))) | |
| 19302 { | |
| 19303 xmlChar *str = NULL; | |
| 19304 | |
| 19305 xmlSchemaCustomWarning(ACTXT_CAST pctxt, | |
| 19306 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, | |
| 19307 prohib->node, NULL, | |
| 19308 "Skipping pointless attribute use prohibition " | |
| 19309 "'%s', since a corresponding attribute use " | |
| 19310 "exists already in the type definition", | |
| 19311 xmlSchemaFormatQName(&str, | |
| 19312 prohib->targetNamespace, prohib->name), | |
| 19313 NULL, NULL); | |
| 19314 FREE_AND_NULL(str); | |
| 19315 /* | |
| 19316 * Remove the prohibition. | |
| 19317 */ | |
| 19318 if (xmlSchemaItemListRemove(prohibs, i) == -1) | |
| 19319 return(-1); | |
| 19320 break; | |
| 19321 } | |
| 19322 } | |
| 19323 } | |
| 19324 } | |
| 19325 return(0); | |
| 19326 } | |
| 19327 | |
| 19328 /** | |
| 19329 * xmlSchemaAttributeGroupExpandRefs: | |
| 19330 * @pctxt: the parser context | |
| 19331 * @attrGr: the attribute group definition | |
| 19332 * | |
| 19333 * Computation of: | |
| 19334 * {attribute uses} property | |
| 19335 * {attribute wildcard} property | |
| 19336 * | |
| 19337 * Substitutes contained attribute group references | |
| 19338 * for their attribute uses. Wilcards are intersected. | |
| 19339 */ | |
| 19340 static int | |
| 19341 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt, | |
| 19342 xmlSchemaAttributeGroupPtr attrGr) | |
| 19343 { | |
| 19344 if ((attrGr->attrUses == NULL) || | |
| 19345 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)) | |
| 19346 return(0); | |
| 19347 | |
| 19348 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED; | |
| 19349 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr, | |
| 19350 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1) | |
| 19351 return(-1); | |
| 19352 return(0); | |
| 19353 } | |
| 19354 | |
| 19355 /** | |
| 19356 * xmlSchemaAttributeGroupExpandRefs: | |
| 19357 * @pctxt: the parser context | |
| 19358 * @attrGr: the attribute group definition | |
| 19359 * | |
| 19360 * Substitutes contained attribute group references | |
| 19361 * for their attribute uses. Wilcards are intersected. | |
| 19362 * | |
| 19363 * Schema Component Constraint: | |
| 19364 * Attribute Group Definition Properties Correct (ag-props-correct) | |
| 19365 */ | |
| 19366 static int | |
| 19367 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt, | |
| 19368 xmlSchemaAttributeGroupPtr attrGr) | |
| 19369 { | |
| 19370 /* | |
| 19371 * SPEC ag-props-correct | |
| 19372 * (1) "The values of the properties of an attribute group definition | |
| 19373 * must be as described in the property tableau in The Attribute | |
| 19374 * Group Definition Schema Component ($3.6.1), modulo the impact of | |
| 19375 * Missing Sub-components ($5.3);" | |
| 19376 */ | |
| 19377 | |
| 19378 if ((attrGr->attrUses != NULL) && | |
| 19379 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1) | |
| 19380 { | |
| 19381 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses; | |
| 19382 xmlSchemaAttributeUsePtr use, tmp; | |
| 19383 int i, j, hasId = 0; | |
| 19384 | |
| 19385 for (i = uses->nbItems -1; i >= 0; i--) { | |
| 19386 use = uses->items[i]; | |
| 19387 /* | |
| 19388 * SPEC ag-props-correct | |
| 19389 * (2) "Two distinct members of the {attribute uses} must not have | |
| 19390 * {attribute declaration}s both of whose {name}s match and whose | |
| 19391 * {target namespace}s are identical." | |
| 19392 */ | |
| 19393 if (i > 0) { | |
| 19394 for (j = i -1; j >= 0; j--) { | |
| 19395 tmp = uses->items[j]; | |
| 19396 if ((WXS_ATTRUSE_DECL_NAME(use) == | |
| 19397 WXS_ATTRUSE_DECL_NAME(tmp)) && | |
| 19398 (WXS_ATTRUSE_DECL_TNS(use) == | |
| 19399 WXS_ATTRUSE_DECL_TNS(tmp))) | |
| 19400 { | |
| 19401 xmlChar *str = NULL; | |
| 19402 | |
| 19403 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 19404 XML_SCHEMAP_AG_PROPS_CORRECT, | |
| 19405 attrGr->node, WXS_BASIC_CAST attrGr, | |
| 19406 "Duplicate %s", | |
| 19407 xmlSchemaGetComponentDesignation(&str, use), | |
| 19408 NULL); | |
| 19409 FREE_AND_NULL(str); | |
| 19410 /* | |
| 19411 * Remove the duplicate. | |
| 19412 */ | |
| 19413 if (xmlSchemaItemListRemove(uses, i) == -1) | |
| 19414 return(-1); | |
| 19415 goto next_use; | |
| 19416 } | |
| 19417 } | |
| 19418 } | |
| 19419 /* | |
| 19420 * SPEC ag-props-correct | |
| 19421 * (3) "Two distinct members of the {attribute uses} must not have | |
| 19422 * {attribute declaration}s both of whose {type definition}s are or | |
| 19423 * are derived from ID." | |
| 19424 * TODO: Does 'derived' include member-types of unions? | |
| 19425 */ | |
| 19426 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) { | |
| 19427 if (xmlSchemaIsDerivedFromBuiltInType( | |
| 19428 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID)) | |
| 19429 { | |
| 19430 if (hasId) { | |
| 19431 xmlChar *str = NULL; | |
| 19432 | |
| 19433 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 19434 XML_SCHEMAP_AG_PROPS_CORRECT, | |
| 19435 attrGr->node, WXS_BASIC_CAST attrGr, | |
| 19436 "There must not exist more than one attribute " | |
| 19437 "declaration of type 'xs:ID' " | |
| 19438 "(or derived from 'xs:ID'). The %s violates this " | |
| 19439 "constraint", | |
| 19440 xmlSchemaGetComponentDesignation(&str, use), | |
| 19441 NULL); | |
| 19442 FREE_AND_NULL(str); | |
| 19443 if (xmlSchemaItemListRemove(uses, i) == -1) | |
| 19444 return(-1); | |
| 19445 } | |
| 19446 hasId = 1; | |
| 19447 } | |
| 19448 } | |
| 19449 next_use: {} | |
| 19450 } | |
| 19451 } | |
| 19452 return(0); | |
| 19453 } | |
| 19454 | |
| 19455 /** | |
| 19456 * xmlSchemaResolveAttrGroupReferences: | |
| 19457 * @attrgrpDecl: the schema attribute definition | |
| 19458 * @ctxt: the schema parser context | |
| 19459 * @name: the attribute name | |
| 19460 * | |
| 19461 * Resolves references to attribute group definitions. | |
| 19462 */ | |
| 19463 static int | |
| 19464 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref, | |
| 19465 xmlSchemaParserCtxtPtr ctxt) | |
| 19466 { | |
| 19467 xmlSchemaAttributeGroupPtr group; | |
| 19468 | |
| 19469 if (ref->item != NULL) | |
| 19470 return(0); | |
| 19471 group = xmlSchemaGetAttributeGroup(ctxt->schema, | |
| 19472 ref->name, | |
| 19473 ref->targetNamespace); | |
| 19474 if (group == NULL) { | |
| 19475 xmlSchemaPResCompAttrErr(ctxt, | |
| 19476 XML_SCHEMAP_SRC_RESOLVE, | |
| 19477 NULL, ref->node, | |
| 19478 "ref", ref->name, ref->targetNamespace, | |
| 19479 ref->itemType, NULL); | |
| 19480 return(ctxt->err); | |
| 19481 } | |
| 19482 ref->item = WXS_BASIC_CAST group; | |
| 19483 return(0); | |
| 19484 } | |
| 19485 | |
| 19486 /** | |
| 19487 * xmlSchemaCheckAttrPropsCorrect: | |
| 19488 * @item: an schema attribute declaration/use | |
| 19489 * @ctxt: a schema parser context | |
| 19490 * @name: the name of the attribute | |
| 19491 * | |
| 19492 * | |
| 19493 * Schema Component Constraint: | |
| 19494 * Attribute Declaration Properties Correct (a-props-correct) | |
| 19495 * | |
| 19496 * Validates the value constraints of an attribute declaration/use. | |
| 19497 * NOTE that this needs the simle type definitions to be already | |
| 19498 * builded and checked. | |
| 19499 */ | |
| 19500 static int | |
| 19501 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt, | |
| 19502 xmlSchemaAttributePtr attr) | |
| 19503 { | |
| 19504 | |
| 19505 /* | |
| 19506 * SPEC a-props-correct (1) | |
| 19507 * "The values of the properties of an attribute declaration must | |
| 19508 * be as described in the property tableau in The Attribute | |
| 19509 * Declaration Schema Component ($3.2.1), modulo the impact of | |
| 19510 * Missing Sub-components ($5.3)." | |
| 19511 */ | |
| 19512 | |
| 19513 if (WXS_ATTR_TYPEDEF(attr) == NULL) | |
| 19514 return(0); | |
| 19515 | |
| 19516 if (attr->defValue != NULL) { | |
| 19517 int ret; | |
| 19518 | |
| 19519 /* | |
| 19520 * SPEC a-props-correct (3) | |
| 19521 * "If the {type definition} is or is derived from ID then there | |
| 19522 * must not be a {value constraint}." | |
| 19523 */ | |
| 19524 if (xmlSchemaIsDerivedFromBuiltInType( | |
| 19525 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID)) | |
| 19526 { | |
| 19527 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 19528 XML_SCHEMAP_A_PROPS_CORRECT_3, | |
| 19529 NULL, WXS_BASIC_CAST attr, | |
| 19530 "Value constraints are not allowed if the type definition " | |
| 19531 "is or is derived from xs:ID", | |
| 19532 NULL, NULL); | |
| 19533 return(pctxt->err); | |
| 19534 } | |
| 19535 /* | |
| 19536 * SPEC a-props-correct (2) | |
| 19537 * "if there is a {value constraint}, the canonical lexical | |
| 19538 * representation of its value must be `valid` with respect | |
| 19539 * to the {type definition} as defined in String Valid ($3.14.4)." | |
| 19540 * TODO: Don't care about the *canonical* stuff here, this requirement | |
| 19541 * will be removed in WXS 1.1 anyway. | |
| 19542 */ | |
| 19543 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, | |
| 19544 attr->node, WXS_ATTR_TYPEDEF(attr), | |
| 19545 attr->defValue, &(attr->defVal), | |
| 19546 1, 1, 0); | |
| 19547 if (ret != 0) { | |
| 19548 if (ret < 0) { | |
| 19549 PERROR_INT("xmlSchemaCheckAttrPropsCorrect", | |
| 19550 "calling xmlSchemaVCheckCVCSimpleType()"); | |
| 19551 return(-1); | |
| 19552 } | |
| 19553 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 19554 XML_SCHEMAP_A_PROPS_CORRECT_2, | |
| 19555 NULL, WXS_BASIC_CAST attr, | |
| 19556 "The value of the value constraint is not valid", | |
| 19557 NULL, NULL); | |
| 19558 return(pctxt->err); | |
| 19559 } | |
| 19560 } | |
| 19561 | |
| 19562 return(0); | |
| 19563 } | |
| 19564 | |
| 19565 static xmlSchemaElementPtr | |
| 19566 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl, | |
| 19567 xmlSchemaElementPtr ancestor) | |
| 19568 { | |
| 19569 xmlSchemaElementPtr ret; | |
| 19570 | |
| 19571 if (WXS_SUBST_HEAD(ancestor) == NULL) | |
| 19572 return (NULL); | |
| 19573 if (WXS_SUBST_HEAD(ancestor) == elemDecl) | |
| 19574 return (ancestor); | |
| 19575 | |
| 19576 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR) | |
| 19577 return (NULL); | |
| 19578 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR; | |
| 19579 ret = xmlSchemaCheckSubstGroupCircular(elemDecl, | |
| 19580 WXS_SUBST_HEAD(ancestor)); | |
| 19581 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR; | |
| 19582 | |
| 19583 return (ret); | |
| 19584 } | |
| 19585 | |
| 19586 /** | |
| 19587 * xmlSchemaCheckElemPropsCorrect: | |
| 19588 * @ctxt: a schema parser context | |
| 19589 * @decl: the element declaration | |
| 19590 * @name: the name of the attribute | |
| 19591 * | |
| 19592 * Schema Component Constraint: | |
| 19593 * Element Declaration Properties Correct (e-props-correct) | |
| 19594 * | |
| 19595 * STATUS: | |
| 19596 * missing: (6) | |
| 19597 */ | |
| 19598 static int | |
| 19599 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt, | |
| 19600 xmlSchemaElementPtr elemDecl) | |
| 19601 { | |
| 19602 int ret = 0; | |
| 19603 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl); | |
| 19604 /* | |
| 19605 * SPEC (1) "The values of the properties of an element declaration | |
| 19606 * must be as described in the property tableau in The Element | |
| 19607 * Declaration Schema Component ($3.3.1), modulo the impact of Missing | |
| 19608 * Sub-components ($5.3)." | |
| 19609 */ | |
| 19610 if (WXS_SUBST_HEAD(elemDecl) != NULL) { | |
| 19611 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ; | |
| 19612 | |
| 19613 xmlSchemaCheckElementDeclComponent(head, pctxt); | |
| 19614 /* | |
| 19615 * SPEC (3) "If there is a non-`absent` {substitution group | |
| 19616 * affiliation}, then {scope} must be global." | |
| 19617 */ | |
| 19618 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) { | |
| 19619 xmlSchemaPCustomErr(pctxt, | |
| 19620 XML_SCHEMAP_E_PROPS_CORRECT_3, | |
| 19621 WXS_BASIC_CAST elemDecl, NULL, | |
| 19622 "Only global element declarations can have a " | |
| 19623 "substitution group affiliation", NULL); | |
| 19624 ret = XML_SCHEMAP_E_PROPS_CORRECT_3; | |
| 19625 } | |
| 19626 /* | |
| 19627 * TODO: SPEC (6) "Circular substitution groups are disallowed. | |
| 19628 * That is, it must not be possible to return to an element declaration | |
| 19629 * by repeatedly following the {substitution group affiliation} | |
| 19630 * property." | |
| 19631 */ | |
| 19632 if (head == elemDecl) | |
| 19633 circ = head; | |
| 19634 else if (WXS_SUBST_HEAD(head) != NULL) | |
| 19635 circ = xmlSchemaCheckSubstGroupCircular(head, head); | |
| 19636 else | |
| 19637 circ = NULL; | |
| 19638 if (circ != NULL) { | |
| 19639 xmlChar *strA = NULL, *strB = NULL; | |
| 19640 | |
| 19641 xmlSchemaPCustomErrExt(pctxt, | |
| 19642 XML_SCHEMAP_E_PROPS_CORRECT_6, | |
| 19643 WXS_BASIC_CAST circ, NULL, | |
| 19644 "The element declaration '%s' defines a circular " | |
| 19645 "substitution group to element declaration '%s'", | |
| 19646 xmlSchemaGetComponentQName(&strA, circ), | |
| 19647 xmlSchemaGetComponentQName(&strB, head), | |
| 19648 NULL); | |
| 19649 FREE_AND_NULL(strA) | |
| 19650 FREE_AND_NULL(strB) | |
| 19651 ret = XML_SCHEMAP_E_PROPS_CORRECT_6; | |
| 19652 } | |
| 19653 /* | |
| 19654 * SPEC (4) "If there is a {substitution group affiliation}, | |
| 19655 * the {type definition} | |
| 19656 * of the element declaration must be validly derived from the {type | |
| 19657 * definition} of the {substitution group affiliation}, given the value | |
| 19658 * of the {substitution group exclusions} of the {substitution group | |
| 19659 * affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6) | |
| 19660 * (if the {type definition} is complex) or as defined in | |
| 19661 * Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is | |
| 19662 * simple)." | |
| 19663 * | |
| 19664 * NOTE: {substitution group exclusions} means the values of the | |
| 19665 * attribute "final". | |
| 19666 */ | |
| 19667 | |
| 19668 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) { | |
| 19669 int set = 0; | |
| 19670 | |
| 19671 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION) | |
| 19672 set |= SUBSET_EXTENSION; | |
| 19673 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION) | |
| 19674 set |= SUBSET_RESTRICTION; | |
| 19675 | |
| 19676 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef, | |
| 19677 WXS_ELEM_TYPEDEF(head), set) != 0) { | |
| 19678 xmlChar *strA = NULL, *strB = NULL, *strC = NULL; | |
| 19679 | |
| 19680 ret = XML_SCHEMAP_E_PROPS_CORRECT_4; | |
| 19681 xmlSchemaPCustomErrExt(pctxt, | |
| 19682 XML_SCHEMAP_E_PROPS_CORRECT_4, | |
| 19683 WXS_BASIC_CAST elemDecl, NULL, | |
| 19684 "The type definition '%s' was " | |
| 19685 "either rejected by the substitution group " | |
| 19686 "affiliation '%s', or not validly derived from its type " | |
| 19687 "definition '%s'", | |
| 19688 xmlSchemaGetComponentQName(&strA, typeDef), | |
| 19689 xmlSchemaGetComponentQName(&strB, head), | |
| 19690 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head))); | |
| 19691 FREE_AND_NULL(strA) | |
| 19692 FREE_AND_NULL(strB) | |
| 19693 FREE_AND_NULL(strC) | |
| 19694 } | |
| 19695 } | |
| 19696 } | |
| 19697 /* | |
| 19698 * SPEC (5) "If the {type definition} or {type definition}'s | |
| 19699 * {content type} | |
| 19700 * is or is derived from ID then there must not be a {value constraint}. | |
| 19701 * Note: The use of ID as a type definition for elements goes beyond | |
| 19702 * XML 1.0, and should be avoided if backwards compatibility is desired" | |
| 19703 */ | |
| 19704 if ((elemDecl->value != NULL) && | |
| 19705 ((WXS_IS_SIMPLE(typeDef) && | |
| 19706 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) || | |
| 19707 (WXS_IS_COMPLEX(typeDef) && | |
| 19708 WXS_HAS_SIMPLE_CONTENT(typeDef) && | |
| 19709 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef, | |
| 19710 XML_SCHEMAS_ID)))) { | |
| 19711 | |
| 19712 ret = XML_SCHEMAP_E_PROPS_CORRECT_5; | |
| 19713 xmlSchemaPCustomErr(pctxt, | |
| 19714 XML_SCHEMAP_E_PROPS_CORRECT_5, | |
| 19715 WXS_BASIC_CAST elemDecl, NULL, | |
| 19716 "The type definition (or type definition's content type) is or " | |
| 19717 "is derived from ID; value constraints are not allowed in " | |
| 19718 "conjunction with such a type definition", NULL); | |
| 19719 } else if (elemDecl->value != NULL) { | |
| 19720 int vcret; | |
| 19721 xmlNodePtr node = NULL; | |
| 19722 | |
| 19723 /* | |
| 19724 * SPEC (2) "If there is a {value constraint}, the canonical lexical | |
| 19725 * representation of its value must be `valid` with respect to the | |
| 19726 * {type definition} as defined in Element Default Valid (Immediate) | |
| 19727 * ($3.3.6)." | |
| 19728 */ | |
| 19729 if (typeDef == NULL) { | |
| 19730 xmlSchemaPErr(pctxt, elemDecl->node, | |
| 19731 XML_SCHEMAP_INTERNAL, | |
| 19732 "Internal error: xmlSchemaCheckElemPropsCorrect, " | |
| 19733 "type is missing... skipping validation of " | |
| 19734 "the value constraint", NULL, NULL); | |
| 19735 return (-1); | |
| 19736 } | |
| 19737 if (elemDecl->node != NULL) { | |
| 19738 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) | |
| 19739 node = (xmlNodePtr) xmlHasProp(elemDecl->node, | |
| 19740 BAD_CAST "fixed"); | |
| 19741 else | |
| 19742 node = (xmlNodePtr) xmlHasProp(elemDecl->node, | |
| 19743 BAD_CAST "default"); | |
| 19744 } | |
| 19745 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node, | |
| 19746 typeDef, elemDecl->value, &(elemDecl->defVal)); | |
| 19747 if (vcret != 0) { | |
| 19748 if (vcret < 0) { | |
| 19749 PERROR_INT("xmlSchemaElemCheckValConstr", | |
| 19750 "failed to validate the value constraint of an " | |
| 19751 "element declaration"); | |
| 19752 return (-1); | |
| 19753 } | |
| 19754 return (vcret); | |
| 19755 } | |
| 19756 } | |
| 19757 | |
| 19758 return (ret); | |
| 19759 } | |
| 19760 | |
| 19761 /** | |
| 19762 * xmlSchemaCheckElemSubstGroup: | |
| 19763 * @ctxt: a schema parser context | |
| 19764 * @decl: the element declaration | |
| 19765 * @name: the name of the attribute | |
| 19766 * | |
| 19767 * Schema Component Constraint: | |
| 19768 * Substitution Group (cos-equiv-class) | |
| 19769 * | |
| 19770 * In Libxml2 the subst. groups will be precomputed, in terms of that | |
| 19771 * a list will be built for each subst. group head, holding all direct | |
| 19772 * referents to this head. | |
| 19773 * NOTE that this function needs: | |
| 19774 * 1. circular subst. groups to be checked beforehand | |
| 19775 * 2. the declaration's type to be derived from the head's type | |
| 19776 * | |
| 19777 * STATUS: | |
| 19778 * | |
| 19779 */ | |
| 19780 static void | |
| 19781 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt, | |
| 19782 xmlSchemaElementPtr elemDecl) | |
| 19783 { | |
| 19784 if ((WXS_SUBST_HEAD(elemDecl) == NULL) || | |
| 19785 /* SPEC (1) "Its {abstract} is false." */ | |
| 19786 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)) | |
| 19787 return; | |
| 19788 { | |
| 19789 xmlSchemaElementPtr head; | |
| 19790 xmlSchemaTypePtr headType, type; | |
| 19791 int set, methSet; | |
| 19792 /* | |
| 19793 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's | |
| 19794 * {disallowed substitutions} as the blocking constraint, as defined in | |
| 19795 * Substitution Group OK (Transitive) ($3.3.6)." | |
| 19796 */ | |
| 19797 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL; | |
| 19798 head = WXS_SUBST_HEAD(head)) { | |
| 19799 set = 0; | |
| 19800 methSet = 0; | |
| 19801 /* | |
| 19802 * The blocking constraints. | |
| 19803 */ | |
| 19804 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) | |
| 19805 continue; | |
| 19806 headType = head->subtypes; | |
| 19807 type = elemDecl->subtypes; | |
| 19808 if (headType == type) | |
| 19809 goto add_member; | |
| 19810 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) | |
| 19811 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; | |
| 19812 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) | |
| 19813 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; | |
| 19814 /* | |
| 19815 * SPEC: Substitution Group OK (Transitive) (2.3) | |
| 19816 * "The set of all {derivation method}s involved in the | |
| 19817 * derivation of D's {type definition} from C's {type definition} | |
| 19818 * does not intersect with the union of the blocking constraint, | |
| 19819 * C's {prohibited substitutions} (if C is complex, otherwise the | |
| 19820 * empty set) and the {prohibited substitutions} (respectively the | |
| 19821 * empty set) of any intermediate {type definition}s in the | |
| 19822 * derivation of D's {type definition} from C's {type definition}." | |
| 19823 */ | |
| 19824 /* | |
| 19825 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the | |
| 19826 * subst.head axis, the methSet does not need to be computed for | |
| 19827 * the full depth over and over. | |
| 19828 */ | |
| 19829 /* | |
| 19830 * The set of all {derivation method}s involved in the derivation | |
| 19831 */ | |
| 19832 while ((type != NULL) && (type != headType)) { | |
| 19833 if ((WXS_IS_EXTENSION(type)) && | |
| 19834 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0)) | |
| 19835 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; | |
| 19836 | |
| 19837 if (WXS_IS_RESTRICTION(type) && | |
| 19838 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0)) | |
| 19839 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; | |
| 19840 | |
| 19841 type = type->baseType; | |
| 19842 } | |
| 19843 /* | |
| 19844 * The {prohibited substitutions} of all intermediate types + | |
| 19845 * the head's type. | |
| 19846 */ | |
| 19847 type = elemDecl->subtypes->baseType; | |
| 19848 while (type != NULL) { | |
| 19849 if (WXS_IS_COMPLEX(type)) { | |
| 19850 if ((type->flags & | |
| 19851 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) && | |
| 19852 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0)) | |
| 19853 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; | |
| 19854 if ((type->flags & | |
| 19855 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) && | |
| 19856 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0)) | |
| 19857 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; | |
| 19858 } else | |
| 19859 break; | |
| 19860 if (type == headType) | |
| 19861 break; | |
| 19862 type = type->baseType; | |
| 19863 } | |
| 19864 if ((set != 0) && | |
| 19865 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) && | |
| 19866 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) || | |
| 19867 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) && | |
| 19868 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) { | |
| 19869 continue; | |
| 19870 } | |
| 19871 add_member: | |
| 19872 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl); | |
| 19873 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0) | |
| 19874 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD; | |
| 19875 } | |
| 19876 } | |
| 19877 } | |
| 19878 | |
| 19879 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */ | |
| 19880 /** | |
| 19881 * xmlSchemaCheckElementDeclComponent | |
| 19882 * @pctxt: the schema parser context | |
| 19883 * @ctxtComponent: the context component (an element declaration) | |
| 19884 * @ctxtParticle: the first particle of the context component | |
| 19885 * @searchParticle: the element declaration particle to be analysed | |
| 19886 * | |
| 19887 * Schema Component Constraint: Element Declarations Consistent | |
| 19888 */ | |
| 19889 static int | |
| 19890 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt, | |
| 19891 xmlSchemaBasicItemPtr ctxtComponent, | |
| 19892 xmlSchemaParticlePtr ctxtParticle, | |
| 19893 xmlSchemaParticlePtr searchParticle, | |
| 19894 xmlSchemaParticlePtr curParticle, | |
| 19895 int search) | |
| 19896 { | |
| 19897 return(0); | |
| 19898 | |
| 19899 int ret = 0; | |
| 19900 xmlSchemaParticlePtr cur = curParticle; | |
| 19901 if (curParticle == NULL) { | |
| 19902 return(0); | |
| 19903 } | |
| 19904 if (WXS_PARTICLE_TERM(curParticle) == NULL) { | |
| 19905 /* | |
| 19906 * Just return in this case. A missing "term" of the particle | |
| 19907 * might arise due to an invalid "term" component. | |
| 19908 */ | |
| 19909 return(0); | |
| 19910 } | |
| 19911 while (cur != NULL) { | |
| 19912 switch (WXS_PARTICLE_TERM(cur)->type) { | |
| 19913 case XML_SCHEMA_TYPE_ANY: | |
| 19914 break; | |
| 19915 case XML_SCHEMA_TYPE_ELEMENT: | |
| 19916 if (search == 0) { | |
| 19917 ret = xmlSchemaCheckElementDeclConsistent(pctxt, | |
| 19918 ctxtComponent, ctxtParticle, cur, ctxtParticle, 1); | |
| 19919 if (ret != 0) | |
| 19920 return(ret); | |
| 19921 } else { | |
| 19922 xmlSchemaElementPtr elem = | |
| 19923 WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur)); | |
| 19924 /* | |
| 19925 * SPEC Element Declarations Consistent: | |
| 19926 * "If the {particles} contains, either directly, | |
| 19927 * indirectly (that is, within the {particles} of a | |
| 19928 * contained model group, recursively) or `implicitly` | |
| 19929 * two or more element declaration particles with | |
| 19930 * the same {name} and {target namespace}, then | |
| 19931 * all their type definitions must be the same | |
| 19932 * top-level definition [...]" | |
| 19933 */ | |
| 19934 if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name, | |
| 19935 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) && | |
| 19936 xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamesp
ace, | |
| 19937 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNam
espace)) | |
| 19938 { | |
| 19939 xmlChar *strA = NULL, *strB = NULL; | |
| 19940 | |
| 19941 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 19942 /* TODO: error code */ | |
| 19943 XML_SCHEMAP_COS_NONAMBIG, | |
| 19944 WXS_ITEM_NODE(cur), NULL, | |
| 19945 "In the content model of %s, there are multiple " | |
| 19946 "element declarations for '%s' with different " | |
| 19947 "type definitions", | |
| 19948 xmlSchemaGetComponentDesignation(&strA, | |
| 19949 ctxtComponent), | |
| 19950 xmlSchemaFormatQName(&strB, | |
| 19951 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace, | |
| 19952 WXS_PARTICLE_TERM_AS_ELEM(cur)->name)); | |
| 19953 FREE_AND_NULL(strA); | |
| 19954 FREE_AND_NULL(strB); | |
| 19955 return(XML_SCHEMAP_COS_NONAMBIG); | |
| 19956 } | |
| 19957 } | |
| 19958 break; | |
| 19959 case XML_SCHEMA_TYPE_SEQUENCE: { | |
| 19960 break; | |
| 19961 } | |
| 19962 case XML_SCHEMA_TYPE_CHOICE:{ | |
| 19963 /* | |
| 19964 xmlSchemaTreeItemPtr sub; | |
| 19965 | |
| 19966 sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticle
Ptr) | |
| 19967 while (sub != NULL) { | |
| 19968 ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtCompone
nt, | |
| 19969 ctxtParticle, ctxtElem); | |
| 19970 if (ret != 0) | |
| 19971 return(ret); | |
| 19972 sub = sub->next; | |
| 19973 } | |
| 19974 */ | |
| 19975 break; | |
| 19976 } | |
| 19977 case XML_SCHEMA_TYPE_ALL: | |
| 19978 break; | |
| 19979 case XML_SCHEMA_TYPE_GROUP: | |
| 19980 break; | |
| 19981 default: | |
| 19982 xmlSchemaInternalErr2(ACTXT_CAST pctxt, | |
| 19983 "xmlSchemaCheckElementDeclConsistent", | |
| 19984 "found unexpected term of type '%s' in content model", | |
| 19985 WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL); | |
| 19986 return(-1); | |
| 19987 } | |
| 19988 cur = (xmlSchemaParticlePtr) cur->next; | |
| 19989 } | |
| 19990 | |
| 19991 exit: | |
| 19992 return(ret); | |
| 19993 } | |
| 19994 #endif | |
| 19995 | |
| 19996 /** | |
| 19997 * xmlSchemaCheckElementDeclComponent | |
| 19998 * @item: an schema element declaration/particle | |
| 19999 * @ctxt: a schema parser context | |
| 20000 * @name: the name of the attribute | |
| 20001 * | |
| 20002 * Validates the value constraints of an element declaration. | |
| 20003 * Adds substitution group members. | |
| 20004 */ | |
| 20005 static void | |
| 20006 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl, | |
| 20007 xmlSchemaParserCtxtPtr ctxt) | |
| 20008 { | |
| 20009 if (elemDecl == NULL) | |
| 20010 return; | |
| 20011 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) | |
| 20012 return; | |
| 20013 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED; | |
| 20014 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) { | |
| 20015 /* | |
| 20016 * Adds substitution group members. | |
| 20017 */ | |
| 20018 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl); | |
| 20019 } | |
| 20020 } | |
| 20021 | |
| 20022 /** | |
| 20023 * xmlSchemaResolveModelGroupParticleReferences: | |
| 20024 * @particle: a particle component | |
| 20025 * @ctxt: a parser context | |
| 20026 * | |
| 20027 * Resolves references of a model group's {particles} to | |
| 20028 * model group definitions and to element declarations. | |
| 20029 */ | |
| 20030 static void | |
| 20031 xmlSchemaResolveModelGroupParticleReferences( | |
| 20032 xmlSchemaParserCtxtPtr ctxt, | |
| 20033 xmlSchemaModelGroupPtr mg) | |
| 20034 { | |
| 20035 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg); | |
| 20036 xmlSchemaQNameRefPtr ref; | |
| 20037 xmlSchemaBasicItemPtr refItem; | |
| 20038 | |
| 20039 /* | |
| 20040 * URGENT TODO: Test this. | |
| 20041 */ | |
| 20042 while (particle != NULL) { | |
| 20043 if ((WXS_PARTICLE_TERM(particle) == NULL) || | |
| 20044 ((WXS_PARTICLE_TERM(particle))->type != | |
| 20045 XML_SCHEMA_EXTRA_QNAMEREF)) | |
| 20046 { | |
| 20047 goto next_particle; | |
| 20048 } | |
| 20049 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle); | |
| 20050 /* | |
| 20051 * Resolve the reference. | |
| 20052 * NULL the {term} by default. | |
| 20053 */ | |
| 20054 particle->children = NULL; | |
| 20055 | |
| 20056 refItem = xmlSchemaGetNamedComponent(ctxt->schema, | |
| 20057 ref->itemType, ref->name, ref->targetNamespace); | |
| 20058 if (refItem == NULL) { | |
| 20059 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE, | |
| 20060 NULL, WXS_ITEM_NODE(particle), "ref", ref->name, | |
| 20061 ref->targetNamespace, ref->itemType, NULL); | |
| 20062 /* TODO: remove the particle. */ | |
| 20063 goto next_particle; | |
| 20064 } | |
| 20065 if (refItem->type == XML_SCHEMA_TYPE_GROUP) { | |
| 20066 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL) | |
| 20067 /* TODO: remove the particle. */ | |
| 20068 goto next_particle; | |
| 20069 /* | |
| 20070 * NOTE that we will assign the model group definition | |
| 20071 * itself to the "term" of the particle. This will ease | |
| 20072 * the check for circular model group definitions. After | |
| 20073 * that the "term" will be assigned the model group of the | |
| 20074 * model group definition. | |
| 20075 */ | |
| 20076 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type == | |
| 20077 XML_SCHEMA_TYPE_ALL) { | |
| 20078 /* | |
| 20079 * SPEC cos-all-limited (1) | |
| 20080 * SPEC cos-all-limited (1.2) | |
| 20081 * "It appears only as the value of one or both of the | |
| 20082 * following properties:" | |
| 20083 * (1.1) "the {model group} property of a model group | |
| 20084 * definition." | |
| 20085 * (1.2) "the {term} property of a particle [... of] the " | |
| 20086 * {content type} of a complex type definition." | |
| 20087 */ | |
| 20088 xmlSchemaCustomErr(ACTXT_CAST ctxt, | |
| 20089 /* TODO: error code */ | |
| 20090 XML_SCHEMAP_COS_ALL_LIMITED, | |
| 20091 WXS_ITEM_NODE(particle), NULL, | |
| 20092 "A model group definition is referenced, but " | |
| 20093 "it contains an 'all' model group, which " | |
| 20094 "cannot be contained by model groups", | |
| 20095 NULL, NULL); | |
| 20096 /* TODO: remove the particle. */ | |
| 20097 goto next_particle; | |
| 20098 } | |
| 20099 particle->children = (xmlSchemaTreeItemPtr) refItem; | |
| 20100 } else { | |
| 20101 /* | |
| 20102 * TODO: Are referenced element declarations the only | |
| 20103 * other components we expect here? | |
| 20104 */ | |
| 20105 particle->children = (xmlSchemaTreeItemPtr) refItem; | |
| 20106 } | |
| 20107 next_particle: | |
| 20108 particle = WXS_PTC_CAST particle->next; | |
| 20109 } | |
| 20110 } | |
| 20111 | |
| 20112 static int | |
| 20113 xmlSchemaAreValuesEqual(xmlSchemaValPtr x, | |
| 20114 xmlSchemaValPtr y) | |
| 20115 { | |
| 20116 xmlSchemaTypePtr tx, ty, ptx, pty; | |
| 20117 int ret; | |
| 20118 | |
| 20119 while (x != NULL) { | |
| 20120 /* Same types. */ | |
| 20121 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x)); | |
| 20122 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y)); | |
| 20123 ptx = xmlSchemaGetPrimitiveType(tx); | |
| 20124 pty = xmlSchemaGetPrimitiveType(ty); | |
| 20125 /* | |
| 20126 * (1) if a datatype T' is `derived` by `restriction` from an | |
| 20127 * atomic datatype T then the `value space` of T' is a subset of | |
| 20128 * the `value space` of T. */ | |
| 20129 /* | |
| 20130 * (2) if datatypes T' and T'' are `derived` by `restriction` | |
| 20131 * from a common atomic ancestor T then the `value space`s of T' | |
| 20132 * and T'' may overlap. | |
| 20133 */ | |
| 20134 if (ptx != pty) | |
| 20135 return(0); | |
| 20136 /* | |
| 20137 * We assume computed values to be normalized, so do a fast | |
| 20138 * string comparison for string based types. | |
| 20139 */ | |
| 20140 if ((ptx->builtInType == XML_SCHEMAS_STRING) || | |
| 20141 WXS_IS_ANY_SIMPLE_TYPE(ptx)) { | |
| 20142 if (! xmlStrEqual( | |
| 20143 xmlSchemaValueGetAsString(x), | |
| 20144 xmlSchemaValueGetAsString(y))) | |
| 20145 return (0); | |
| 20146 } else { | |
| 20147 ret = xmlSchemaCompareValuesWhtsp( | |
| 20148 x, XML_SCHEMA_WHITESPACE_PRESERVE, | |
| 20149 y, XML_SCHEMA_WHITESPACE_PRESERVE); | |
| 20150 if (ret == -2) | |
| 20151 return(-1); | |
| 20152 if (ret != 0) | |
| 20153 return(0); | |
| 20154 } | |
| 20155 /* | |
| 20156 * Lists. | |
| 20157 */ | |
| 20158 x = xmlSchemaValueGetNext(x); | |
| 20159 if (x != NULL) { | |
| 20160 y = xmlSchemaValueGetNext(y); | |
| 20161 if (y == NULL) | |
| 20162 return (0); | |
| 20163 } else if (xmlSchemaValueGetNext(y) != NULL) | |
| 20164 return (0); | |
| 20165 else | |
| 20166 return (1); | |
| 20167 } | |
| 20168 return (0); | |
| 20169 } | |
| 20170 | |
| 20171 /** | |
| 20172 * xmlSchemaResolveAttrUseReferences: | |
| 20173 * @item: an attribute use | |
| 20174 * @ctxt: a parser context | |
| 20175 * | |
| 20176 * Resolves the referenced attribute declaration. | |
| 20177 */ | |
| 20178 static int | |
| 20179 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause, | |
| 20180 xmlSchemaParserCtxtPtr ctxt) | |
| 20181 { | |
| 20182 if ((ctxt == NULL) || (ause == NULL)) | |
| 20183 return(-1); | |
| 20184 if ((ause->attrDecl == NULL) || | |
| 20185 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF)) | |
| 20186 return(0); | |
| 20187 | |
| 20188 { | |
| 20189 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl; | |
| 20190 | |
| 20191 /* | |
| 20192 * TODO: Evaluate, what errors could occur if the declaration is not | |
| 20193 * found. | |
| 20194 */ | |
| 20195 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema, | |
| 20196 ref->name, ref->targetNamespace); | |
| 20197 if (ause->attrDecl == NULL) { | |
| 20198 xmlSchemaPResCompAttrErr(ctxt, | |
| 20199 XML_SCHEMAP_SRC_RESOLVE, | |
| 20200 WXS_BASIC_CAST ause, ause->node, | |
| 20201 "ref", ref->name, ref->targetNamespace, | |
| 20202 XML_SCHEMA_TYPE_ATTRIBUTE, NULL); | |
| 20203 return(ctxt->err);; | |
| 20204 } | |
| 20205 } | |
| 20206 return(0); | |
| 20207 } | |
| 20208 | |
| 20209 /** | |
| 20210 * xmlSchemaCheckAttrUsePropsCorrect: | |
| 20211 * @ctxt: a parser context | |
| 20212 * @use: an attribute use | |
| 20213 * | |
| 20214 * Schema Component Constraint: | |
| 20215 * Attribute Use Correct (au-props-correct) | |
| 20216 * | |
| 20217 */ | |
| 20218 static int | |
| 20219 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt, | |
| 20220 xmlSchemaAttributeUsePtr use) | |
| 20221 { | |
| 20222 if ((ctxt == NULL) || (use == NULL)) | |
| 20223 return(-1); | |
| 20224 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) || | |
| 20225 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE)) | |
| 20226 return(0); | |
| 20227 | |
| 20228 /* | |
| 20229 * SPEC au-props-correct (1) | |
| 20230 * "The values of the properties of an attribute use must be as | |
| 20231 * described in the property tableau in The Attribute Use Schema | |
| 20232 * Component ($3.5.1), modulo the impact of Missing | |
| 20233 * Sub-components ($5.3)." | |
| 20234 */ | |
| 20235 | |
| 20236 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) && | |
| 20237 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) && | |
| 20238 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0)) | |
| 20239 { | |
| 20240 xmlSchemaPCustomErr(ctxt, | |
| 20241 XML_SCHEMAP_AU_PROPS_CORRECT_2, | |
| 20242 WXS_BASIC_CAST use, NULL, | |
| 20243 "The attribute declaration has a 'fixed' value constraint " | |
| 20244 ", thus the attribute use must also have a 'fixed' value " | |
| 20245 "constraint", | |
| 20246 NULL); | |
| 20247 return(ctxt->err); | |
| 20248 } | |
| 20249 /* | |
| 20250 * Compute and check the value constraint's value. | |
| 20251 */ | |
| 20252 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) { | |
| 20253 int ret; | |
| 20254 /* | |
| 20255 * TODO: The spec seems to be missing a check of the | |
| 20256 * value constraint of the attribute use. We will do it here. | |
| 20257 */ | |
| 20258 /* | |
| 20259 * SPEC a-props-correct (3) | |
| 20260 */ | |
| 20261 if (xmlSchemaIsDerivedFromBuiltInType( | |
| 20262 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID)) | |
| 20263 { | |
| 20264 xmlSchemaCustomErr(ACTXT_CAST ctxt, | |
| 20265 XML_SCHEMAP_AU_PROPS_CORRECT, | |
| 20266 NULL, WXS_BASIC_CAST use, | |
| 20267 "Value constraints are not allowed if the type definition " | |
| 20268 "is or is derived from xs:ID", | |
| 20269 NULL, NULL); | |
| 20270 return(ctxt->err); | |
| 20271 } | |
| 20272 | |
| 20273 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt, | |
| 20274 use->node, WXS_ATTRUSE_TYPEDEF(use), | |
| 20275 use->defValue, &(use->defVal), | |
| 20276 1, 1, 0); | |
| 20277 if (ret != 0) { | |
| 20278 if (ret < 0) { | |
| 20279 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect", | |
| 20280 "calling xmlSchemaVCheckCVCSimpleType()"); | |
| 20281 return(-1); | |
| 20282 } | |
| 20283 xmlSchemaCustomErr(ACTXT_CAST ctxt, | |
| 20284 XML_SCHEMAP_AU_PROPS_CORRECT, | |
| 20285 NULL, WXS_BASIC_CAST use, | |
| 20286 "The value of the value constraint is not valid", | |
| 20287 NULL, NULL); | |
| 20288 return(ctxt->err); | |
| 20289 } | |
| 20290 } | |
| 20291 /* | |
| 20292 * SPEC au-props-correct (2) | |
| 20293 * "If the {attribute declaration} has a fixed | |
| 20294 * {value constraint}, then if the attribute use itself has a | |
| 20295 * {value constraint}, it must also be fixed and its value must match | |
| 20296 * that of the {attribute declaration}'s {value constraint}." | |
| 20297 */ | |
| 20298 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) && | |
| 20299 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0)) | |
| 20300 { | |
| 20301 if (! xmlSchemaAreValuesEqual(use->defVal, | |
| 20302 (WXS_ATTRUSE_DECL(use))->defVal)) | |
| 20303 { | |
| 20304 xmlSchemaPCustomErr(ctxt, | |
| 20305 XML_SCHEMAP_AU_PROPS_CORRECT_2, | |
| 20306 WXS_BASIC_CAST use, NULL, | |
| 20307 "The 'fixed' value constraint of the attribute use " | |
| 20308 "must match the attribute declaration's value " | |
| 20309 "constraint '%s'", | |
| 20310 (WXS_ATTRUSE_DECL(use))->defValue); | |
| 20311 } | |
| 20312 return(ctxt->err); | |
| 20313 } | |
| 20314 return(0); | |
| 20315 } | |
| 20316 | |
| 20317 | |
| 20318 | |
| 20319 | |
| 20320 /** | |
| 20321 * xmlSchemaResolveAttrTypeReferences: | |
| 20322 * @item: an attribute declaration | |
| 20323 * @ctxt: a parser context | |
| 20324 * | |
| 20325 * Resolves the referenced type definition component. | |
| 20326 */ | |
| 20327 static int | |
| 20328 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item, | |
| 20329 xmlSchemaParserCtxtPtr ctxt) | |
| 20330 { | |
| 20331 /* | |
| 20332 * The simple type definition corresponding to the <simpleType> element | |
| 20333 * information item in the [children], if present, otherwise the simple | |
| 20334 * type definition `resolved` to by the `actual value` of the type | |
| 20335 * [attribute], if present, otherwise the `simple ur-type definition`. | |
| 20336 */ | |
| 20337 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED) | |
| 20338 return(0); | |
| 20339 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED; | |
| 20340 if (item->subtypes != NULL) | |
| 20341 return(0); | |
| 20342 if (item->typeName != NULL) { | |
| 20343 xmlSchemaTypePtr type; | |
| 20344 | |
| 20345 type = xmlSchemaGetType(ctxt->schema, item->typeName, | |
| 20346 item->typeNs); | |
| 20347 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) { | |
| 20348 xmlSchemaPResCompAttrErr(ctxt, | |
| 20349 XML_SCHEMAP_SRC_RESOLVE, | |
| 20350 WXS_BASIC_CAST item, item->node, | |
| 20351 "type", item->typeName, item->typeNs, | |
| 20352 XML_SCHEMA_TYPE_SIMPLE, NULL); | |
| 20353 return(ctxt->err); | |
| 20354 } else | |
| 20355 item->subtypes = type; | |
| 20356 | |
| 20357 } else { | |
| 20358 /* | |
| 20359 * The type defaults to the xs:anySimpleType. | |
| 20360 */ | |
| 20361 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE); | |
| 20362 } | |
| 20363 return(0); | |
| 20364 } | |
| 20365 | |
| 20366 /** | |
| 20367 * xmlSchemaResolveIDCKeyReferences: | |
| 20368 * @idc: the identity-constraint definition | |
| 20369 * @ctxt: the schema parser context | |
| 20370 * @name: the attribute name | |
| 20371 * | |
| 20372 * Resolve keyRef references to key/unique IDCs. | |
| 20373 * Schema Component Constraint: | |
| 20374 * Identity-constraint Definition Properties Correct (c-props-correct) | |
| 20375 */ | |
| 20376 static int | |
| 20377 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc, | |
| 20378 xmlSchemaParserCtxtPtr pctxt) | |
| 20379 { | |
| 20380 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) | |
| 20381 return(0); | |
| 20382 if (idc->ref->name != NULL) { | |
| 20383 idc->ref->item = (xmlSchemaBasicItemPtr) | |
| 20384 xmlSchemaGetIDC(pctxt->schema, idc->ref->name, | |
| 20385 idc->ref->targetNamespace); | |
| 20386 if (idc->ref->item == NULL) { | |
| 20387 /* | |
| 20388 * TODO: It is actually not an error to fail to resolve | |
| 20389 * at this stage. BUT we need to be that strict! | |
| 20390 */ | |
| 20391 xmlSchemaPResCompAttrErr(pctxt, | |
| 20392 XML_SCHEMAP_SRC_RESOLVE, | |
| 20393 WXS_BASIC_CAST idc, idc->node, | |
| 20394 "refer", idc->ref->name, | |
| 20395 idc->ref->targetNamespace, | |
| 20396 XML_SCHEMA_TYPE_IDC_KEY, NULL); | |
| 20397 return(pctxt->err); | |
| 20398 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) { | |
| 20399 /* | |
| 20400 * SPEC c-props-correct (1) | |
| 20401 */ | |
| 20402 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 20403 XML_SCHEMAP_C_PROPS_CORRECT, | |
| 20404 NULL, WXS_BASIC_CAST idc, | |
| 20405 "The keyref references a keyref", | |
| 20406 NULL, NULL); | |
| 20407 idc->ref->item = NULL; | |
| 20408 return(pctxt->err); | |
| 20409 } else { | |
| 20410 if (idc->nbFields != | |
| 20411 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) { | |
| 20412 xmlChar *str = NULL; | |
| 20413 xmlSchemaIDCPtr refer; | |
| 20414 | |
| 20415 refer = (xmlSchemaIDCPtr) idc->ref->item; | |
| 20416 /* | |
| 20417 * SPEC c-props-correct(2) | |
| 20418 * "If the {identity-constraint category} is keyref, | |
| 20419 * the cardinality of the {fields} must equal that of | |
| 20420 * the {fields} of the {referenced key}. | |
| 20421 */ | |
| 20422 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 20423 XML_SCHEMAP_C_PROPS_CORRECT, | |
| 20424 NULL, WXS_BASIC_CAST idc, | |
| 20425 "The cardinality of the keyref differs from the " | |
| 20426 "cardinality of the referenced key/unique '%s'", | |
| 20427 xmlSchemaFormatQName(&str, refer->targetNamespace, | |
| 20428 refer->name), | |
| 20429 NULL); | |
| 20430 FREE_AND_NULL(str) | |
| 20431 return(pctxt->err); | |
| 20432 } | |
| 20433 } | |
| 20434 } | |
| 20435 return(0); | |
| 20436 } | |
| 20437 | |
| 20438 static int | |
| 20439 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib, | |
| 20440 xmlSchemaParserCtxtPtr pctxt) | |
| 20441 { | |
| 20442 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name, | |
| 20443 prohib->targetNamespace) == NULL) { | |
| 20444 | |
| 20445 xmlSchemaPResCompAttrErr(pctxt, | |
| 20446 XML_SCHEMAP_SRC_RESOLVE, | |
| 20447 NULL, prohib->node, | |
| 20448 "ref", prohib->name, prohib->targetNamespace, | |
| 20449 XML_SCHEMA_TYPE_ATTRIBUTE, NULL); | |
| 20450 return(XML_SCHEMAP_SRC_RESOLVE); | |
| 20451 } | |
| 20452 return(0); | |
| 20453 } | |
| 20454 | |
| 20455 #define WXS_REDEFINED_TYPE(c) \ | |
| 20456 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED) | |
| 20457 | |
| 20458 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \ | |
| 20459 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINE
D) | |
| 20460 | |
| 20461 #define WXS_REDEFINED_ATTR_GROUP(c) \ | |
| 20462 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED) | |
| 20463 | |
| 20464 static int | |
| 20465 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt) | |
| 20466 { | |
| 20467 int err = 0; | |
| 20468 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs; | |
| 20469 xmlSchemaBasicItemPtr prev, item; | |
| 20470 int wasRedefined; | |
| 20471 | |
| 20472 if (redef == NULL) | |
| 20473 return(0); | |
| 20474 | |
| 20475 do { | |
| 20476 item = redef->item; | |
| 20477 /* | |
| 20478 * First try to locate the redefined component in the | |
| 20479 * schema graph starting with the redefined schema. | |
| 20480 * NOTE: According to this schema bug entry: | |
| 20481 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctD
ec/0019.html | |
| 20482 * it's not clear if the referenced component needs to originate | |
| 20483 * from the <redefine>d schema _document_ or the schema; the latter | |
| 20484 * would include all imported and included sub-schemas of the | |
| 20485 * <redefine>d schema. Currenlty we latter approach is used. | |
| 20486 * SUPPLEMENT: It seems that the WG moves towards the latter | |
| 20487 * approach, so we are doing it right. | |
| 20488 * | |
| 20489 */ | |
| 20490 prev = xmlSchemaFindRedefCompInGraph( | |
| 20491 redef->targetBucket, item->type, | |
| 20492 redef->refName, redef->refTargetNs); | |
| 20493 if (prev == NULL) { | |
| 20494 xmlChar *str = NULL; | |
| 20495 xmlNodePtr node; | |
| 20496 | |
| 20497 /* | |
| 20498 * SPEC src-redefine: | |
| 20499 * (6.2.1) "The `actual value` of its own name attribute plus | |
| 20500 * target namespace must successfully `resolve` to a model | |
| 20501 * group definition in I." | |
| 20502 * (7.2.1) "The `actual value` of its own name attribute plus | |
| 20503 * target namespace must successfully `resolve` to an attribute | |
| 20504 * group definition in I." | |
| 20505 | |
| 20506 * | |
| 20507 * Note that, if we are redefining with the use of references | |
| 20508 * to components, the spec assumes the src-resolve to be used; | |
| 20509 * but this won't assure that we search only *inside* the | |
| 20510 * redefined schema. | |
| 20511 */ | |
| 20512 if (redef->reference) | |
| 20513 node = WXS_ITEM_NODE(redef->reference); | |
| 20514 else | |
| 20515 node = WXS_ITEM_NODE(item); | |
| 20516 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 20517 /* | |
| 20518 * TODO: error code. | |
| 20519 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the | |
| 20520 * reference kind. | |
| 20521 */ | |
| 20522 XML_SCHEMAP_SRC_REDEFINE, node, NULL, | |
| 20523 "The %s '%s' to be redefined could not be found in " | |
| 20524 "the redefined schema", | |
| 20525 WXS_ITEM_TYPE_NAME(item), | |
| 20526 xmlSchemaFormatQName(&str, redef->refTargetNs, | |
| 20527 redef->refName)); | |
| 20528 FREE_AND_NULL(str); | |
| 20529 err = pctxt->err; | |
| 20530 redef = redef->next; | |
| 20531 continue; | |
| 20532 } | |
| 20533 /* | |
| 20534 * TODO: Obtaining and setting the redefinition state is really | |
| 20535 * clumsy. | |
| 20536 */ | |
| 20537 wasRedefined = 0; | |
| 20538 switch (item->type) { | |
| 20539 case XML_SCHEMA_TYPE_COMPLEX: | |
| 20540 case XML_SCHEMA_TYPE_SIMPLE: | |
| 20541 if ((WXS_TYPE_CAST prev)->flags & | |
| 20542 XML_SCHEMAS_TYPE_REDEFINED) | |
| 20543 { | |
| 20544 wasRedefined = 1; | |
| 20545 break; | |
| 20546 } | |
| 20547 /* Mark it as redefined. */ | |
| 20548 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED; | |
| 20549 /* | |
| 20550 * Assign the redefined type to the | |
| 20551 * base type of the redefining type. | |
| 20552 * TODO: How | |
| 20553 */ | |
| 20554 ((xmlSchemaTypePtr) item)->baseType = | |
| 20555 (xmlSchemaTypePtr) prev; | |
| 20556 break; | |
| 20557 case XML_SCHEMA_TYPE_GROUP: | |
| 20558 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags & | |
| 20559 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED) | |
| 20560 { | |
| 20561 wasRedefined = 1; | |
| 20562 break; | |
| 20563 } | |
| 20564 /* Mark it as redefined. */ | |
| 20565 (WXS_MODEL_GROUPDEF_CAST prev)->flags |= | |
| 20566 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED; | |
| 20567 if (redef->reference != NULL) { | |
| 20568 /* | |
| 20569 * Overwrite the QName-reference with the | |
| 20570 * referenced model group def. | |
| 20571 */ | |
| 20572 (WXS_PTC_CAST redef->reference)->children = | |
| 20573 WXS_TREE_CAST prev; | |
| 20574 } | |
| 20575 redef->target = prev; | |
| 20576 break; | |
| 20577 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | |
| 20578 if ((WXS_ATTR_GROUP_CAST prev)->flags & | |
| 20579 XML_SCHEMAS_ATTRGROUP_REDEFINED) | |
| 20580 { | |
| 20581 wasRedefined = 1; | |
| 20582 break; | |
| 20583 } | |
| 20584 (WXS_ATTR_GROUP_CAST prev)->flags |= | |
| 20585 XML_SCHEMAS_ATTRGROUP_REDEFINED; | |
| 20586 if (redef->reference != NULL) { | |
| 20587 /* | |
| 20588 * Assign the redefined attribute group to the | |
| 20589 * QName-reference component. | |
| 20590 * This is the easy case, since we will just | |
| 20591 * expand the redefined group. | |
| 20592 */ | |
| 20593 (WXS_QNAME_CAST redef->reference)->item = prev; | |
| 20594 redef->target = NULL; | |
| 20595 } else { | |
| 20596 /* | |
| 20597 * This is the complicated case: we need | |
| 20598 * to apply src-redefine (7.2.2) at a later | |
| 20599 * stage, i.e. when attribute group references | |
| 20600 * have beed expanded and simple types have | |
| 20601 * beed fixed. | |
| 20602 */ | |
| 20603 redef->target = prev; | |
| 20604 } | |
| 20605 break; | |
| 20606 default: | |
| 20607 PERROR_INT("xmlSchemaResolveRedefReferences", | |
| 20608 "Unexpected redefined component type"); | |
| 20609 return(-1); | |
| 20610 } | |
| 20611 if (wasRedefined) { | |
| 20612 xmlChar *str = NULL; | |
| 20613 xmlNodePtr node; | |
| 20614 | |
| 20615 if (redef->reference) | |
| 20616 node = WXS_ITEM_NODE(redef->reference); | |
| 20617 else | |
| 20618 node = WXS_ITEM_NODE(redef->item); | |
| 20619 | |
| 20620 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 20621 /* TODO: error code. */ | |
| 20622 XML_SCHEMAP_SRC_REDEFINE, | |
| 20623 node, NULL, | |
| 20624 "The referenced %s was already redefined. Multiple " | |
| 20625 "redefinition of the same component is not supported", | |
| 20626 xmlSchemaGetComponentDesignation(&str, prev), | |
| 20627 NULL); | |
| 20628 FREE_AND_NULL(str) | |
| 20629 err = pctxt->err; | |
| 20630 redef = redef->next; | |
| 20631 continue; | |
| 20632 } | |
| 20633 redef = redef->next; | |
| 20634 } while (redef != NULL); | |
| 20635 | |
| 20636 return(err); | |
| 20637 } | |
| 20638 | |
| 20639 static int | |
| 20640 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt) | |
| 20641 { | |
| 20642 int err = 0; | |
| 20643 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs; | |
| 20644 xmlSchemaBasicItemPtr item; | |
| 20645 | |
| 20646 if (redef == NULL) | |
| 20647 return(0); | |
| 20648 | |
| 20649 do { | |
| 20650 if (redef->target == NULL) { | |
| 20651 redef = redef->next; | |
| 20652 continue; | |
| 20653 } | |
| 20654 item = redef->item; | |
| 20655 | |
| 20656 switch (item->type) { | |
| 20657 case XML_SCHEMA_TYPE_SIMPLE: | |
| 20658 case XML_SCHEMA_TYPE_COMPLEX: | |
| 20659 /* | |
| 20660 * Since the spec wants the {name} of the redefined | |
| 20661 * type to be 'absent', we'll NULL it. | |
| 20662 */ | |
| 20663 (WXS_TYPE_CAST redef->target)->name = NULL; | |
| 20664 | |
| 20665 /* | |
| 20666 * TODO: Seems like there's nothing more to do. The normal | |
| 20667 * inheritance mechanism is used. But not 100% sure. | |
| 20668 */ | |
| 20669 break; | |
| 20670 case XML_SCHEMA_TYPE_GROUP: | |
| 20671 /* | |
| 20672 * URGENT TODO: | |
| 20673 * SPEC src-redefine: | |
| 20674 * (6.2.2) "The {model group} of the model group definition | |
| 20675 * which corresponds to it per XML Representation of Model | |
| 20676 * Group Definition Schema Components ($3.7.2) must be a | |
| 20677 * `valid restriction` of the {model group} of that model | |
| 20678 * group definition in I, as defined in Particle Valid | |
| 20679 * (Restriction) ($3.9.6)." | |
| 20680 */ | |
| 20681 break; | |
| 20682 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | |
| 20683 /* | |
| 20684 * SPEC src-redefine: | |
| 20685 * (7.2.2) "The {attribute uses} and {attribute wildcard} of | |
| 20686 * the attribute group definition which corresponds to it | |
| 20687 * per XML Representation of Attribute Group Definition Schema | |
| 20688 * Components ($3.6.2) must be `valid restrictions` of the | |
| 20689 * {attribute uses} and {attribute wildcard} of that attribute | |
| 20690 * group definition in I, as defined in clause 2, clause 3 and | |
| 20691 * clause 4 of Derivation Valid (Restriction, Complex) | |
| 20692 * ($3.4.6) (where references to the base type definition are | |
| 20693 * understood as references to the attribute group definition | |
| 20694 * in I)." | |
| 20695 */ | |
| 20696 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt, | |
| 20697 XML_SCHEMA_ACTION_REDEFINE, | |
| 20698 item, redef->target, | |
| 20699 (WXS_ATTR_GROUP_CAST item)->attrUses, | |
| 20700 (WXS_ATTR_GROUP_CAST redef->target)->attrUses, | |
| 20701 (WXS_ATTR_GROUP_CAST item)->attributeWildcard, | |
| 20702 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard); | |
| 20703 if (err == -1) | |
| 20704 return(-1); | |
| 20705 break; | |
| 20706 default: | |
| 20707 break; | |
| 20708 } | |
| 20709 redef = redef->next; | |
| 20710 } while (redef != NULL); | |
| 20711 return(0); | |
| 20712 } | |
| 20713 | |
| 20714 | |
| 20715 static int | |
| 20716 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt, | |
| 20717 xmlSchemaBucketPtr bucket) | |
| 20718 { | |
| 20719 xmlSchemaBasicItemPtr item; | |
| 20720 int err; | |
| 20721 xmlHashTablePtr *table; | |
| 20722 const xmlChar *name; | |
| 20723 int i; | |
| 20724 | |
| 20725 #define WXS_GET_GLOBAL_HASH(c, slot) { \ | |
| 20726 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \ | |
| 20727 table = &(WXS_IMPBUCKET((c))->schema->slot); \ | |
| 20728 else \ | |
| 20729 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); } | |
| 20730 | |
| 20731 /* | |
| 20732 * Add global components to the schema's hash tables. | |
| 20733 * This is the place where duplicate components will be | |
| 20734 * detected. | |
| 20735 * TODO: I think normally we should support imports of the | |
| 20736 * same namespace from multiple locations. We don't do currently, | |
| 20737 * but if we do then according to: | |
| 20738 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224 | |
| 20739 * we would need, if imported directly, to import redefined | |
| 20740 * components as well to be able to catch clashing components. | |
| 20741 * (I hope I'll still know what this means after some months :-() | |
| 20742 */ | |
| 20743 if (bucket == NULL) | |
| 20744 return(-1); | |
| 20745 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) | |
| 20746 return(0); | |
| 20747 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED; | |
| 20748 | |
| 20749 for (i = 0; i < bucket->globals->nbItems; i++) { | |
| 20750 item = bucket->globals->items[i]; | |
| 20751 table = NULL; | |
| 20752 switch (item->type) { | |
| 20753 case XML_SCHEMA_TYPE_COMPLEX: | |
| 20754 case XML_SCHEMA_TYPE_SIMPLE: | |
| 20755 if (WXS_REDEFINED_TYPE(item)) | |
| 20756 continue; | |
| 20757 name = (WXS_TYPE_CAST item)->name; | |
| 20758 WXS_GET_GLOBAL_HASH(bucket, typeDecl) | |
| 20759 break; | |
| 20760 case XML_SCHEMA_TYPE_ELEMENT: | |
| 20761 name = (WXS_ELEM_CAST item)->name; | |
| 20762 WXS_GET_GLOBAL_HASH(bucket, elemDecl) | |
| 20763 break; | |
| 20764 case XML_SCHEMA_TYPE_ATTRIBUTE: | |
| 20765 name = (WXS_ATTR_CAST item)->name; | |
| 20766 WXS_GET_GLOBAL_HASH(bucket, attrDecl) | |
| 20767 break; | |
| 20768 case XML_SCHEMA_TYPE_GROUP: | |
| 20769 if (WXS_REDEFINED_MODEL_GROUP_DEF(item)) | |
| 20770 continue; | |
| 20771 name = (WXS_MODEL_GROUPDEF_CAST item)->name; | |
| 20772 WXS_GET_GLOBAL_HASH(bucket, groupDecl) | |
| 20773 break; | |
| 20774 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | |
| 20775 if (WXS_REDEFINED_ATTR_GROUP(item)) | |
| 20776 continue; | |
| 20777 name = (WXS_ATTR_GROUP_CAST item)->name; | |
| 20778 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl) | |
| 20779 break; | |
| 20780 case XML_SCHEMA_TYPE_IDC_KEY: | |
| 20781 case XML_SCHEMA_TYPE_IDC_UNIQUE: | |
| 20782 case XML_SCHEMA_TYPE_IDC_KEYREF: | |
| 20783 name = (WXS_IDC_CAST item)->name; | |
| 20784 WXS_GET_GLOBAL_HASH(bucket, idcDef) | |
| 20785 break; | |
| 20786 case XML_SCHEMA_TYPE_NOTATION: | |
| 20787 name = ((xmlSchemaNotationPtr) item)->name; | |
| 20788 WXS_GET_GLOBAL_HASH(bucket, notaDecl) | |
| 20789 break; | |
| 20790 default: | |
| 20791 PERROR_INT("xmlSchemaAddComponents", | |
| 20792 "Unexpected global component type"); | |
| 20793 continue; | |
| 20794 } | |
| 20795 if (*table == NULL) { | |
| 20796 *table = xmlHashCreateDict(10, pctxt->dict); | |
| 20797 if (*table == NULL) { | |
| 20798 PERROR_INT("xmlSchemaAddComponents", | |
| 20799 "failed to create a component hash table"); | |
| 20800 return(-1); | |
| 20801 } | |
| 20802 } | |
| 20803 err = xmlHashAddEntry(*table, name, item); | |
| 20804 if (err != 0) { | |
| 20805 xmlChar *str = NULL; | |
| 20806 | |
| 20807 xmlSchemaCustomErr(ACTXT_CAST pctxt, | |
| 20808 XML_SCHEMAP_REDEFINED_TYPE, | |
| 20809 WXS_ITEM_NODE(item), | |
| 20810 WXS_BASIC_CAST item, | |
| 20811 "A global %s '%s' does already exist", | |
| 20812 WXS_ITEM_TYPE_NAME(item), | |
| 20813 xmlSchemaGetComponentQName(&str, item)); | |
| 20814 FREE_AND_NULL(str); | |
| 20815 } | |
| 20816 } | |
| 20817 /* | |
| 20818 * Process imported/included schemas. | |
| 20819 */ | |
| 20820 if (bucket->relations != NULL) { | |
| 20821 xmlSchemaSchemaRelationPtr rel = bucket->relations; | |
| 20822 do { | |
| 20823 if ((rel->bucket != NULL) && | |
| 20824 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) { | |
| 20825 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1) | |
| 20826 return(-1); | |
| 20827 } | |
| 20828 rel = rel->next; | |
| 20829 } while (rel != NULL); | |
| 20830 } | |
| 20831 return(0); | |
| 20832 } | |
| 20833 | |
| 20834 static int | |
| 20835 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt, | |
| 20836 xmlSchemaBucketPtr rootBucket) | |
| 20837 { | |
| 20838 xmlSchemaConstructionCtxtPtr con = pctxt->constructor; | |
| 20839 xmlSchemaTreeItemPtr item, *items; | |
| 20840 int nbItems, i, ret = 0; | |
| 20841 xmlSchemaBucketPtr oldbucket = con->bucket; | |
| 20842 xmlSchemaElementPtr elemDecl; | |
| 20843 | |
| 20844 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure; | |
| 20845 | |
| 20846 if ((con->pending == NULL) || | |
| 20847 (con->pending->nbItems == 0)) | |
| 20848 return(0); | |
| 20849 | |
| 20850 /* | |
| 20851 * Since xmlSchemaFixupComplexType() will create new particles | |
| 20852 * (local components), and those particle components need a bucket | |
| 20853 * on the constructor, we'll assure here that the constructor has | |
| 20854 * a bucket. | |
| 20855 * TODO: Think about storing locals _only_ on the main bucket. | |
| 20856 */ | |
| 20857 if (con->bucket == NULL) | |
| 20858 con->bucket = rootBucket; | |
| 20859 | |
| 20860 /* TODO: | |
| 20861 * SPEC (src-redefine): | |
| 20862 * (6.2) "If it has no such self-reference, then all of the | |
| 20863 * following must be true:" | |
| 20864 | |
| 20865 * (6.2.2) The {model group} of the model group definition which | |
| 20866 * corresponds to it per XML Representation of Model Group | |
| 20867 * Definition Schema Components ($3.7.2) must be a `valid | |
| 20868 * restriction` of the {model group} of that model group definition | |
| 20869 * in I, as defined in Particle Valid (Restriction) ($3.9.6)." | |
| 20870 */ | |
| 20871 xmlSchemaCheckSRCRedefineFirst(pctxt); | |
| 20872 | |
| 20873 /* | |
| 20874 * Add global components to the schemata's hash tables. | |
| 20875 */ | |
| 20876 xmlSchemaAddComponents(pctxt, rootBucket); | |
| 20877 | |
| 20878 pctxt->ctxtType = NULL; | |
| 20879 items = (xmlSchemaTreeItemPtr *) con->pending->items; | |
| 20880 nbItems = con->pending->nbItems; | |
| 20881 /* | |
| 20882 * Now that we have parsed *all* the schema document(s) and converted | |
| 20883 * them to schema components, we can resolve references, apply component | |
| 20884 * constraints, create the FSA from the content model, etc. | |
| 20885 */ | |
| 20886 /* | |
| 20887 * Resolve references of.. | |
| 20888 * | |
| 20889 * 1. element declarations: | |
| 20890 * - the type definition | |
| 20891 * - the substitution group affiliation | |
| 20892 * 2. simple/complex types: | |
| 20893 * - the base type definition | |
| 20894 * - the memberTypes of union types | |
| 20895 * - the itemType of list types | |
| 20896 * 3. attributes declarations and attribute uses: | |
| 20897 * - the type definition | |
| 20898 * - if an attribute use, then the attribute declaration | |
| 20899 * 4. attribute group references: | |
| 20900 * - the attribute group definition | |
| 20901 * 5. particles: | |
| 20902 * - the term of the particle (e.g. a model group) | |
| 20903 * 6. IDC key-references: | |
| 20904 * - the referenced IDC 'key' or 'unique' definition | |
| 20905 * 7. Attribute prohibitions which had a "ref" attribute. | |
| 20906 */ | |
| 20907 for (i = 0; i < nbItems; i++) { | |
| 20908 item = items[i]; | |
| 20909 switch (item->type) { | |
| 20910 case XML_SCHEMA_TYPE_ELEMENT: | |
| 20911 xmlSchemaResolveElementReferences( | |
| 20912 (xmlSchemaElementPtr) item, pctxt); | |
| 20913 FIXHFAILURE; | |
| 20914 break; | |
| 20915 case XML_SCHEMA_TYPE_COMPLEX: | |
| 20916 case XML_SCHEMA_TYPE_SIMPLE: | |
| 20917 xmlSchemaResolveTypeReferences( | |
| 20918 (xmlSchemaTypePtr) item, pctxt); | |
| 20919 FIXHFAILURE; | |
| 20920 break; | |
| 20921 case XML_SCHEMA_TYPE_ATTRIBUTE: | |
| 20922 xmlSchemaResolveAttrTypeReferences( | |
| 20923 (xmlSchemaAttributePtr) item, pctxt); | |
| 20924 FIXHFAILURE; | |
| 20925 break; | |
| 20926 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: | |
| 20927 xmlSchemaResolveAttrUseReferences( | |
| 20928 (xmlSchemaAttributeUsePtr) item, pctxt); | |
| 20929 FIXHFAILURE; | |
| 20930 break; | |
| 20931 case XML_SCHEMA_EXTRA_QNAMEREF: | |
| 20932 if ((WXS_QNAME_CAST item)->itemType == | |
| 20933 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) | |
| 20934 { | |
| 20935 xmlSchemaResolveAttrGroupReferences( | |
| 20936 WXS_QNAME_CAST item, pctxt); | |
| 20937 } | |
| 20938 FIXHFAILURE; | |
| 20939 break; | |
| 20940 case XML_SCHEMA_TYPE_SEQUENCE: | |
| 20941 case XML_SCHEMA_TYPE_CHOICE: | |
| 20942 case XML_SCHEMA_TYPE_ALL: | |
| 20943 xmlSchemaResolveModelGroupParticleReferences(pctxt, | |
| 20944 WXS_MODEL_GROUP_CAST item); | |
| 20945 FIXHFAILURE; | |
| 20946 break; | |
| 20947 case XML_SCHEMA_TYPE_IDC_KEY: | |
| 20948 case XML_SCHEMA_TYPE_IDC_UNIQUE: | |
| 20949 case XML_SCHEMA_TYPE_IDC_KEYREF: | |
| 20950 xmlSchemaResolveIDCKeyReferences( | |
| 20951 (xmlSchemaIDCPtr) item, pctxt); | |
| 20952 FIXHFAILURE; | |
| 20953 break; | |
| 20954 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB: | |
| 20955 /* | |
| 20956 * Handle attribue prohibition which had a | |
| 20957 * "ref" attribute. | |
| 20958 */ | |
| 20959 xmlSchemaResolveAttrUseProhibReferences( | |
| 20960 WXS_ATTR_PROHIB_CAST item, pctxt); | |
| 20961 FIXHFAILURE; | |
| 20962 break; | |
| 20963 default: | |
| 20964 break; | |
| 20965 } | |
| 20966 } | |
| 20967 if (pctxt->nberrors != 0) | |
| 20968 goto exit_error; | |
| 20969 | |
| 20970 /* | |
| 20971 * Now that all references are resolved we | |
| 20972 * can check for circularity of... | |
| 20973 * 1. the base axis of type definitions | |
| 20974 * 2. nested model group definitions | |
| 20975 * 3. nested attribute group definitions | |
| 20976 * TODO: check for circual substitution groups. | |
| 20977 */ | |
| 20978 for (i = 0; i < nbItems; i++) { | |
| 20979 item = items[i]; | |
| 20980 /* | |
| 20981 * Let's better stop on the first error here. | |
| 20982 */ | |
| 20983 switch (item->type) { | |
| 20984 case XML_SCHEMA_TYPE_COMPLEX: | |
| 20985 case XML_SCHEMA_TYPE_SIMPLE: | |
| 20986 xmlSchemaCheckTypeDefCircular( | |
| 20987 (xmlSchemaTypePtr) item, pctxt); | |
| 20988 FIXHFAILURE; | |
| 20989 if (pctxt->nberrors != 0) | |
| 20990 goto exit_error; | |
| 20991 break; | |
| 20992 case XML_SCHEMA_TYPE_GROUP: | |
| 20993 xmlSchemaCheckGroupDefCircular( | |
| 20994 (xmlSchemaModelGroupDefPtr) item, pctxt); | |
| 20995 FIXHFAILURE; | |
| 20996 if (pctxt->nberrors != 0) | |
| 20997 goto exit_error; | |
| 20998 break; | |
| 20999 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | |
| 21000 xmlSchemaCheckAttrGroupCircular( | |
| 21001 (xmlSchemaAttributeGroupPtr) item, pctxt); | |
| 21002 FIXHFAILURE; | |
| 21003 if (pctxt->nberrors != 0) | |
| 21004 goto exit_error; | |
| 21005 break; | |
| 21006 default: | |
| 21007 break; | |
| 21008 } | |
| 21009 } | |
| 21010 if (pctxt->nberrors != 0) | |
| 21011 goto exit_error; | |
| 21012 /* | |
| 21013 * Model group definition references: | |
| 21014 * Such a reference is reflected by a particle at the component | |
| 21015 * level. Until now the 'term' of such particles pointed | |
| 21016 * to the model group definition; this was done, in order to | |
| 21017 * ease circularity checks. Now we need to set the 'term' of | |
| 21018 * such particles to the model group of the model group definition. | |
| 21019 */ | |
| 21020 for (i = 0; i < nbItems; i++) { | |
| 21021 item = items[i]; | |
| 21022 switch (item->type) { | |
| 21023 case XML_SCHEMA_TYPE_SEQUENCE: | |
| 21024 case XML_SCHEMA_TYPE_CHOICE: | |
| 21025 xmlSchemaModelGroupToModelGroupDefFixup(pctxt, | |
| 21026 WXS_MODEL_GROUP_CAST item); | |
| 21027 break; | |
| 21028 default: | |
| 21029 break; | |
| 21030 } | |
| 21031 } | |
| 21032 if (pctxt->nberrors != 0) | |
| 21033 goto exit_error; | |
| 21034 /* | |
| 21035 * Expand attribute group references of attribute group definitions. | |
| 21036 */ | |
| 21037 for (i = 0; i < nbItems; i++) { | |
| 21038 item = items[i]; | |
| 21039 switch (item->type) { | |
| 21040 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | |
| 21041 if ((! WXS_ATTR_GROUP_EXPANDED(item)) && | |
| 21042 WXS_ATTR_GROUP_HAS_REFS(item)) | |
| 21043 { | |
| 21044 xmlSchemaAttributeGroupExpandRefs(pctxt, | |
| 21045 WXS_ATTR_GROUP_CAST item); | |
| 21046 FIXHFAILURE; | |
| 21047 } | |
| 21048 break; | |
| 21049 default: | |
| 21050 break; | |
| 21051 } | |
| 21052 } | |
| 21053 if (pctxt->nberrors != 0) | |
| 21054 goto exit_error; | |
| 21055 /* | |
| 21056 * First compute the variety of simple types. This is needed as | |
| 21057 * a seperate step, since otherwise we won't be able to detect | |
| 21058 * circular union types in all cases. | |
| 21059 */ | |
| 21060 for (i = 0; i < nbItems; i++) { | |
| 21061 item = items[i]; | |
| 21062 switch (item->type) { | |
| 21063 case XML_SCHEMA_TYPE_SIMPLE: | |
| 21064 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) { | |
| 21065 xmlSchemaFixupSimpleTypeStageOne(pctxt, | |
| 21066 (xmlSchemaTypePtr) item); | |
| 21067 FIXHFAILURE; | |
| 21068 } | |
| 21069 break; | |
| 21070 default: | |
| 21071 break; | |
| 21072 } | |
| 21073 } | |
| 21074 if (pctxt->nberrors != 0) | |
| 21075 goto exit_error; | |
| 21076 /* | |
| 21077 * Detect circular union types. Note that this needs the variety to | |
| 21078 * be already computed. | |
| 21079 */ | |
| 21080 for (i = 0; i < nbItems; i++) { | |
| 21081 item = items[i]; | |
| 21082 switch (item->type) { | |
| 21083 case XML_SCHEMA_TYPE_SIMPLE: | |
| 21084 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) { | |
| 21085 xmlSchemaCheckUnionTypeDefCircular(pctxt, | |
| 21086 (xmlSchemaTypePtr) item); | |
| 21087 FIXHFAILURE; | |
| 21088 } | |
| 21089 break; | |
| 21090 default: | |
| 21091 break; | |
| 21092 } | |
| 21093 } | |
| 21094 if (pctxt->nberrors != 0) | |
| 21095 goto exit_error; | |
| 21096 | |
| 21097 /* | |
| 21098 * Do the complete type fixup for simple types. | |
| 21099 */ | |
| 21100 for (i = 0; i < nbItems; i++) { | |
| 21101 item = items[i]; | |
| 21102 switch (item->type) { | |
| 21103 case XML_SCHEMA_TYPE_SIMPLE: | |
| 21104 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) { | |
| 21105 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item); | |
| 21106 FIXHFAILURE; | |
| 21107 } | |
| 21108 break; | |
| 21109 default: | |
| 21110 break; | |
| 21111 } | |
| 21112 } | |
| 21113 if (pctxt->nberrors != 0) | |
| 21114 goto exit_error; | |
| 21115 /* | |
| 21116 * At this point we need build and check all simple types. | |
| 21117 */ | |
| 21118 /* | |
| 21119 * Apply contraints for attribute declarations. | |
| 21120 */ | |
| 21121 for (i = 0; i < nbItems; i++) { | |
| 21122 item = items[i]; | |
| 21123 switch (item->type) { | |
| 21124 case XML_SCHEMA_TYPE_ATTRIBUTE: | |
| 21125 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item); | |
| 21126 FIXHFAILURE; | |
| 21127 break; | |
| 21128 default: | |
| 21129 break; | |
| 21130 } | |
| 21131 } | |
| 21132 if (pctxt->nberrors != 0) | |
| 21133 goto exit_error; | |
| 21134 /* | |
| 21135 * Apply constraints for attribute uses. | |
| 21136 */ | |
| 21137 for (i = 0; i < nbItems; i++) { | |
| 21138 item = items[i]; | |
| 21139 switch (item->type) { | |
| 21140 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: | |
| 21141 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) { | |
| 21142 xmlSchemaCheckAttrUsePropsCorrect(pctxt, | |
| 21143 WXS_ATTR_USE_CAST item); | |
| 21144 FIXHFAILURE; | |
| 21145 } | |
| 21146 break; | |
| 21147 default: | |
| 21148 break; | |
| 21149 } | |
| 21150 } | |
| 21151 if (pctxt->nberrors != 0) | |
| 21152 goto exit_error; | |
| 21153 | |
| 21154 /* | |
| 21155 * Apply constraints for attribute group definitions. | |
| 21156 */ | |
| 21157 for (i = 0; i < nbItems; i++) { | |
| 21158 item = items[i]; | |
| 21159 switch (item->type) { | |
| 21160 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | |
| 21161 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) && | |
| 21162 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems
> 1)) | |
| 21163 { | |
| 21164 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item); | |
| 21165 FIXHFAILURE; | |
| 21166 } | |
| 21167 break; | |
| 21168 default: | |
| 21169 break; | |
| 21170 } | |
| 21171 } | |
| 21172 if (pctxt->nberrors != 0) | |
| 21173 goto exit_error; | |
| 21174 | |
| 21175 /* | |
| 21176 * Apply constraints for redefinitions. | |
| 21177 */ | |
| 21178 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL) | |
| 21179 xmlSchemaCheckSRCRedefineSecond(pctxt); | |
| 21180 if (pctxt->nberrors != 0) | |
| 21181 goto exit_error; | |
| 21182 | |
| 21183 /* | |
| 21184 * Complex types are builded and checked. | |
| 21185 */ | |
| 21186 for (i = 0; i < nbItems; i++) { | |
| 21187 item = con->pending->items[i]; | |
| 21188 switch (item->type) { | |
| 21189 case XML_SCHEMA_TYPE_COMPLEX: | |
| 21190 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) { | |
| 21191 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item); | |
| 21192 FIXHFAILURE; | |
| 21193 } | |
| 21194 break; | |
| 21195 default: | |
| 21196 break; | |
| 21197 } | |
| 21198 } | |
| 21199 if (pctxt->nberrors != 0) | |
| 21200 goto exit_error; | |
| 21201 | |
| 21202 /* | |
| 21203 * The list could have changed, since xmlSchemaFixupComplexType() | |
| 21204 * will create particles and model groups in some cases. | |
| 21205 */ | |
| 21206 items = (xmlSchemaTreeItemPtr *) con->pending->items; | |
| 21207 nbItems = con->pending->nbItems; | |
| 21208 | |
| 21209 /* | |
| 21210 * Apply some constraints for element declarations. | |
| 21211 */ | |
| 21212 for (i = 0; i < nbItems; i++) { | |
| 21213 item = items[i]; | |
| 21214 switch (item->type) { | |
| 21215 case XML_SCHEMA_TYPE_ELEMENT: | |
| 21216 elemDecl = (xmlSchemaElementPtr) item; | |
| 21217 | |
| 21218 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) | |
| 21219 { | |
| 21220 xmlSchemaCheckElementDeclComponent( | |
| 21221 (xmlSchemaElementPtr) elemDecl, pctxt); | |
| 21222 FIXHFAILURE; | |
| 21223 } | |
| 21224 | |
| 21225 #ifdef WXS_ELEM_DECL_CONS_ENABLED | |
| 21226 /* | |
| 21227 * Schema Component Constraint: Element Declarations Consistent | |
| 21228 * Apply this constraint to local types of element declarations. | |
| 21229 */ | |
| 21230 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) && | |
| 21231 (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) && | |
| 21232 (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl)))) | |
| 21233 { | |
| 21234 xmlSchemaCheckElementDeclConsistent(pctxt, | |
| 21235 WXS_BASIC_CAST elemDecl, | |
| 21236 WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)), | |
| 21237 NULL, NULL, 0); | |
| 21238 } | |
| 21239 #endif | |
| 21240 break; | |
| 21241 default: | |
| 21242 break; | |
| 21243 } | |
| 21244 } | |
| 21245 if (pctxt->nberrors != 0) | |
| 21246 goto exit_error; | |
| 21247 | |
| 21248 /* | |
| 21249 * Finally we can build the automaton from the content model of | |
| 21250 * complex types. | |
| 21251 */ | |
| 21252 | |
| 21253 for (i = 0; i < nbItems; i++) { | |
| 21254 item = items[i]; | |
| 21255 switch (item->type) { | |
| 21256 case XML_SCHEMA_TYPE_COMPLEX: | |
| 21257 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt); | |
| 21258 /* FIXHFAILURE; */ | |
| 21259 break; | |
| 21260 default: | |
| 21261 break; | |
| 21262 } | |
| 21263 } | |
| 21264 if (pctxt->nberrors != 0) | |
| 21265 goto exit_error; | |
| 21266 /* | |
| 21267 * URGENT TODO: cos-element-consistent | |
| 21268 */ | |
| 21269 goto exit; | |
| 21270 | |
| 21271 exit_error: | |
| 21272 ret = pctxt->err; | |
| 21273 goto exit; | |
| 21274 | |
| 21275 exit_failure: | |
| 21276 ret = -1; | |
| 21277 | |
| 21278 exit: | |
| 21279 /* | |
| 21280 * Reset the constructor. This is needed for XSI acquisition, since | |
| 21281 * those items will be processed over and over again for every XSI | |
| 21282 * if not cleared here. | |
| 21283 */ | |
| 21284 con->bucket = oldbucket; | |
| 21285 con->pending->nbItems = 0; | |
| 21286 if (con->substGroups != NULL) { | |
| 21287 xmlHashFree(con->substGroups, | |
| 21288 (xmlHashDeallocator) xmlSchemaSubstGroupFree); | |
| 21289 con->substGroups = NULL; | |
| 21290 } | |
| 21291 if (con->redefs != NULL) { | |
| 21292 xmlSchemaRedefListFree(con->redefs); | |
| 21293 con->redefs = NULL; | |
| 21294 } | |
| 21295 return(ret); | |
| 21296 } | |
| 21297 /** | |
| 21298 * xmlSchemaParse: | |
| 21299 * @ctxt: a schema validation context | |
| 21300 * | |
| 21301 * parse a schema definition resource and build an internal | |
| 21302 * XML Shema struture which can be used to validate instances. | |
| 21303 * | |
| 21304 * Returns the internal XML Schema structure built from the resource or | |
| 21305 * NULL in case of error | |
| 21306 */ | |
| 21307 xmlSchemaPtr | |
| 21308 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt) | |
| 21309 { | |
| 21310 xmlSchemaPtr mainSchema = NULL; | |
| 21311 xmlSchemaBucketPtr bucket = NULL; | |
| 21312 int res; | |
| 21313 | |
| 21314 /* | |
| 21315 * This one is used if the schema to be parsed was specified via | |
| 21316 * the API; i.e. not automatically by the validated instance document. | |
| 21317 */ | |
| 21318 | |
| 21319 xmlSchemaInitTypes(); | |
| 21320 | |
| 21321 if (ctxt == NULL) | |
| 21322 return (NULL); | |
| 21323 | |
| 21324 /* TODO: Init the context. Is this all we need?*/ | |
| 21325 ctxt->nberrors = 0; | |
| 21326 ctxt->err = 0; | |
| 21327 ctxt->counter = 0; | |
| 21328 | |
| 21329 /* Create the *main* schema. */ | |
| 21330 mainSchema = xmlSchemaNewSchema(ctxt); | |
| 21331 if (mainSchema == NULL) | |
| 21332 goto exit_failure; | |
| 21333 /* | |
| 21334 * Create the schema constructor. | |
| 21335 */ | |
| 21336 if (ctxt->constructor == NULL) { | |
| 21337 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict); | |
| 21338 if (ctxt->constructor == NULL) | |
| 21339 return(NULL); | |
| 21340 /* Take ownership of the constructor to be able to free it. */ | |
| 21341 ctxt->ownsConstructor = 1; | |
| 21342 } | |
| 21343 ctxt->constructor->mainSchema = mainSchema; | |
| 21344 /* | |
| 21345 * Locate and add the schema document. | |
| 21346 */ | |
| 21347 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN, | |
| 21348 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL, | |
| 21349 NULL, NULL, &bucket); | |
| 21350 if (res == -1) | |
| 21351 goto exit_failure; | |
| 21352 if (res != 0) | |
| 21353 goto exit; | |
| 21354 | |
| 21355 if (bucket == NULL) { | |
| 21356 /* TODO: Error code, actually we failed to *locate* the schema. */ | |
| 21357 if (ctxt->URL) | |
| 21358 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD, | |
| 21359 NULL, NULL, | |
| 21360 "Failed to locate the main schema resource at '%s'", | |
| 21361 ctxt->URL, NULL); | |
| 21362 else | |
| 21363 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD, | |
| 21364 NULL, NULL, | |
| 21365 "Failed to locate the main schema resource", | |
| 21366 NULL, NULL); | |
| 21367 goto exit; | |
| 21368 } | |
| 21369 /* Then do the parsing for good. */ | |
| 21370 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1) | |
| 21371 goto exit_failure; | |
| 21372 if (ctxt->nberrors != 0) | |
| 21373 goto exit; | |
| 21374 | |
| 21375 mainSchema->doc = bucket->doc; | |
| 21376 mainSchema->preserve = ctxt->preserve; | |
| 21377 | |
| 21378 ctxt->schema = mainSchema; | |
| 21379 | |
| 21380 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1) | |
| 21381 goto exit_failure; | |
| 21382 | |
| 21383 /* | |
| 21384 * TODO: This is not nice, since we cannot distinguish from the | |
| 21385 * result if there was an internal error or not. | |
| 21386 */ | |
| 21387 exit: | |
| 21388 if (ctxt->nberrors != 0) { | |
| 21389 if (mainSchema) { | |
| 21390 xmlSchemaFree(mainSchema); | |
| 21391 mainSchema = NULL; | |
| 21392 } | |
| 21393 if (ctxt->constructor) { | |
| 21394 xmlSchemaConstructionCtxtFree(ctxt->constructor); | |
| 21395 ctxt->constructor = NULL; | |
| 21396 ctxt->ownsConstructor = 0; | |
| 21397 } | |
| 21398 } | |
| 21399 ctxt->schema = NULL; | |
| 21400 return(mainSchema); | |
| 21401 exit_failure: | |
| 21402 /* | |
| 21403 * Quite verbose, but should catch internal errors, which were | |
| 21404 * not communitated. | |
| 21405 */ | |
| 21406 if (mainSchema) { | |
| 21407 xmlSchemaFree(mainSchema); | |
| 21408 mainSchema = NULL; | |
| 21409 } | |
| 21410 if (ctxt->constructor) { | |
| 21411 xmlSchemaConstructionCtxtFree(ctxt->constructor); | |
| 21412 ctxt->constructor = NULL; | |
| 21413 ctxt->ownsConstructor = 0; | |
| 21414 } | |
| 21415 PERROR_INT2("xmlSchemaParse", | |
| 21416 "An internal error occured"); | |
| 21417 ctxt->schema = NULL; | |
| 21418 return(NULL); | |
| 21419 } | |
| 21420 | |
| 21421 /** | |
| 21422 * xmlSchemaSetParserErrors: | |
| 21423 * @ctxt: a schema validation context | |
| 21424 * @err: the error callback | |
| 21425 * @warn: the warning callback | |
| 21426 * @ctx: contextual data for the callbacks | |
| 21427 * | |
| 21428 * Set the callback functions used to handle errors for a validation context | |
| 21429 */ | |
| 21430 void | |
| 21431 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt, | |
| 21432 xmlSchemaValidityErrorFunc err, | |
| 21433 xmlSchemaValidityWarningFunc warn, void *ctx) | |
| 21434 { | |
| 21435 if (ctxt == NULL) | |
| 21436 return; | |
| 21437 ctxt->error = err; | |
| 21438 ctxt->warning = warn; | |
| 21439 ctxt->errCtxt = ctx; | |
| 21440 if (ctxt->vctxt != NULL) | |
| 21441 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx); | |
| 21442 } | |
| 21443 | |
| 21444 /** | |
| 21445 * xmlSchemaSetParserStructuredErrors: | |
| 21446 * @ctxt: a schema parser context | |
| 21447 * @serror: the structured error function | |
| 21448 * @ctx: the functions context | |
| 21449 * | |
| 21450 * Set the structured error callback | |
| 21451 */ | |
| 21452 void | |
| 21453 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt, | |
| 21454 xmlStructuredErrorFunc serror, | |
| 21455 void *ctx) | |
| 21456 { | |
| 21457 if (ctxt == NULL) | |
| 21458 return; | |
| 21459 ctxt->serror = serror; | |
| 21460 ctxt->errCtxt = ctx; | |
| 21461 if (ctxt->vctxt != NULL) | |
| 21462 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx); | |
| 21463 } | |
| 21464 | |
| 21465 /** | |
| 21466 * xmlSchemaGetParserErrors: | |
| 21467 * @ctxt: a XMl-Schema parser context | |
| 21468 * @err: the error callback result | |
| 21469 * @warn: the warning callback result | |
| 21470 * @ctx: contextual data for the callbacks result | |
| 21471 * | |
| 21472 * Get the callback information used to handle errors for a parser context | |
| 21473 * | |
| 21474 * Returns -1 in case of failure, 0 otherwise | |
| 21475 */ | |
| 21476 int | |
| 21477 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt, | |
| 21478 xmlSchemaValidityErrorFunc * err, | |
| 21479 xmlSchemaValidityWarningFunc * warn, void **ctx) | |
| 21480 { | |
| 21481 if (ctxt == NULL) | |
| 21482 return(-1); | |
| 21483 if (err != NULL) | |
| 21484 *err = ctxt->error; | |
| 21485 if (warn != NULL) | |
| 21486 *warn = ctxt->warning; | |
| 21487 if (ctx != NULL) | |
| 21488 *ctx = ctxt->errCtxt; | |
| 21489 return(0); | |
| 21490 } | |
| 21491 | |
| 21492 /** | |
| 21493 * xmlSchemaFacetTypeToString: | |
| 21494 * @type: the facet type | |
| 21495 * | |
| 21496 * Convert the xmlSchemaTypeType to a char string. | |
| 21497 * | |
| 21498 * Returns the char string representation of the facet type if the | |
| 21499 * type is a facet and an "Internal Error" string otherwise. | |
| 21500 */ | |
| 21501 static const xmlChar * | |
| 21502 xmlSchemaFacetTypeToString(xmlSchemaTypeType type) | |
| 21503 { | |
| 21504 switch (type) { | |
| 21505 case XML_SCHEMA_FACET_PATTERN: | |
| 21506 return (BAD_CAST "pattern"); | |
| 21507 case XML_SCHEMA_FACET_MAXEXCLUSIVE: | |
| 21508 return (BAD_CAST "maxExclusive"); | |
| 21509 case XML_SCHEMA_FACET_MAXINCLUSIVE: | |
| 21510 return (BAD_CAST "maxInclusive"); | |
| 21511 case XML_SCHEMA_FACET_MINEXCLUSIVE: | |
| 21512 return (BAD_CAST "minExclusive"); | |
| 21513 case XML_SCHEMA_FACET_MININCLUSIVE: | |
| 21514 return (BAD_CAST "minInclusive"); | |
| 21515 case XML_SCHEMA_FACET_WHITESPACE: | |
| 21516 return (BAD_CAST "whiteSpace"); | |
| 21517 case XML_SCHEMA_FACET_ENUMERATION: | |
| 21518 return (BAD_CAST "enumeration"); | |
| 21519 case XML_SCHEMA_FACET_LENGTH: | |
| 21520 return (BAD_CAST "length"); | |
| 21521 case XML_SCHEMA_FACET_MAXLENGTH: | |
| 21522 return (BAD_CAST "maxLength"); | |
| 21523 case XML_SCHEMA_FACET_MINLENGTH: | |
| 21524 return (BAD_CAST "minLength"); | |
| 21525 case XML_SCHEMA_FACET_TOTALDIGITS: | |
| 21526 return (BAD_CAST "totalDigits"); | |
| 21527 case XML_SCHEMA_FACET_FRACTIONDIGITS: | |
| 21528 return (BAD_CAST "fractionDigits"); | |
| 21529 default: | |
| 21530 break; | |
| 21531 } | |
| 21532 return (BAD_CAST "Internal Error"); | |
| 21533 } | |
| 21534 | |
| 21535 static xmlSchemaWhitespaceValueType | |
| 21536 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type) | |
| 21537 { | |
| 21538 /* | |
| 21539 * The normalization type can be changed only for types which are derived | |
| 21540 * from xsd:string. | |
| 21541 */ | |
| 21542 if (type->type == XML_SCHEMA_TYPE_BASIC) { | |
| 21543 /* | |
| 21544 * Note that we assume a whitespace of preserve for anySimpleType. | |
| 21545 */ | |
| 21546 if ((type->builtInType == XML_SCHEMAS_STRING) || | |
| 21547 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) | |
| 21548 return(XML_SCHEMA_WHITESPACE_PRESERVE); | |
| 21549 else if (type->builtInType == XML_SCHEMAS_NORMSTRING) | |
| 21550 return(XML_SCHEMA_WHITESPACE_REPLACE); | |
| 21551 else { | |
| 21552 /* | |
| 21553 * For all `atomic` datatypes other than string (and types `derived` | |
| 21554 * by `restriction` from it) the value of whiteSpace is fixed to | |
| 21555 * collapse | |
| 21556 * Note that this includes built-in list datatypes. | |
| 21557 */ | |
| 21558 return(XML_SCHEMA_WHITESPACE_COLLAPSE); | |
| 21559 } | |
| 21560 } else if (WXS_IS_LIST(type)) { | |
| 21561 /* | |
| 21562 * For list types the facet "whiteSpace" is fixed to "collapse". | |
| 21563 */ | |
| 21564 return (XML_SCHEMA_WHITESPACE_COLLAPSE); | |
| 21565 } else if (WXS_IS_UNION(type)) { | |
| 21566 return (XML_SCHEMA_WHITESPACE_UNKNOWN); | |
| 21567 } else if (WXS_IS_ATOMIC(type)) { | |
| 21568 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE) | |
| 21569 return (XML_SCHEMA_WHITESPACE_PRESERVE); | |
| 21570 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE) | |
| 21571 return (XML_SCHEMA_WHITESPACE_REPLACE); | |
| 21572 else | |
| 21573 return (XML_SCHEMA_WHITESPACE_COLLAPSE); | |
| 21574 } | |
| 21575 return (-1); | |
| 21576 } | |
| 21577 | |
| 21578 /************************************************************************ | |
| 21579 * * | |
| 21580 * Simple type validation * | |
| 21581 * * | |
| 21582 ************************************************************************/ | |
| 21583 | |
| 21584 | |
| 21585 /************************************************************************ | |
| 21586 * * | |
| 21587 * DOM Validation code * | |
| 21588 * * | |
| 21589 ************************************************************************/ | |
| 21590 | |
| 21591 /** | |
| 21592 * xmlSchemaAssembleByLocation: | |
| 21593 * @pctxt: a schema parser context | |
| 21594 * @vctxt: a schema validation context | |
| 21595 * @schema: the existing schema | |
| 21596 * @node: the node that fired the assembling | |
| 21597 * @nsName: the namespace name of the new schema | |
| 21598 * @location: the location of the schema | |
| 21599 * | |
| 21600 * Expands an existing schema by an additional schema. | |
| 21601 * | |
| 21602 * Returns 0 if the new schema is correct, a positive error code | |
| 21603 * number otherwise and -1 in case of an internal or API error. | |
| 21604 */ | |
| 21605 static int | |
| 21606 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt, | |
| 21607 xmlSchemaPtr schema, | |
| 21608 xmlNodePtr node, | |
| 21609 const xmlChar *nsName, | |
| 21610 const xmlChar *location) | |
| 21611 { | |
| 21612 int ret = 0; | |
| 21613 xmlSchemaParserCtxtPtr pctxt; | |
| 21614 xmlSchemaBucketPtr bucket = NULL; | |
| 21615 | |
| 21616 if ((vctxt == NULL) || (schema == NULL)) | |
| 21617 return (-1); | |
| 21618 | |
| 21619 if (vctxt->pctxt == NULL) { | |
| 21620 VERROR_INT("xmlSchemaAssembleByLocation", | |
| 21621 "no parser context available"); | |
| 21622 return(-1); | |
| 21623 } | |
| 21624 pctxt = vctxt->pctxt; | |
| 21625 if (pctxt->constructor == NULL) { | |
| 21626 PERROR_INT("xmlSchemaAssembleByLocation", | |
| 21627 "no constructor"); | |
| 21628 return(-1); | |
| 21629 } | |
| 21630 /* | |
| 21631 * Acquire the schema document. | |
| 21632 */ | |
| 21633 location = xmlSchemaBuildAbsoluteURI(pctxt->dict, | |
| 21634 location, node); | |
| 21635 /* | |
| 21636 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here; | |
| 21637 * the process will automatically change this to | |
| 21638 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document. | |
| 21639 */ | |
| 21640 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT, | |
| 21641 location, NULL, NULL, 0, node, NULL, nsName, | |
| 21642 &bucket); | |
| 21643 if (ret != 0) | |
| 21644 return(ret); | |
| 21645 if (bucket == NULL) { | |
| 21646 /* | |
| 21647 * Generate a warning that the document could not be located. | |
| 21648 */ | |
| 21649 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC, | |
| 21650 node, NULL, | |
| 21651 "The document at location '%s' could not be acquired", | |
| 21652 location, NULL, NULL); | |
| 21653 return(ret); | |
| 21654 } | |
| 21655 /* | |
| 21656 * The first located schema will be handled as if all other | |
| 21657 * schemas imported by XSI were imported by this first schema. | |
| 21658 */ | |
| 21659 if ((bucket != NULL) && | |
| 21660 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL)) | |
| 21661 WXS_CONSTRUCTOR(pctxt)->bucket = bucket; | |
| 21662 /* | |
| 21663 * TODO: Is this handled like an import? I.e. is it not an error | |
| 21664 * if the schema cannot be located? | |
| 21665 */ | |
| 21666 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket))) | |
| 21667 return(0); | |
| 21668 /* | |
| 21669 * We will reuse the parser context for every schema imported | |
| 21670 * directly via XSI. So reset the context. | |
| 21671 */ | |
| 21672 pctxt->nberrors = 0; | |
| 21673 pctxt->err = 0; | |
| 21674 pctxt->doc = bucket->doc; | |
| 21675 | |
| 21676 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket); | |
| 21677 if (ret == -1) { | |
| 21678 pctxt->doc = NULL; | |
| 21679 goto exit_failure; | |
| 21680 } | |
| 21681 /* Paranoid error channelling. */ | |
| 21682 if ((ret == 0) && (pctxt->nberrors != 0)) | |
| 21683 ret = pctxt->err; | |
| 21684 if (pctxt->nberrors == 0) { | |
| 21685 /* | |
| 21686 * Only bother to fixup pending components, if there was | |
| 21687 * no error yet. | |
| 21688 * For every XSI acquired schema (and its sub-schemata) we will | |
| 21689 * fixup the components. | |
| 21690 */ | |
| 21691 xmlSchemaFixupComponents(pctxt, bucket); | |
| 21692 ret = pctxt->err; | |
| 21693 /* | |
| 21694 * Not nice, but we need somehow to channel the schema parser | |
| 21695 * error to the validation context. | |
| 21696 */ | |
| 21697 if ((ret != 0) && (vctxt->err == 0)) | |
| 21698 vctxt->err = ret; | |
| 21699 vctxt->nberrors += pctxt->nberrors; | |
| 21700 } else { | |
| 21701 /* Add to validation error sum. */ | |
| 21702 vctxt->nberrors += pctxt->nberrors; | |
| 21703 } | |
| 21704 pctxt->doc = NULL; | |
| 21705 return(ret); | |
| 21706 exit_failure: | |
| 21707 pctxt->doc = NULL; | |
| 21708 return (-1); | |
| 21709 } | |
| 21710 | |
| 21711 static xmlSchemaAttrInfoPtr | |
| 21712 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt, | |
| 21713 int metaType) | |
| 21714 { | |
| 21715 if (vctxt->nbAttrInfos == 0) | |
| 21716 return (NULL); | |
| 21717 { | |
| 21718 int i; | |
| 21719 xmlSchemaAttrInfoPtr iattr; | |
| 21720 | |
| 21721 for (i = 0; i < vctxt->nbAttrInfos; i++) { | |
| 21722 iattr = vctxt->attrInfos[i]; | |
| 21723 if (iattr->metaType == metaType) | |
| 21724 return (iattr); | |
| 21725 } | |
| 21726 | |
| 21727 } | |
| 21728 return (NULL); | |
| 21729 } | |
| 21730 | |
| 21731 /** | |
| 21732 * xmlSchemaAssembleByXSI: | |
| 21733 * @vctxt: a schema validation context | |
| 21734 * | |
| 21735 * Expands an existing schema by an additional schema using | |
| 21736 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute | |
| 21737 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace | |
| 21738 * must be set to 1. | |
| 21739 * | |
| 21740 * Returns 0 if the new schema is correct, a positive error code | |
| 21741 * number otherwise and -1 in case of an internal or API error. | |
| 21742 */ | |
| 21743 static int | |
| 21744 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt) | |
| 21745 { | |
| 21746 const xmlChar *cur, *end; | |
| 21747 const xmlChar *nsname = NULL, *location; | |
| 21748 int count = 0; | |
| 21749 int ret = 0; | |
| 21750 xmlSchemaAttrInfoPtr iattr; | |
| 21751 | |
| 21752 /* | |
| 21753 * Parse the value; we will assume an even number of values | |
| 21754 * to be given (this is how Xerces and XSV work). | |
| 21755 * | |
| 21756 * URGENT TODO: !! This needs to work for both | |
| 21757 * @noNamespaceSchemaLocation AND @schemaLocation on the same | |
| 21758 * element !! | |
| 21759 */ | |
| 21760 iattr = xmlSchemaGetMetaAttrInfo(vctxt, | |
| 21761 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC); | |
| 21762 if (iattr == NULL) | |
| 21763 iattr = xmlSchemaGetMetaAttrInfo(vctxt, | |
| 21764 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC); | |
| 21765 if (iattr == NULL) | |
| 21766 return (0); | |
| 21767 cur = iattr->value; | |
| 21768 do { | |
| 21769 /* | |
| 21770 * TODO: Move the string parsing mechanism away from here. | |
| 21771 */ | |
| 21772 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) { | |
| 21773 /* | |
| 21774 * Get the namespace name. | |
| 21775 */ | |
| 21776 while (IS_BLANK_CH(*cur)) | |
| 21777 cur++; | |
| 21778 end = cur; | |
| 21779 while ((*end != 0) && (!(IS_BLANK_CH(*end)))) | |
| 21780 end++; | |
| 21781 if (end == cur) | |
| 21782 break; | |
| 21783 count++; /* TODO: Don't use the schema's dict. */ | |
| 21784 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur); | |
| 21785 cur = end; | |
| 21786 } | |
| 21787 /* | |
| 21788 * Get the URI. | |
| 21789 */ | |
| 21790 while (IS_BLANK_CH(*cur)) | |
| 21791 cur++; | |
| 21792 end = cur; | |
| 21793 while ((*end != 0) && (!(IS_BLANK_CH(*end)))) | |
| 21794 end++; | |
| 21795 if (end == cur) { | |
| 21796 if (iattr->metaType == | |
| 21797 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) | |
| 21798 { | |
| 21799 /* | |
| 21800 * If using @schemaLocation then tuples are expected. | |
| 21801 * I.e. the namespace name *and* the document's URI. | |
| 21802 */ | |
| 21803 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC, | |
| 21804 iattr->node, NULL, | |
| 21805 "The value must consist of tuples: the target namespace " | |
| 21806 "name and the document's URI", NULL, NULL, NULL); | |
| 21807 } | |
| 21808 break; | |
| 21809 } | |
| 21810 count++; /* TODO: Don't use the schema's dict. */ | |
| 21811 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur); | |
| 21812 cur = end; | |
| 21813 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema, | |
| 21814 iattr->node, nsname, location); | |
| 21815 if (ret == -1) { | |
| 21816 VERROR_INT("xmlSchemaAssembleByXSI", | |
| 21817 "assembling schemata"); | |
| 21818 return (-1); | |
| 21819 } | |
| 21820 } while (*cur != 0); | |
| 21821 return (ret); | |
| 21822 } | |
| 21823 | |
| 21824 static const xmlChar * | |
| 21825 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt, | |
| 21826 const xmlChar *prefix) | |
| 21827 { | |
| 21828 if (vctxt->sax != NULL) { | |
| 21829 int i, j; | |
| 21830 xmlSchemaNodeInfoPtr inode; | |
| 21831 | |
| 21832 for (i = vctxt->depth; i >= 0; i--) { | |
| 21833 if (vctxt->elemInfos[i]->nbNsBindings != 0) { | |
| 21834 inode = vctxt->elemInfos[i]; | |
| 21835 for (j = 0; j < inode->nbNsBindings * 2; j += 2) { | |
| 21836 if (((prefix == NULL) && | |
| 21837 (inode->nsBindings[j] == NULL)) || | |
| 21838 ((prefix != NULL) && xmlStrEqual(prefix, | |
| 21839 inode->nsBindings[j]))) { | |
| 21840 | |
| 21841 /* | |
| 21842 * Note that the namespace bindings are already | |
| 21843 * in a string dict. | |
| 21844 */ | |
| 21845 return (inode->nsBindings[j+1]); | |
| 21846 } | |
| 21847 } | |
| 21848 } | |
| 21849 } | |
| 21850 return (NULL); | |
| 21851 #ifdef LIBXML_READER_ENABLED | |
| 21852 } else if (vctxt->reader != NULL) { | |
| 21853 xmlChar *nsName; | |
| 21854 | |
| 21855 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix); | |
| 21856 if (nsName != NULL) { | |
| 21857 const xmlChar *ret; | |
| 21858 | |
| 21859 ret = xmlDictLookup(vctxt->dict, nsName, -1); | |
| 21860 xmlFree(nsName); | |
| 21861 return (ret); | |
| 21862 } else | |
| 21863 return (NULL); | |
| 21864 #endif | |
| 21865 } else { | |
| 21866 xmlNsPtr ns; | |
| 21867 | |
| 21868 if ((vctxt->inode->node == NULL) || | |
| 21869 (vctxt->inode->node->doc == NULL)) { | |
| 21870 VERROR_INT("xmlSchemaLookupNamespace", | |
| 21871 "no node or node's doc avaliable"); | |
| 21872 return (NULL); | |
| 21873 } | |
| 21874 ns = xmlSearchNs(vctxt->inode->node->doc, | |
| 21875 vctxt->inode->node, prefix); | |
| 21876 if (ns != NULL) | |
| 21877 return (ns->href); | |
| 21878 return (NULL); | |
| 21879 } | |
| 21880 } | |
| 21881 | |
| 21882 /* | |
| 21883 * This one works on the schema of the validation context. | |
| 21884 */ | |
| 21885 static int | |
| 21886 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt, | |
| 21887 xmlSchemaPtr schema, | |
| 21888 xmlNodePtr node, | |
| 21889 const xmlChar *value, | |
| 21890 xmlSchemaValPtr *val, | |
| 21891 int valNeeded) | |
| 21892 { | |
| 21893 int ret; | |
| 21894 | |
| 21895 if (vctxt && (vctxt->schema == NULL)) { | |
| 21896 VERROR_INT("xmlSchemaValidateNotation", | |
| 21897 "a schema is needed on the validation context"); | |
| 21898 return (-1); | |
| 21899 } | |
| 21900 ret = xmlValidateQName(value, 1); | |
| 21901 if (ret != 0) | |
| 21902 return (ret); | |
| 21903 { | |
| 21904 xmlChar *localName = NULL; | |
| 21905 xmlChar *prefix = NULL; | |
| 21906 | |
| 21907 localName = xmlSplitQName2(value, &prefix); | |
| 21908 if (prefix != NULL) { | |
| 21909 const xmlChar *nsName = NULL; | |
| 21910 | |
| 21911 if (vctxt != NULL) | |
| 21912 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix); | |
| 21913 else if (node != NULL) { | |
| 21914 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix); | |
| 21915 if (ns != NULL) | |
| 21916 nsName = ns->href; | |
| 21917 } else { | |
| 21918 xmlFree(prefix); | |
| 21919 xmlFree(localName); | |
| 21920 return (1); | |
| 21921 } | |
| 21922 if (nsName == NULL) { | |
| 21923 xmlFree(prefix); | |
| 21924 xmlFree(localName); | |
| 21925 return (1); | |
| 21926 } | |
| 21927 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) { | |
| 21928 if ((valNeeded) && (val != NULL)) { | |
| 21929 (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName), | |
| 21930 xmlStrdup(nsName)); | |
| 21931 if (*val == NULL) | |
| 21932 ret = -1; | |
| 21933 } | |
| 21934 } else | |
| 21935 ret = 1; | |
| 21936 xmlFree(prefix); | |
| 21937 xmlFree(localName); | |
| 21938 } else { | |
| 21939 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) { | |
| 21940 if (valNeeded && (val != NULL)) { | |
| 21941 (*val) = xmlSchemaNewNOTATIONValue( | |
| 21942 BAD_CAST xmlStrdup(value), NULL); | |
| 21943 if (*val == NULL) | |
| 21944 ret = -1; | |
| 21945 } | |
| 21946 } else | |
| 21947 return (1); | |
| 21948 } | |
| 21949 } | |
| 21950 return (ret); | |
| 21951 } | |
| 21952 | |
| 21953 static int | |
| 21954 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt, | |
| 21955 const xmlChar* lname, | |
| 21956 const xmlChar* nsname) | |
| 21957 { | |
| 21958 int i; | |
| 21959 | |
| 21960 lname = xmlDictLookup(vctxt->dict, lname, -1); | |
| 21961 if (lname == NULL) | |
| 21962 return(-1); | |
| 21963 if (nsname != NULL) { | |
| 21964 nsname = xmlDictLookup(vctxt->dict, nsname, -1); | |
| 21965 if (nsname == NULL) | |
| 21966 return(-1); | |
| 21967 } | |
| 21968 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) { | |
| 21969 if ((vctxt->nodeQNames->items [i] == lname) && | |
| 21970 (vctxt->nodeQNames->items[i +1] == nsname)) | |
| 21971 /* Already there */ | |
| 21972 return(i); | |
| 21973 } | |
| 21974 /* Add new entry. */ | |
| 21975 i = vctxt->nodeQNames->nbItems; | |
| 21976 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname); | |
| 21977 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname); | |
| 21978 return(i); | |
| 21979 } | |
| 21980 | |
| 21981 /************************************************************************ | |
| 21982 * * | |
| 21983 * Validation of identity-constraints (IDC) * | |
| 21984 * * | |
| 21985 ************************************************************************/ | |
| 21986 | |
| 21987 /** | |
| 21988 * xmlSchemaAugmentIDC: | |
| 21989 * @idcDef: the IDC definition | |
| 21990 * | |
| 21991 * Creates an augmented IDC definition item. | |
| 21992 * | |
| 21993 * Returns the item, or NULL on internal errors. | |
| 21994 */ | |
| 21995 static void | |
| 21996 xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef, | |
| 21997 xmlSchemaValidCtxtPtr vctxt) | |
| 21998 { | |
| 21999 xmlSchemaIDCAugPtr aidc; | |
| 22000 | |
| 22001 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug)); | |
| 22002 if (aidc == NULL) { | |
| 22003 xmlSchemaVErrMemory(vctxt, | |
| 22004 "xmlSchemaAugmentIDC: allocating an augmented IDC definition", | |
| 22005 NULL); | |
| 22006 return; | |
| 22007 } | |
| 22008 aidc->keyrefDepth = -1; | |
| 22009 aidc->def = idcDef; | |
| 22010 aidc->next = NULL; | |
| 22011 if (vctxt->aidcs == NULL) | |
| 22012 vctxt->aidcs = aidc; | |
| 22013 else { | |
| 22014 aidc->next = vctxt->aidcs; | |
| 22015 vctxt->aidcs = aidc; | |
| 22016 } | |
| 22017 /* | |
| 22018 * Save if we have keyrefs at all. | |
| 22019 */ | |
| 22020 if ((vctxt->hasKeyrefs == 0) && | |
| 22021 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF)) | |
| 22022 vctxt->hasKeyrefs = 1; | |
| 22023 } | |
| 22024 | |
| 22025 /** | |
| 22026 * xmlSchemaAugmentImportedIDC: | |
| 22027 * @imported: the imported schema | |
| 22028 * | |
| 22029 * Creates an augmented IDC definition for the imported schema. | |
| 22030 */ | |
| 22031 static void | |
| 22032 xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr v
ctxt) { | |
| 22033 if (imported->schema->idcDef != NULL) { | |
| 22034 xmlHashScan(imported->schema->idcDef , | |
| 22035 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt); | |
| 22036 } | |
| 22037 } | |
| 22038 | |
| 22039 /** | |
| 22040 * xmlSchemaIDCNewBinding: | |
| 22041 * @idcDef: the IDC definition of this binding | |
| 22042 * | |
| 22043 * Creates a new IDC binding. | |
| 22044 * | |
| 22045 * Returns the new IDC binding, NULL on internal errors. | |
| 22046 */ | |
| 22047 static xmlSchemaPSVIIDCBindingPtr | |
| 22048 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef) | |
| 22049 { | |
| 22050 xmlSchemaPSVIIDCBindingPtr ret; | |
| 22051 | |
| 22052 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc( | |
| 22053 sizeof(xmlSchemaPSVIIDCBinding)); | |
| 22054 if (ret == NULL) { | |
| 22055 xmlSchemaVErrMemory(NULL, | |
| 22056 "allocating a PSVI IDC binding item", NULL); | |
| 22057 return (NULL); | |
| 22058 } | |
| 22059 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding)); | |
| 22060 ret->definition = idcDef; | |
| 22061 return (ret); | |
| 22062 } | |
| 22063 | |
| 22064 /** | |
| 22065 * xmlSchemaIDCStoreNodeTableItem: | |
| 22066 * @vctxt: the WXS validation context | |
| 22067 * @item: the IDC node table item | |
| 22068 * | |
| 22069 * The validation context is used to store IDC node table items. | |
| 22070 * They are stored to avoid copying them if IDC node-tables are merged | |
| 22071 * with corresponding parent IDC node-tables (bubbling). | |
| 22072 * | |
| 22073 * Returns 0 if succeeded, -1 on internal errors. | |
| 22074 */ | |
| 22075 static int | |
| 22076 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt, | |
| 22077 xmlSchemaPSVIIDCNodePtr item) | |
| 22078 { | |
| 22079 /* | |
| 22080 * Add to gobal list. | |
| 22081 */ | |
| 22082 if (vctxt->idcNodes == NULL) { | |
| 22083 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *) | |
| 22084 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr)); | |
| 22085 if (vctxt->idcNodes == NULL) { | |
| 22086 xmlSchemaVErrMemory(vctxt, | |
| 22087 "allocating the IDC node table item list", NULL); | |
| 22088 return (-1); | |
| 22089 } | |
| 22090 vctxt->sizeIdcNodes = 20; | |
| 22091 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) { | |
| 22092 vctxt->sizeIdcNodes *= 2; | |
| 22093 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *) | |
| 22094 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes * | |
| 22095 sizeof(xmlSchemaPSVIIDCNodePtr)); | |
| 22096 if (vctxt->idcNodes == NULL) { | |
| 22097 xmlSchemaVErrMemory(vctxt, | |
| 22098 "re-allocating the IDC node table item list", NULL); | |
| 22099 return (-1); | |
| 22100 } | |
| 22101 } | |
| 22102 vctxt->idcNodes[vctxt->nbIdcNodes++] = item; | |
| 22103 | |
| 22104 return (0); | |
| 22105 } | |
| 22106 | |
| 22107 /** | |
| 22108 * xmlSchemaIDCStoreKey: | |
| 22109 * @vctxt: the WXS validation context | |
| 22110 * @item: the IDC key | |
| 22111 * | |
| 22112 * The validation context is used to store an IDC key. | |
| 22113 * | |
| 22114 * Returns 0 if succeeded, -1 on internal errors. | |
| 22115 */ | |
| 22116 static int | |
| 22117 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt, | |
| 22118 xmlSchemaPSVIIDCKeyPtr key) | |
| 22119 { | |
| 22120 /* | |
| 22121 * Add to gobal list. | |
| 22122 */ | |
| 22123 if (vctxt->idcKeys == NULL) { | |
| 22124 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *) | |
| 22125 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr)); | |
| 22126 if (vctxt->idcKeys == NULL) { | |
| 22127 xmlSchemaVErrMemory(vctxt, | |
| 22128 "allocating the IDC key storage list", NULL); | |
| 22129 return (-1); | |
| 22130 } | |
| 22131 vctxt->sizeIdcKeys = 40; | |
| 22132 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) { | |
| 22133 vctxt->sizeIdcKeys *= 2; | |
| 22134 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *) | |
| 22135 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys * | |
| 22136 sizeof(xmlSchemaPSVIIDCKeyPtr)); | |
| 22137 if (vctxt->idcKeys == NULL) { | |
| 22138 xmlSchemaVErrMemory(vctxt, | |
| 22139 "re-allocating the IDC key storage list", NULL); | |
| 22140 return (-1); | |
| 22141 } | |
| 22142 } | |
| 22143 vctxt->idcKeys[vctxt->nbIdcKeys++] = key; | |
| 22144 | |
| 22145 return (0); | |
| 22146 } | |
| 22147 | |
| 22148 /** | |
| 22149 * xmlSchemaIDCAppendNodeTableItem: | |
| 22150 * @bind: the IDC binding | |
| 22151 * @ntItem: the node-table item | |
| 22152 * | |
| 22153 * Appends the IDC node-table item to the binding. | |
| 22154 * | |
| 22155 * Returns 0 on success and -1 on internal errors. | |
| 22156 */ | |
| 22157 static int | |
| 22158 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind, | |
| 22159 xmlSchemaPSVIIDCNodePtr ntItem) | |
| 22160 { | |
| 22161 if (bind->nodeTable == NULL) { | |
| 22162 bind->sizeNodes = 10; | |
| 22163 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) | |
| 22164 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr)); | |
| 22165 if (bind->nodeTable == NULL) { | |
| 22166 xmlSchemaVErrMemory(NULL, | |
| 22167 "allocating an array of IDC node-table items", NULL); | |
| 22168 return(-1); | |
| 22169 } | |
| 22170 } else if (bind->sizeNodes <= bind->nbNodes) { | |
| 22171 bind->sizeNodes *= 2; | |
| 22172 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) | |
| 22173 xmlRealloc(bind->nodeTable, bind->sizeNodes * | |
| 22174 sizeof(xmlSchemaPSVIIDCNodePtr)); | |
| 22175 if (bind->nodeTable == NULL) { | |
| 22176 xmlSchemaVErrMemory(NULL, | |
| 22177 "re-allocating an array of IDC node-table items", NULL); | |
| 22178 return(-1); | |
| 22179 } | |
| 22180 } | |
| 22181 bind->nodeTable[bind->nbNodes++] = ntItem; | |
| 22182 return(0); | |
| 22183 } | |
| 22184 | |
| 22185 /** | |
| 22186 * xmlSchemaIDCAcquireBinding: | |
| 22187 * @vctxt: the WXS validation context | |
| 22188 * @matcher: the IDC matcher | |
| 22189 * | |
| 22190 * Looks up an PSVI IDC binding, for the IDC definition and | |
| 22191 * of the given matcher. If none found, a new one is created | |
| 22192 * and added to the IDC table. | |
| 22193 * | |
| 22194 * Returns an IDC binding or NULL on internal errors. | |
| 22195 */ | |
| 22196 static xmlSchemaPSVIIDCBindingPtr | |
| 22197 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt, | |
| 22198 xmlSchemaIDCMatcherPtr matcher) | |
| 22199 { | |
| 22200 xmlSchemaNodeInfoPtr ielem; | |
| 22201 | |
| 22202 ielem = vctxt->elemInfos[matcher->depth]; | |
| 22203 | |
| 22204 if (ielem->idcTable == NULL) { | |
| 22205 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def); | |
| 22206 if (ielem->idcTable == NULL) | |
| 22207 return (NULL); | |
| 22208 return(ielem->idcTable); | |
| 22209 } else { | |
| 22210 xmlSchemaPSVIIDCBindingPtr bind = NULL; | |
| 22211 | |
| 22212 bind = ielem->idcTable; | |
| 22213 do { | |
| 22214 if (bind->definition == matcher->aidc->def) | |
| 22215 return(bind); | |
| 22216 if (bind->next == NULL) { | |
| 22217 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def); | |
| 22218 if (bind->next == NULL) | |
| 22219 return (NULL); | |
| 22220 return(bind->next); | |
| 22221 } | |
| 22222 bind = bind->next; | |
| 22223 } while (bind != NULL); | |
| 22224 } | |
| 22225 return (NULL); | |
| 22226 } | |
| 22227 | |
| 22228 static xmlSchemaItemListPtr | |
| 22229 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED, | |
| 22230 xmlSchemaIDCMatcherPtr matcher) | |
| 22231 { | |
| 22232 if (matcher->targets == NULL) | |
| 22233 matcher->targets = xmlSchemaItemListCreate(); | |
| 22234 return(matcher->targets); | |
| 22235 } | |
| 22236 | |
| 22237 /** | |
| 22238 * xmlSchemaIDCFreeKey: | |
| 22239 * @key: the IDC key | |
| 22240 * | |
| 22241 * Frees an IDC key together with its compiled value. | |
| 22242 */ | |
| 22243 static void | |
| 22244 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key) | |
| 22245 { | |
| 22246 if (key->val != NULL) | |
| 22247 xmlSchemaFreeValue(key->val); | |
| 22248 xmlFree(key); | |
| 22249 } | |
| 22250 | |
| 22251 /** | |
| 22252 * xmlSchemaIDCFreeBinding: | |
| 22253 * | |
| 22254 * Frees an IDC binding. Note that the node table-items | |
| 22255 * are not freed. | |
| 22256 */ | |
| 22257 static void | |
| 22258 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind) | |
| 22259 { | |
| 22260 if (bind->nodeTable != NULL) | |
| 22261 xmlFree(bind->nodeTable); | |
| 22262 if (bind->dupls != NULL) | |
| 22263 xmlSchemaItemListFree(bind->dupls); | |
| 22264 xmlFree(bind); | |
| 22265 } | |
| 22266 | |
| 22267 /** | |
| 22268 * xmlSchemaIDCFreeIDCTable: | |
| 22269 * @bind: the first IDC binding in the list | |
| 22270 * | |
| 22271 * Frees an IDC table, i.e. all the IDC bindings in the list. | |
| 22272 */ | |
| 22273 static void | |
| 22274 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind) | |
| 22275 { | |
| 22276 xmlSchemaPSVIIDCBindingPtr prev; | |
| 22277 | |
| 22278 while (bind != NULL) { | |
| 22279 prev = bind; | |
| 22280 bind = bind->next; | |
| 22281 xmlSchemaIDCFreeBinding(prev); | |
| 22282 } | |
| 22283 } | |
| 22284 | |
| 22285 /** | |
| 22286 * xmlSchemaIDCFreeMatcherList: | |
| 22287 * @matcher: the first IDC matcher in the list | |
| 22288 * | |
| 22289 * Frees a list of IDC matchers. | |
| 22290 */ | |
| 22291 static void | |
| 22292 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher) | |
| 22293 { | |
| 22294 xmlSchemaIDCMatcherPtr next; | |
| 22295 | |
| 22296 while (matcher != NULL) { | |
| 22297 next = matcher->next; | |
| 22298 if (matcher->keySeqs != NULL) { | |
| 22299 int i; | |
| 22300 for (i = 0; i < matcher->sizeKeySeqs; i++) | |
| 22301 if (matcher->keySeqs[i] != NULL) | |
| 22302 xmlFree(matcher->keySeqs[i]); | |
| 22303 xmlFree(matcher->keySeqs); | |
| 22304 } | |
| 22305 if (matcher->targets != NULL) { | |
| 22306 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) { | |
| 22307 int i; | |
| 22308 xmlSchemaPSVIIDCNodePtr idcNode; | |
| 22309 /* | |
| 22310 * Node-table items for keyrefs are not stored globally | |
| 22311 * to the validation context, since they are not bubbled. | |
| 22312 * We need to free them here. | |
| 22313 */ | |
| 22314 for (i = 0; i < matcher->targets->nbItems; i++) { | |
| 22315 idcNode = | |
| 22316 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i]; | |
| 22317 xmlFree(idcNode->keys); | |
| 22318 xmlFree(idcNode); | |
| 22319 } | |
| 22320 } | |
| 22321 xmlSchemaItemListFree(matcher->targets); | |
| 22322 } | |
| 22323 xmlFree(matcher); | |
| 22324 matcher = next; | |
| 22325 } | |
| 22326 } | |
| 22327 | |
| 22328 /** | |
| 22329 * xmlSchemaIDCReleaseMatcherList: | |
| 22330 * @vctxt: the WXS validation context | |
| 22331 * @matcher: the first IDC matcher in the list | |
| 22332 * | |
| 22333 * Caches a list of IDC matchers for reuse. | |
| 22334 */ | |
| 22335 static void | |
| 22336 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt, | |
| 22337 xmlSchemaIDCMatcherPtr matcher) | |
| 22338 { | |
| 22339 xmlSchemaIDCMatcherPtr next; | |
| 22340 | |
| 22341 while (matcher != NULL) { | |
| 22342 next = matcher->next; | |
| 22343 if (matcher->keySeqs != NULL) { | |
| 22344 int i; | |
| 22345 /* | |
| 22346 * Don't free the array, but only the content. | |
| 22347 */ | |
| 22348 for (i = 0; i < matcher->sizeKeySeqs; i++) | |
| 22349 if (matcher->keySeqs[i] != NULL) { | |
| 22350 xmlFree(matcher->keySeqs[i]); | |
| 22351 matcher->keySeqs[i] = NULL; | |
| 22352 } | |
| 22353 } | |
| 22354 if (matcher->targets) { | |
| 22355 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) { | |
| 22356 int i; | |
| 22357 xmlSchemaPSVIIDCNodePtr idcNode; | |
| 22358 /* | |
| 22359 * Node-table items for keyrefs are not stored globally | |
| 22360 * to the validation context, since they are not bubbled. | |
| 22361 * We need to free them here. | |
| 22362 */ | |
| 22363 for (i = 0; i < matcher->targets->nbItems; i++) { | |
| 22364 idcNode = | |
| 22365 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i]; | |
| 22366 xmlFree(idcNode->keys); | |
| 22367 xmlFree(idcNode); | |
| 22368 } | |
| 22369 } | |
| 22370 xmlSchemaItemListFree(matcher->targets); | |
| 22371 matcher->targets = NULL; | |
| 22372 } | |
| 22373 matcher->next = NULL; | |
| 22374 /* | |
| 22375 * Cache the matcher. | |
| 22376 */ | |
| 22377 if (vctxt->idcMatcherCache != NULL) | |
| 22378 matcher->nextCached = vctxt->idcMatcherCache; | |
| 22379 vctxt->idcMatcherCache = matcher; | |
| 22380 | |
| 22381 matcher = next; | |
| 22382 } | |
| 22383 } | |
| 22384 | |
| 22385 /** | |
| 22386 * xmlSchemaIDCAddStateObject: | |
| 22387 * @vctxt: the WXS validation context | |
| 22388 * @matcher: the IDC matcher | |
| 22389 * @sel: the XPath information | |
| 22390 * @parent: the parent "selector" state object if any | |
| 22391 * @type: "selector" or "field" | |
| 22392 * | |
| 22393 * Creates/reuses and activates state objects for the given | |
| 22394 * XPath information; if the XPath expression consists of unions, | |
| 22395 * multiple state objects are created for every unioned expression. | |
| 22396 * | |
| 22397 * Returns 0 on success and -1 on internal errors. | |
| 22398 */ | |
| 22399 static int | |
| 22400 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt, | |
| 22401 xmlSchemaIDCMatcherPtr matcher, | |
| 22402 xmlSchemaIDCSelectPtr sel, | |
| 22403 int type) | |
| 22404 { | |
| 22405 xmlSchemaIDCStateObjPtr sto; | |
| 22406 | |
| 22407 /* | |
| 22408 * Reuse the state objects from the pool. | |
| 22409 */ | |
| 22410 if (vctxt->xpathStatePool != NULL) { | |
| 22411 sto = vctxt->xpathStatePool; | |
| 22412 vctxt->xpathStatePool = sto->next; | |
| 22413 sto->next = NULL; | |
| 22414 } else { | |
| 22415 /* | |
| 22416 * Create a new state object. | |
| 22417 */ | |
| 22418 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj)); | |
| 22419 if (sto == NULL) { | |
| 22420 xmlSchemaVErrMemory(NULL, | |
| 22421 "allocating an IDC state object", NULL); | |
| 22422 return (-1); | |
| 22423 } | |
| 22424 memset(sto, 0, sizeof(xmlSchemaIDCStateObj)); | |
| 22425 } | |
| 22426 /* | |
| 22427 * Add to global list. | |
| 22428 */ | |
| 22429 if (vctxt->xpathStates != NULL) | |
| 22430 sto->next = vctxt->xpathStates; | |
| 22431 vctxt->xpathStates = sto; | |
| 22432 | |
| 22433 /* | |
| 22434 * Free the old xpath validation context. | |
| 22435 */ | |
| 22436 if (sto->xpathCtxt != NULL) | |
| 22437 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt); | |
| 22438 | |
| 22439 /* | |
| 22440 * Create a new XPath (pattern) validation context. | |
| 22441 */ | |
| 22442 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt( | |
| 22443 (xmlPatternPtr) sel->xpathComp); | |
| 22444 if (sto->xpathCtxt == NULL) { | |
| 22445 VERROR_INT("xmlSchemaIDCAddStateObject", | |
| 22446 "failed to create an XPath validation context"); | |
| 22447 return (-1); | |
| 22448 } | |
| 22449 sto->type = type; | |
| 22450 sto->depth = vctxt->depth; | |
| 22451 sto->matcher = matcher; | |
| 22452 sto->sel = sel; | |
| 22453 sto->nbHistory = 0; | |
| 22454 | |
| 22455 #ifdef DEBUG_IDC | |
| 22456 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n", | |
| 22457 sto->sel->xpath); | |
| 22458 #endif | |
| 22459 return (0); | |
| 22460 } | |
| 22461 | |
| 22462 /** | |
| 22463 * xmlSchemaXPathEvaluate: | |
| 22464 * @vctxt: the WXS validation context | |
| 22465 * @nodeType: the nodeType of the current node | |
| 22466 * | |
| 22467 * Evaluates all active XPath state objects. | |
| 22468 * | |
| 22469 * Returns the number of IC "field" state objects which resolved to | |
| 22470 * this node, 0 if none resolved and -1 on internal errors. | |
| 22471 */ | |
| 22472 static int | |
| 22473 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt, | |
| 22474 xmlElementType nodeType) | |
| 22475 { | |
| 22476 xmlSchemaIDCStateObjPtr sto, head = NULL, first; | |
| 22477 int res, resolved = 0, depth = vctxt->depth; | |
| 22478 | |
| 22479 if (vctxt->xpathStates == NULL) | |
| 22480 return (0); | |
| 22481 | |
| 22482 if (nodeType == XML_ATTRIBUTE_NODE) | |
| 22483 depth++; | |
| 22484 #ifdef DEBUG_IDC | |
| 22485 { | |
| 22486 xmlChar *str = NULL; | |
| 22487 xmlGenericError(xmlGenericErrorContext, | |
| 22488 "IDC: EVAL on %s, depth %d, type %d\n", | |
| 22489 xmlSchemaFormatQName(&str, vctxt->inode->nsName, | |
| 22490 vctxt->inode->localName), depth, nodeType); | |
| 22491 FREE_AND_NULL(str) | |
| 22492 } | |
| 22493 #endif | |
| 22494 /* | |
| 22495 * Process all active XPath state objects. | |
| 22496 */ | |
| 22497 first = vctxt->xpathStates; | |
| 22498 sto = first; | |
| 22499 while (sto != head) { | |
| 22500 #ifdef DEBUG_IDC | |
| 22501 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) | |
| 22502 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'
\n", | |
| 22503 sto->matcher->aidc->def->name, sto->sel->xpath); | |
| 22504 else | |
| 22505 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n"
, | |
| 22506 sto->matcher->aidc->def->name, sto->sel->xpath); | |
| 22507 #endif | |
| 22508 if (nodeType == XML_ELEMENT_NODE) | |
| 22509 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt, | |
| 22510 vctxt->inode->localName, vctxt->inode->nsName); | |
| 22511 else | |
| 22512 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt, | |
| 22513 vctxt->inode->localName, vctxt->inode->nsName); | |
| 22514 | |
| 22515 if (res == -1) { | |
| 22516 VERROR_INT("xmlSchemaXPathEvaluate", | |
| 22517 "calling xmlStreamPush()"); | |
| 22518 return (-1); | |
| 22519 } | |
| 22520 if (res == 0) | |
| 22521 goto next_sto; | |
| 22522 /* | |
| 22523 * Full match. | |
| 22524 */ | |
| 22525 #ifdef DEBUG_IDC | |
| 22526 xmlGenericError(xmlGenericErrorContext, "IDC: " | |
| 22527 "MATCH\n"); | |
| 22528 #endif | |
| 22529 /* | |
| 22530 * Register a match in the state object history. | |
| 22531 */ | |
| 22532 if (sto->history == NULL) { | |
| 22533 sto->history = (int *) xmlMalloc(5 * sizeof(int)); | |
| 22534 if (sto->history == NULL) { | |
| 22535 xmlSchemaVErrMemory(NULL, | |
| 22536 "allocating the state object history", NULL); | |
| 22537 return(-1); | |
| 22538 } | |
| 22539 sto->sizeHistory = 5; | |
| 22540 } else if (sto->sizeHistory <= sto->nbHistory) { | |
| 22541 sto->sizeHistory *= 2; | |
| 22542 sto->history = (int *) xmlRealloc(sto->history, | |
| 22543 sto->sizeHistory * sizeof(int)); | |
| 22544 if (sto->history == NULL) { | |
| 22545 xmlSchemaVErrMemory(NULL, | |
| 22546 "re-allocating the state object history", NULL); | |
| 22547 return(-1); | |
| 22548 } | |
| 22549 } | |
| 22550 sto->history[sto->nbHistory++] = depth; | |
| 22551 | |
| 22552 #ifdef DEBUG_IDC | |
| 22553 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n", | |
| 22554 vctxt->depth); | |
| 22555 #endif | |
| 22556 | |
| 22557 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) { | |
| 22558 xmlSchemaIDCSelectPtr sel; | |
| 22559 /* | |
| 22560 * Activate state objects for the IDC fields of | |
| 22561 * the IDC selector. | |
| 22562 */ | |
| 22563 #ifdef DEBUG_IDC | |
| 22564 xmlGenericError(xmlGenericErrorContext, "IDC: " | |
| 22565 "activating field states\n"); | |
| 22566 #endif | |
| 22567 sel = sto->matcher->aidc->def->fields; | |
| 22568 while (sel != NULL) { | |
| 22569 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher, | |
| 22570 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1) | |
| 22571 return (-1); | |
| 22572 sel = sel->next; | |
| 22573 } | |
| 22574 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) { | |
| 22575 /* | |
| 22576 * An IDC key node was found by the IDC field. | |
| 22577 */ | |
| 22578 #ifdef DEBUG_IDC | |
| 22579 xmlGenericError(xmlGenericErrorContext, | |
| 22580 "IDC: key found\n"); | |
| 22581 #endif | |
| 22582 /* | |
| 22583 * Notify that the character value of this node is | |
| 22584 * needed. | |
| 22585 */ | |
| 22586 if (resolved == 0) { | |
| 22587 if ((vctxt->inode->flags & | |
| 22588 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0) | |
| 22589 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED; | |
| 22590 } | |
| 22591 resolved++; | |
| 22592 } | |
| 22593 next_sto: | |
| 22594 if (sto->next == NULL) { | |
| 22595 /* | |
| 22596 * Evaluate field state objects created on this node as well. | |
| 22597 */ | |
| 22598 head = first; | |
| 22599 sto = vctxt->xpathStates; | |
| 22600 } else | |
| 22601 sto = sto->next; | |
| 22602 } | |
| 22603 return (resolved); | |
| 22604 } | |
| 22605 | |
| 22606 static const xmlChar * | |
| 22607 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt, | |
| 22608 xmlChar **buf, | |
| 22609 xmlSchemaPSVIIDCKeyPtr *seq, | |
| 22610 int count) | |
| 22611 { | |
| 22612 int i, res; | |
| 22613 xmlChar *value = NULL; | |
| 22614 | |
| 22615 *buf = xmlStrdup(BAD_CAST "["); | |
| 22616 for (i = 0; i < count; i++) { | |
| 22617 *buf = xmlStrcat(*buf, BAD_CAST "'"); | |
| 22618 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val, | |
| 22619 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type), | |
| 22620 &value); | |
| 22621 if (res == 0) | |
| 22622 *buf = xmlStrcat(*buf, BAD_CAST value); | |
| 22623 else { | |
| 22624 VERROR_INT("xmlSchemaFormatIDCKeySequence", | |
| 22625 "failed to compute a canonical value"); | |
| 22626 *buf = xmlStrcat(*buf, BAD_CAST "???"); | |
| 22627 } | |
| 22628 if (i < count -1) | |
| 22629 *buf = xmlStrcat(*buf, BAD_CAST "', "); | |
| 22630 else | |
| 22631 *buf = xmlStrcat(*buf, BAD_CAST "'"); | |
| 22632 if (value != NULL) { | |
| 22633 xmlFree(value); | |
| 22634 value = NULL; | |
| 22635 } | |
| 22636 } | |
| 22637 *buf = xmlStrcat(*buf, BAD_CAST "]"); | |
| 22638 | |
| 22639 return (BAD_CAST *buf); | |
| 22640 } | |
| 22641 | |
| 22642 /** | |
| 22643 * xmlSchemaXPathPop: | |
| 22644 * @vctxt: the WXS validation context | |
| 22645 * | |
| 22646 * Pops all XPath states. | |
| 22647 * | |
| 22648 * Returns 0 on success and -1 on internal errors. | |
| 22649 */ | |
| 22650 static int | |
| 22651 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt) | |
| 22652 { | |
| 22653 xmlSchemaIDCStateObjPtr sto; | |
| 22654 int res; | |
| 22655 | |
| 22656 if (vctxt->xpathStates == NULL) | |
| 22657 return(0); | |
| 22658 sto = vctxt->xpathStates; | |
| 22659 do { | |
| 22660 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt); | |
| 22661 if (res == -1) | |
| 22662 return (-1); | |
| 22663 sto = sto->next; | |
| 22664 } while (sto != NULL); | |
| 22665 return(0); | |
| 22666 } | |
| 22667 | |
| 22668 /** | |
| 22669 * xmlSchemaXPathProcessHistory: | |
| 22670 * @vctxt: the WXS validation context | |
| 22671 * @type: the simple/complex type of the current node if any at all | |
| 22672 * @val: the precompiled value | |
| 22673 * | |
| 22674 * Processes and pops the history items of the IDC state objects. | |
| 22675 * IDC key-sequences are validated/created on IDC bindings. | |
| 22676 * | |
| 22677 * Returns 0 on success and -1 on internal errors. | |
| 22678 */ | |
| 22679 static int | |
| 22680 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt, | |
| 22681 int depth) | |
| 22682 { | |
| 22683 xmlSchemaIDCStateObjPtr sto, nextsto; | |
| 22684 int res, matchDepth; | |
| 22685 xmlSchemaPSVIIDCKeyPtr key = NULL; | |
| 22686 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL; | |
| 22687 | |
| 22688 if (vctxt->xpathStates == NULL) | |
| 22689 return (0); | |
| 22690 sto = vctxt->xpathStates; | |
| 22691 | |
| 22692 #ifdef DEBUG_IDC | |
| 22693 { | |
| 22694 xmlChar *str = NULL; | |
| 22695 xmlGenericError(xmlGenericErrorContext, | |
| 22696 "IDC: BACK on %s, depth %d\n", | |
| 22697 xmlSchemaFormatQName(&str, vctxt->inode->nsName, | |
| 22698 vctxt->inode->localName), vctxt->depth); | |
| 22699 FREE_AND_NULL(str) | |
| 22700 } | |
| 22701 #endif | |
| 22702 /* | |
| 22703 * Evaluate the state objects. | |
| 22704 */ | |
| 22705 while (sto != NULL) { | |
| 22706 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt); | |
| 22707 if (res == -1) { | |
| 22708 VERROR_INT("xmlSchemaXPathProcessHistory", | |
| 22709 "calling xmlStreamPop()"); | |
| 22710 return (-1); | |
| 22711 } | |
| 22712 #ifdef DEBUG_IDC | |
| 22713 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n", | |
| 22714 sto->sel->xpath); | |
| 22715 #endif | |
| 22716 if (sto->nbHistory == 0) | |
| 22717 goto deregister_check; | |
| 22718 | |
| 22719 matchDepth = sto->history[sto->nbHistory -1]; | |
| 22720 | |
| 22721 /* | |
| 22722 * Only matches at the current depth are of interest. | |
| 22723 */ | |
| 22724 if (matchDepth != depth) { | |
| 22725 sto = sto->next; | |
| 22726 continue; | |
| 22727 } | |
| 22728 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) { | |
| 22729 /* | |
| 22730 * NOTE: According to | |
| 22731 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198 | |
| 22732 * ... the simple-content of complex types is also allowed. | |
| 22733 */ | |
| 22734 | |
| 22735 if (WXS_IS_COMPLEX(type)) { | |
| 22736 if (WXS_HAS_SIMPLE_CONTENT(type)) { | |
| 22737 /* | |
| 22738 * Sanity check for complex types with simple content. | |
| 22739 */ | |
| 22740 simpleType = type->contentTypeDef; | |
| 22741 if (simpleType == NULL) { | |
| 22742 VERROR_INT("xmlSchemaXPathProcessHistory", | |
| 22743 "field resolves to a CT with simple content " | |
| 22744 "but the CT is missing the ST definition"); | |
| 22745 return (-1); | |
| 22746 } | |
| 22747 } else | |
| 22748 simpleType = NULL; | |
| 22749 } else | |
| 22750 simpleType = type; | |
| 22751 if (simpleType == NULL) { | |
| 22752 xmlChar *str = NULL; | |
| 22753 | |
| 22754 /* | |
| 22755 * Not qualified if the field resolves to a node of non | |
| 22756 * simple type. | |
| 22757 */ | |
| 22758 xmlSchemaCustomErr(ACTXT_CAST vctxt, | |
| 22759 XML_SCHEMAV_CVC_IDC, NULL, | |
| 22760 WXS_BASIC_CAST sto->matcher->aidc->def, | |
| 22761 "The XPath '%s' of a field of %s does evaluate to a node of
" | |
| 22762 "non-simple type", | |
| 22763 sto->sel->xpath, | |
| 22764 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def)); | |
| 22765 FREE_AND_NULL(str); | |
| 22766 sto->nbHistory--; | |
| 22767 goto deregister_check; | |
| 22768 } | |
| 22769 | |
| 22770 if ((key == NULL) && (vctxt->inode->val == NULL)) { | |
| 22771 /* | |
| 22772 * Failed to provide the normalized value; maybe | |
| 22773 * the value was invalid. | |
| 22774 */ | |
| 22775 VERROR(XML_SCHEMAV_CVC_IDC, | |
| 22776 WXS_BASIC_CAST sto->matcher->aidc->def, | |
| 22777 "Warning: No precomputed value available, the value " | |
| 22778 "was either invalid or something strange happend"); | |
| 22779 sto->nbHistory--; | |
| 22780 goto deregister_check; | |
| 22781 } else { | |
| 22782 xmlSchemaIDCMatcherPtr matcher = sto->matcher; | |
| 22783 xmlSchemaPSVIIDCKeyPtr *keySeq; | |
| 22784 int pos, idx; | |
| 22785 | |
| 22786 /* | |
| 22787 * The key will be anchored on the matcher's list of | |
| 22788 * key-sequences. The position in this list is determined | |
| 22789 * by the target node's depth relative to the matcher's | |
| 22790 * depth of creation (i.e. the depth of the scope element). | |
| 22791 * | |
| 22792 * Element Depth Pos List-entries | |
| 22793 * <scope> 0 NULL | |
| 22794 * <bar> 1 NULL | |
| 22795 * <target/> 2 2 target | |
| 22796 * <bar> | |
| 22797 * </scope> | |
| 22798 * | |
| 22799 * The size of the list is only dependant on the depth of | |
| 22800 * the tree. | |
| 22801 * An entry will be NULLed in selector_leave, i.e. when | |
| 22802 * we hit the target's | |
| 22803 */ | |
| 22804 pos = sto->depth - matcher->depth; | |
| 22805 idx = sto->sel->index; | |
| 22806 | |
| 22807 /* | |
| 22808 * Create/grow the array of key-sequences. | |
| 22809 */ | |
| 22810 if (matcher->keySeqs == NULL) { | |
| 22811 if (pos > 9) | |
| 22812 matcher->sizeKeySeqs = pos * 2; | |
| 22813 else | |
| 22814 matcher->sizeKeySeqs = 10; | |
| 22815 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **) | |
| 22816 xmlMalloc(matcher->sizeKeySeqs * | |
| 22817 sizeof(xmlSchemaPSVIIDCKeyPtr *)); | |
| 22818 if (matcher->keySeqs == NULL) { | |
| 22819 xmlSchemaVErrMemory(NULL, | |
| 22820 "allocating an array of key-sequences", | |
| 22821 NULL); | |
| 22822 return(-1); | |
| 22823 } | |
| 22824 memset(matcher->keySeqs, 0, | |
| 22825 matcher->sizeKeySeqs * | |
| 22826 sizeof(xmlSchemaPSVIIDCKeyPtr *)); | |
| 22827 } else if (pos >= matcher->sizeKeySeqs) { | |
| 22828 int i = matcher->sizeKeySeqs; | |
| 22829 | |
| 22830 matcher->sizeKeySeqs *= 2; | |
| 22831 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **) | |
| 22832 xmlRealloc(matcher->keySeqs, | |
| 22833 matcher->sizeKeySeqs * | |
| 22834 sizeof(xmlSchemaPSVIIDCKeyPtr *)); | |
| 22835 if (matcher->keySeqs == NULL) { | |
| 22836 xmlSchemaVErrMemory(NULL, | |
| 22837 "reallocating an array of key-sequences", | |
| 22838 NULL); | |
| 22839 return (-1); | |
| 22840 } | |
| 22841 /* | |
| 22842 * The array needs to be NULLed. | |
| 22843 * TODO: Use memset? | |
| 22844 */ | |
| 22845 for (; i < matcher->sizeKeySeqs; i++) | |
| 22846 matcher->keySeqs[i] = NULL; | |
| 22847 } | |
| 22848 | |
| 22849 /* | |
| 22850 * Get/create the key-sequence. | |
| 22851 */ | |
| 22852 keySeq = matcher->keySeqs[pos]; | |
| 22853 if (keySeq == NULL) { | |
| 22854 goto create_sequence; | |
| 22855 } else if (keySeq[idx] != NULL) { | |
| 22856 xmlChar *str = NULL; | |
| 22857 /* | |
| 22858 * cvc-identity-constraint: | |
| 22859 * 3 For each node in the `target node set` all | |
| 22860 * of the {fields}, with that node as the context | |
| 22861 * node, evaluate to either an empty node-set or | |
| 22862 * a node-set with exactly one member, which must | |
| 22863 * have a simple type. | |
| 22864 * | |
| 22865 * The key was already set; report an error. | |
| 22866 */ | |
| 22867 xmlSchemaCustomErr(ACTXT_CAST vctxt, | |
| 22868 XML_SCHEMAV_CVC_IDC, NULL, | |
| 22869 WXS_BASIC_CAST matcher->aidc->def, | |
| 22870 "The XPath '%s' of a field of %s evaluates to a " | |
| 22871 "node-set with more than one member", | |
| 22872 sto->sel->xpath, | |
| 22873 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def)); | |
| 22874 FREE_AND_NULL(str); | |
| 22875 sto->nbHistory--; | |
| 22876 goto deregister_check; | |
| 22877 } else | |
| 22878 goto create_key; | |
| 22879 | |
| 22880 create_sequence: | |
| 22881 /* | |
| 22882 * Create a key-sequence. | |
| 22883 */ | |
| 22884 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc( | |
| 22885 matcher->aidc->def->nbFields * | |
| 22886 sizeof(xmlSchemaPSVIIDCKeyPtr)); | |
| 22887 if (keySeq == NULL) { | |
| 22888 xmlSchemaVErrMemory(NULL, | |
| 22889 "allocating an IDC key-sequence", NULL); | |
| 22890 return(-1); | |
| 22891 } | |
| 22892 memset(keySeq, 0, matcher->aidc->def->nbFields * | |
| 22893 sizeof(xmlSchemaPSVIIDCKeyPtr)); | |
| 22894 matcher->keySeqs[pos] = keySeq; | |
| 22895 create_key: | |
| 22896 /* | |
| 22897 * Create a key once per node only. | |
| 22898 */ | |
| 22899 if (key == NULL) { | |
| 22900 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc( | |
| 22901 sizeof(xmlSchemaPSVIIDCKey)); | |
| 22902 if (key == NULL) { | |
| 22903 xmlSchemaVErrMemory(NULL, | |
| 22904 "allocating a IDC key", NULL); | |
| 22905 xmlFree(keySeq); | |
| 22906 matcher->keySeqs[pos] = NULL; | |
| 22907 return(-1); | |
| 22908 } | |
| 22909 /* | |
| 22910 * Consume the compiled value. | |
| 22911 */ | |
| 22912 key->type = simpleType; | |
| 22913 key->val = vctxt->inode->val; | |
| 22914 vctxt->inode->val = NULL; | |
| 22915 /* | |
| 22916 * Store the key in a global list. | |
| 22917 */ | |
| 22918 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) { | |
| 22919 xmlSchemaIDCFreeKey(key); | |
| 22920 return (-1); | |
| 22921 } | |
| 22922 } | |
| 22923 keySeq[idx] = key; | |
| 22924 } | |
| 22925 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) { | |
| 22926 | |
| 22927 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL; | |
| 22928 /* xmlSchemaPSVIIDCBindingPtr bind; */ | |
| 22929 xmlSchemaPSVIIDCNodePtr ntItem; | |
| 22930 xmlSchemaIDCMatcherPtr matcher; | |
| 22931 xmlSchemaIDCPtr idc; | |
| 22932 xmlSchemaItemListPtr targets; | |
| 22933 int pos, i, j, nbKeys; | |
| 22934 /* | |
| 22935 * Here we have the following scenario: | |
| 22936 * An IDC 'selector' state object resolved to a target node, | |
| 22937 * during the time this target node was in the | |
| 22938 * ancestor-or-self axis, the 'field' state object(s) looked | |
| 22939 * out for matching nodes to create a key-sequence for this | |
| 22940 * target node. Now we are back to this target node and need | |
| 22941 * to put the key-sequence, together with the target node | |
| 22942 * itself, into the node-table of the corresponding IDC | |
| 22943 * binding. | |
| 22944 */ | |
| 22945 matcher = sto->matcher; | |
| 22946 idc = matcher->aidc->def; | |
| 22947 nbKeys = idc->nbFields; | |
| 22948 pos = depth - matcher->depth; | |
| 22949 /* | |
| 22950 * Check if the matcher has any key-sequences at all, plus | |
| 22951 * if it has a key-sequence for the current target node. | |
| 22952 */ | |
| 22953 if ((matcher->keySeqs == NULL) || | |
| 22954 (matcher->sizeKeySeqs <= pos)) { | |
| 22955 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) | |
| 22956 goto selector_key_error; | |
| 22957 else | |
| 22958 goto selector_leave; | |
| 22959 } | |
| 22960 | |
| 22961 keySeq = &(matcher->keySeqs[pos]); | |
| 22962 if (*keySeq == NULL) { | |
| 22963 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) | |
| 22964 goto selector_key_error; | |
| 22965 else | |
| 22966 goto selector_leave; | |
| 22967 } | |
| 22968 | |
| 22969 for (i = 0; i < nbKeys; i++) { | |
| 22970 if ((*keySeq)[i] == NULL) { | |
| 22971 /* | |
| 22972 * Not qualified, if not all fields did resolve. | |
| 22973 */ | |
| 22974 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) { | |
| 22975 /* | |
| 22976 * All fields of a "key" IDC must resolve. | |
| 22977 */ | |
| 22978 goto selector_key_error; | |
| 22979 } | |
| 22980 goto selector_leave; | |
| 22981 } | |
| 22982 } | |
| 22983 /* | |
| 22984 * All fields did resolve. | |
| 22985 */ | |
| 22986 | |
| 22987 /* | |
| 22988 * 4.1 If the {identity-constraint category} is unique(/key), | |
| 22989 * then no two members of the `qualified node set` have | |
| 22990 * `key-sequences` whose members are pairwise equal, as | |
| 22991 * defined by Equal in [XML Schemas: Datatypes]. | |
| 22992 * | |
| 22993 * Get the IDC binding from the matcher and check for | |
| 22994 * duplicate key-sequences. | |
| 22995 */ | |
| 22996 #if 0 | |
| 22997 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher); | |
| 22998 #endif | |
| 22999 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher); | |
| 23000 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) && | |
| 23001 (targets->nbItems != 0)) { | |
| 23002 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq; | |
| 23003 | |
| 23004 i = 0; | |
| 23005 res = 0; | |
| 23006 /* | |
| 23007 * Compare the key-sequences, key by key. | |
| 23008 */ | |
| 23009 do { | |
| 23010 bkeySeq = | |
| 23011 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys; | |
| 23012 for (j = 0; j < nbKeys; j++) { | |
| 23013 ckey = (*keySeq)[j]; | |
| 23014 bkey = bkeySeq[j]; | |
| 23015 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val); | |
| 23016 if (res == -1) { | |
| 23017 return (-1); | |
| 23018 } else if (res == 0) { | |
| 23019 /* | |
| 23020 * One of the keys differs, so the key-sequence | |
| 23021 * won't be equal; get out. | |
| 23022 */ | |
| 23023 break; | |
| 23024 } | |
| 23025 } | |
| 23026 if (res == 1) { | |
| 23027 /* | |
| 23028 * Duplicate key-sequence found. | |
| 23029 */ | |
| 23030 break; | |
| 23031 } | |
| 23032 i++; | |
| 23033 } while (i < targets->nbItems); | |
| 23034 if (i != targets->nbItems) { | |
| 23035 xmlChar *str = NULL, *strB = NULL; | |
| 23036 /* | |
| 23037 * TODO: Try to report the key-sequence. | |
| 23038 */ | |
| 23039 xmlSchemaCustomErr(ACTXT_CAST vctxt, | |
| 23040 XML_SCHEMAV_CVC_IDC, NULL, | |
| 23041 WXS_BASIC_CAST idc, | |
| 23042 "Duplicate key-sequence %s in %s", | |
| 23043 xmlSchemaFormatIDCKeySequence(vctxt, &str, | |
| 23044 (*keySeq), nbKeys), | |
| 23045 xmlSchemaGetIDCDesignation(&strB, idc)); | |
| 23046 FREE_AND_NULL(str); | |
| 23047 FREE_AND_NULL(strB); | |
| 23048 goto selector_leave; | |
| 23049 } | |
| 23050 } | |
| 23051 /* | |
| 23052 * Add a node-table item to the IDC binding. | |
| 23053 */ | |
| 23054 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc( | |
| 23055 sizeof(xmlSchemaPSVIIDCNode)); | |
| 23056 if (ntItem == NULL) { | |
| 23057 xmlSchemaVErrMemory(NULL, | |
| 23058 "allocating an IDC node-table item", NULL); | |
| 23059 xmlFree(*keySeq); | |
| 23060 *keySeq = NULL; | |
| 23061 return(-1); | |
| 23062 } | |
| 23063 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode)); | |
| 23064 | |
| 23065 /* | |
| 23066 * Store the node-table item in a global list. | |
| 23067 */ | |
| 23068 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) { | |
| 23069 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) { | |
| 23070 xmlFree(ntItem); | |
| 23071 xmlFree(*keySeq); | |
| 23072 *keySeq = NULL; | |
| 23073 return (-1); | |
| 23074 } | |
| 23075 ntItem->nodeQNameID = -1; | |
| 23076 } else { | |
| 23077 /* | |
| 23078 * Save a cached QName for this node on the IDC node, to be | |
| 23079 * able to report it, even if the node is not saved. | |
| 23080 */ | |
| 23081 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt, | |
| 23082 vctxt->inode->localName, vctxt->inode->nsName); | |
| 23083 if (ntItem->nodeQNameID == -1) { | |
| 23084 xmlFree(ntItem); | |
| 23085 xmlFree(*keySeq); | |
| 23086 *keySeq = NULL; | |
| 23087 return (-1); | |
| 23088 } | |
| 23089 } | |
| 23090 /* | |
| 23091 * Init the node-table item: Save the node, position and | |
| 23092 * consume the key-sequence. | |
| 23093 */ | |
| 23094 ntItem->node = vctxt->node; | |
| 23095 ntItem->nodeLine = vctxt->inode->nodeLine; | |
| 23096 ntItem->keys = *keySeq; | |
| 23097 *keySeq = NULL; | |
| 23098 #if 0 | |
| 23099 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) | |
| 23100 #endif | |
| 23101 if (xmlSchemaItemListAdd(targets, ntItem) == -1) { | |
| 23102 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) { | |
| 23103 /* | |
| 23104 * Free the item, since keyref items won't be | |
| 23105 * put on a global list. | |
| 23106 */ | |
| 23107 xmlFree(ntItem->keys); | |
| 23108 xmlFree(ntItem); | |
| 23109 } | |
| 23110 return (-1); | |
| 23111 } | |
| 23112 | |
| 23113 goto selector_leave; | |
| 23114 selector_key_error: | |
| 23115 { | |
| 23116 xmlChar *str = NULL; | |
| 23117 /* | |
| 23118 * 4.2.1 (KEY) The `target node set` and the | |
| 23119 * `qualified node set` are equal, that is, every | |
| 23120 * member of the `target node set` is also a member | |
| 23121 * of the `qualified node set` and vice versa. | |
| 23122 */ | |
| 23123 xmlSchemaCustomErr(ACTXT_CAST vctxt, | |
| 23124 XML_SCHEMAV_CVC_IDC, NULL, | |
| 23125 WXS_BASIC_CAST idc, | |
| 23126 "Not all fields of %s evaluate to a node", | |
| 23127 xmlSchemaGetIDCDesignation(&str, idc), NULL); | |
| 23128 FREE_AND_NULL(str); | |
| 23129 } | |
| 23130 selector_leave: | |
| 23131 /* | |
| 23132 * Free the key-sequence if not added to the IDC table. | |
| 23133 */ | |
| 23134 if ((keySeq != NULL) && (*keySeq != NULL)) { | |
| 23135 xmlFree(*keySeq); | |
| 23136 *keySeq = NULL; | |
| 23137 } | |
| 23138 } /* if selector */ | |
| 23139 | |
| 23140 sto->nbHistory--; | |
| 23141 | |
| 23142 deregister_check: | |
| 23143 /* | |
| 23144 * Deregister state objects if they reach the depth of creation. | |
| 23145 */ | |
| 23146 if ((sto->nbHistory == 0) && (sto->depth == depth)) { | |
| 23147 #ifdef DEBUG_IDC | |
| 23148 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n", | |
| 23149 sto->sel->xpath); | |
| 23150 #endif | |
| 23151 if (vctxt->xpathStates != sto) { | |
| 23152 VERROR_INT("xmlSchemaXPathProcessHistory", | |
| 23153 "The state object to be removed is not the first " | |
| 23154 "in the list"); | |
| 23155 } | |
| 23156 nextsto = sto->next; | |
| 23157 /* | |
| 23158 * Unlink from the list of active XPath state objects. | |
| 23159 */ | |
| 23160 vctxt->xpathStates = sto->next; | |
| 23161 sto->next = vctxt->xpathStatePool; | |
| 23162 /* | |
| 23163 * Link it to the pool of reusable state objects. | |
| 23164 */ | |
| 23165 vctxt->xpathStatePool = sto; | |
| 23166 sto = nextsto; | |
| 23167 } else | |
| 23168 sto = sto->next; | |
| 23169 } /* while (sto != NULL) */ | |
| 23170 return (0); | |
| 23171 } | |
| 23172 | |
| 23173 /** | |
| 23174 * xmlSchemaIDCRegisterMatchers: | |
| 23175 * @vctxt: the WXS validation context | |
| 23176 * @elemDecl: the element declaration | |
| 23177 * | |
| 23178 * Creates helper objects to evaluate IDC selectors/fields | |
| 23179 * successively. | |
| 23180 * | |
| 23181 * Returns 0 if OK and -1 on internal errors. | |
| 23182 */ | |
| 23183 static int | |
| 23184 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt, | |
| 23185 xmlSchemaElementPtr elemDecl) | |
| 23186 { | |
| 23187 xmlSchemaIDCMatcherPtr matcher, last = NULL; | |
| 23188 xmlSchemaIDCPtr idc, refIdc; | |
| 23189 xmlSchemaIDCAugPtr aidc; | |
| 23190 | |
| 23191 idc = (xmlSchemaIDCPtr) elemDecl->idcs; | |
| 23192 if (idc == NULL) | |
| 23193 return (0); | |
| 23194 | |
| 23195 #ifdef DEBUG_IDC | |
| 23196 { | |
| 23197 xmlChar *str = NULL; | |
| 23198 xmlGenericError(xmlGenericErrorContext, | |
| 23199 "IDC: REGISTER on %s, depth %d\n", | |
| 23200 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName, | |
| 23201 vctxt->inode->localName), vctxt->depth); | |
| 23202 FREE_AND_NULL(str) | |
| 23203 } | |
| 23204 #endif | |
| 23205 if (vctxt->inode->idcMatchers != NULL) { | |
| 23206 VERROR_INT("xmlSchemaIDCRegisterMatchers", | |
| 23207 "The chain of IDC matchers is expected to be empty"); | |
| 23208 return (-1); | |
| 23209 } | |
| 23210 do { | |
| 23211 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) { | |
| 23212 /* | |
| 23213 * Since IDCs bubbles are expensive we need to know the | |
| 23214 * depth at which the bubbles should stop; this will be | |
| 23215 * the depth of the top-most keyref IDC. If no keyref | |
| 23216 * references a key/unique IDC, the keyrefDepth will | |
| 23217 * be -1, indicating that no bubbles are needed. | |
| 23218 */ | |
| 23219 refIdc = (xmlSchemaIDCPtr) idc->ref->item; | |
| 23220 if (refIdc != NULL) { | |
| 23221 /* | |
| 23222 * Remember that we have keyrefs on this node. | |
| 23223 */ | |
| 23224 vctxt->inode->hasKeyrefs = 1; | |
| 23225 /* | |
| 23226 * Lookup the referenced augmented IDC info. | |
| 23227 */ | |
| 23228 aidc = vctxt->aidcs; | |
| 23229 while (aidc != NULL) { | |
| 23230 if (aidc->def == refIdc) | |
| 23231 break; | |
| 23232 aidc = aidc->next; | |
| 23233 } | |
| 23234 if (aidc == NULL) { | |
| 23235 VERROR_INT("xmlSchemaIDCRegisterMatchers", | |
| 23236 "Could not find an augmented IDC item for an IDC " | |
| 23237 "definition"); | |
| 23238 return (-1); | |
| 23239 } | |
| 23240 if ((aidc->keyrefDepth == -1) || | |
| 23241 (vctxt->depth < aidc->keyrefDepth)) | |
| 23242 aidc->keyrefDepth = vctxt->depth; | |
| 23243 } | |
| 23244 } | |
| 23245 /* | |
| 23246 * Lookup the augmented IDC item for the IDC definition. | |
| 23247 */ | |
| 23248 aidc = vctxt->aidcs; | |
| 23249 while (aidc != NULL) { | |
| 23250 if (aidc->def == idc) | |
| 23251 break; | |
| 23252 aidc = aidc->next; | |
| 23253 } | |
| 23254 if (aidc == NULL) { | |
| 23255 VERROR_INT("xmlSchemaIDCRegisterMatchers", | |
| 23256 "Could not find an augmented IDC item for an IDC definition"); | |
| 23257 return (-1); | |
| 23258 } | |
| 23259 /* | |
| 23260 * Create an IDC matcher for every IDC definition. | |
| 23261 */ | |
| 23262 if (vctxt->idcMatcherCache != NULL) { | |
| 23263 /* | |
| 23264 * Reuse a cached matcher. | |
| 23265 */ | |
| 23266 matcher = vctxt->idcMatcherCache; | |
| 23267 vctxt->idcMatcherCache = matcher->nextCached; | |
| 23268 matcher->nextCached = NULL; | |
| 23269 } else { | |
| 23270 matcher = (xmlSchemaIDCMatcherPtr) | |
| 23271 xmlMalloc(sizeof(xmlSchemaIDCMatcher)); | |
| 23272 if (matcher == NULL) { | |
| 23273 xmlSchemaVErrMemory(vctxt, | |
| 23274 "allocating an IDC matcher", NULL); | |
| 23275 return (-1); | |
| 23276 } | |
| 23277 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher)); | |
| 23278 } | |
| 23279 if (last == NULL) | |
| 23280 vctxt->inode->idcMatchers = matcher; | |
| 23281 else | |
| 23282 last->next = matcher; | |
| 23283 last = matcher; | |
| 23284 | |
| 23285 matcher->type = IDC_MATCHER; | |
| 23286 matcher->depth = vctxt->depth; | |
| 23287 matcher->aidc = aidc; | |
| 23288 matcher->idcType = aidc->def->type; | |
| 23289 #ifdef DEBUG_IDC | |
| 23290 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n"); | |
| 23291 #endif | |
| 23292 /* | |
| 23293 * Init the automaton state object. | |
| 23294 */ | |
| 23295 if (xmlSchemaIDCAddStateObject(vctxt, matcher, | |
| 23296 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1) | |
| 23297 return (-1); | |
| 23298 | |
| 23299 idc = idc->next; | |
| 23300 } while (idc != NULL); | |
| 23301 return (0); | |
| 23302 } | |
| 23303 | |
| 23304 static int | |
| 23305 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt, | |
| 23306 xmlSchemaNodeInfoPtr ielem) | |
| 23307 { | |
| 23308 xmlSchemaPSVIIDCBindingPtr bind; | |
| 23309 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable; | |
| 23310 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys; | |
| 23311 xmlSchemaPSVIIDCNodePtr *targets, *dupls; | |
| 23312 | |
| 23313 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers; | |
| 23314 /* vctxt->createIDCNodeTables */ | |
| 23315 while (matcher != NULL) { | |
| 23316 /* | |
| 23317 * Skip keyref IDCs and empty IDC target-lists. | |
| 23318 */ | |
| 23319 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) || | |
| 23320 WXS_ILIST_IS_EMPTY(matcher->targets)) | |
| 23321 { | |
| 23322 matcher = matcher->next; | |
| 23323 continue; | |
| 23324 } | |
| 23325 /* | |
| 23326 * If we _want_ the IDC node-table to be created in any case | |
| 23327 * then do so. Otherwise create them only if keyrefs need them. | |
| 23328 */ | |
| 23329 if ((! vctxt->createIDCNodeTables) && | |
| 23330 ((matcher->aidc->keyrefDepth == -1) || | |
| 23331 (matcher->aidc->keyrefDepth > vctxt->depth))) | |
| 23332 { | |
| 23333 matcher = matcher->next; | |
| 23334 continue; | |
| 23335 } | |
| 23336 /* | |
| 23337 * Get/create the IDC binding on this element for the IDC definition. | |
| 23338 */ | |
| 23339 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher); | |
| 23340 | |
| 23341 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) { | |
| 23342 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items; | |
| 23343 nbDupls = bind->dupls->nbItems; | |
| 23344 } else { | |
| 23345 dupls = NULL; | |
| 23346 nbDupls = 0; | |
| 23347 } | |
| 23348 if (bind->nodeTable != NULL) { | |
| 23349 nbNodeTable = bind->nbNodes; | |
| 23350 } else { | |
| 23351 nbNodeTable = 0; | |
| 23352 } | |
| 23353 | |
| 23354 if ((nbNodeTable == 0) && (nbDupls == 0)) { | |
| 23355 /* | |
| 23356 * Transfer all IDC target-nodes to the IDC node-table. | |
| 23357 */ | |
| 23358 bind->nodeTable = | |
| 23359 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items; | |
| 23360 bind->sizeNodes = matcher->targets->sizeItems; | |
| 23361 bind->nbNodes = matcher->targets->nbItems; | |
| 23362 | |
| 23363 matcher->targets->items = NULL; | |
| 23364 matcher->targets->sizeItems = 0; | |
| 23365 matcher->targets->nbItems = 0; | |
| 23366 } else { | |
| 23367 /* | |
| 23368 * Compare the key-sequences and add to the IDC node-table. | |
| 23369 */ | |
| 23370 nbTargets = matcher->targets->nbItems; | |
| 23371 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items; | |
| 23372 nbFields = matcher->aidc->def->nbFields; | |
| 23373 i = 0; | |
| 23374 do { | |
| 23375 keys = targets[i]->keys; | |
| 23376 if (nbDupls) { | |
| 23377 /* | |
| 23378 * Search in already found duplicates first. | |
| 23379 */ | |
| 23380 j = 0; | |
| 23381 do { | |
| 23382 if (nbFields == 1) { | |
| 23383 res = xmlSchemaAreValuesEqual(keys[0]->val, | |
| 23384 dupls[j]->keys[0]->val); | |
| 23385 if (res == -1) | |
| 23386 goto internal_error; | |
| 23387 if (res == 1) { | |
| 23388 /* | |
| 23389 * Equal key-sequence. | |
| 23390 */ | |
| 23391 goto next_target; | |
| 23392 } | |
| 23393 } else { | |
| 23394 res = 0; | |
| 23395 ntkeys = dupls[j]->keys; | |
| 23396 for (k = 0; k < nbFields; k++) { | |
| 23397 res = xmlSchemaAreValuesEqual(keys[k]->val, | |
| 23398 ntkeys[k]->val); | |
| 23399 if (res == -1) | |
| 23400 goto internal_error; | |
| 23401 if (res == 0) { | |
| 23402 /* | |
| 23403 * One of the keys differs. | |
| 23404 */ | |
| 23405 break; | |
| 23406 } | |
| 23407 } | |
| 23408 if (res == 1) { | |
| 23409 /* | |
| 23410 * Equal key-sequence found. | |
| 23411 */ | |
| 23412 goto next_target; | |
| 23413 } | |
| 23414 } | |
| 23415 j++; | |
| 23416 } while (j < nbDupls); | |
| 23417 } | |
| 23418 if (nbNodeTable) { | |
| 23419 j = 0; | |
| 23420 do { | |
| 23421 if (nbFields == 1) { | |
| 23422 res = xmlSchemaAreValuesEqual(keys[0]->val, | |
| 23423 bind->nodeTable[j]->keys[0]->val); | |
| 23424 if (res == -1) | |
| 23425 goto internal_error; | |
| 23426 if (res == 0) { | |
| 23427 /* | |
| 23428 * The key-sequence differs. | |
| 23429 */ | |
| 23430 goto next_node_table_entry; | |
| 23431 } | |
| 23432 } else { | |
| 23433 res = 0; | |
| 23434 ntkeys = bind->nodeTable[j]->keys; | |
| 23435 for (k = 0; k < nbFields; k++) { | |
| 23436 res = xmlSchemaAreValuesEqual(keys[k]->val, | |
| 23437 ntkeys[k]->val); | |
| 23438 if (res == -1) | |
| 23439 goto internal_error; | |
| 23440 if (res == 0) { | |
| 23441 /* | |
| 23442 * One of the keys differs. | |
| 23443 */ | |
| 23444 goto next_node_table_entry; | |
| 23445 } | |
| 23446 } | |
| 23447 } | |
| 23448 /* | |
| 23449 * Add the duplicate to the list of duplicates. | |
| 23450 */ | |
| 23451 if (bind->dupls == NULL) { | |
| 23452 bind->dupls = xmlSchemaItemListCreate(); | |
| 23453 if (bind->dupls == NULL) | |
| 23454 goto internal_error; | |
| 23455 } | |
| 23456 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]
) == -1) | |
| 23457 goto internal_error; | |
| 23458 /* | |
| 23459 * Remove the duplicate entry from the IDC node-table. | |
| 23460 */ | |
| 23461 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1]; | |
| 23462 bind->nbNodes--; | |
| 23463 | |
| 23464 goto next_target; | |
| 23465 | |
| 23466 next_node_table_entry: | |
| 23467 j++; | |
| 23468 } while (j < nbNodeTable); | |
| 23469 } | |
| 23470 /* | |
| 23471 * If everything is fine, then add the IDC target-node to | |
| 23472 * the IDC node-table. | |
| 23473 */ | |
| 23474 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1) | |
| 23475 goto internal_error; | |
| 23476 | |
| 23477 next_target: | |
| 23478 i++; | |
| 23479 } while (i < nbTargets); | |
| 23480 } | |
| 23481 matcher = matcher->next; | |
| 23482 } | |
| 23483 return(0); | |
| 23484 | |
| 23485 internal_error: | |
| 23486 return(-1); | |
| 23487 } | |
| 23488 | |
| 23489 /** | |
| 23490 * xmlSchemaBubbleIDCNodeTables: | |
| 23491 * @depth: the current tree depth | |
| 23492 * | |
| 23493 * Merges IDC bindings of an element at @depth into the corresponding IDC | |
| 23494 * bindings of its parent element. If a duplicate note-table entry is found, | |
| 23495 * both, the parent node-table entry and child entry are discarded from the | |
| 23496 * node-table of the parent. | |
| 23497 * | |
| 23498 * Returns 0 if OK and -1 on internal errors. | |
| 23499 */ | |
| 23500 static int | |
| 23501 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt) | |
| 23502 { | |
| 23503 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */ | |
| 23504 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings
. */ | |
| 23505 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-tab
le entries. */ | |
| 23506 xmlSchemaIDCAugPtr aidc; | |
| 23507 int i, j, k, ret = 0, nbFields, oldNum, oldDupls; | |
| 23508 | |
| 23509 bind = vctxt->inode->idcTable; | |
| 23510 if (bind == NULL) { | |
| 23511 /* Fine, no table, no bubbles. */ | |
| 23512 return (0); | |
| 23513 } | |
| 23514 | |
| 23515 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable); | |
| 23516 /* | |
| 23517 * Walk all bindings; create new or add to existing bindings. | |
| 23518 * Remove duplicate key-sequences. | |
| 23519 */ | |
| 23520 while (bind != NULL) { | |
| 23521 | |
| 23522 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls)) | |
| 23523 goto next_binding; | |
| 23524 /* | |
| 23525 * Check if the key/unique IDC table needs to be bubbled. | |
| 23526 */ | |
| 23527 if (! vctxt->createIDCNodeTables) { | |
| 23528 aidc = vctxt->aidcs; | |
| 23529 do { | |
| 23530 if (aidc->def == bind->definition) { | |
| 23531 if ((aidc->keyrefDepth == -1) || | |
| 23532 (aidc->keyrefDepth >= vctxt->depth)) { | |
| 23533 goto next_binding; | |
| 23534 } | |
| 23535 break; | |
| 23536 } | |
| 23537 aidc = aidc->next; | |
| 23538 } while (aidc != NULL); | |
| 23539 } | |
| 23540 | |
| 23541 if (parTable != NULL) | |
| 23542 parBind = *parTable; | |
| 23543 /* | |
| 23544 * Search a matching parent binding for the | |
| 23545 * IDC definition. | |
| 23546 */ | |
| 23547 while (parBind != NULL) { | |
| 23548 if (parBind->definition == bind->definition) | |
| 23549 break; | |
| 23550 parBind = parBind->next; | |
| 23551 } | |
| 23552 | |
| 23553 if (parBind != NULL) { | |
| 23554 /* | |
| 23555 * Compare every node-table entry of the child node, | |
| 23556 * i.e. the key-sequence within, ... | |
| 23557 */ | |
| 23558 oldNum = parBind->nbNodes; /* Skip newly added items. */ | |
| 23559 | |
| 23560 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) { | |
| 23561 oldDupls = parBind->dupls->nbItems; | |
| 23562 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items; | |
| 23563 } else { | |
| 23564 dupls = NULL; | |
| 23565 oldDupls = 0; | |
| 23566 } | |
| 23567 | |
| 23568 parNodes = parBind->nodeTable; | |
| 23569 nbFields = bind->definition->nbFields; | |
| 23570 | |
| 23571 for (i = 0; i < bind->nbNodes; i++) { | |
| 23572 node = bind->nodeTable[i]; | |
| 23573 if (node == NULL) | |
| 23574 continue; | |
| 23575 /* | |
| 23576 * ...with every key-sequence of the parent node, already | |
| 23577 * evaluated to be a duplicate key-sequence. | |
| 23578 */ | |
| 23579 if (oldDupls) { | |
| 23580 j = 0; | |
| 23581 while (j < oldDupls) { | |
| 23582 if (nbFields == 1) { | |
| 23583 ret = xmlSchemaAreValuesEqual( | |
| 23584 node->keys[0]->val, | |
| 23585 dupls[j]->keys[0]->val); | |
| 23586 if (ret == -1) | |
| 23587 goto internal_error; | |
| 23588 if (ret == 0) { | |
| 23589 j++; | |
| 23590 continue; | |
| 23591 } | |
| 23592 } else { | |
| 23593 parNode = dupls[j]; | |
| 23594 for (k = 0; k < nbFields; k++) { | |
| 23595 ret = xmlSchemaAreValuesEqual( | |
| 23596 node->keys[k]->val, | |
| 23597 parNode->keys[k]->val); | |
| 23598 if (ret == -1) | |
| 23599 goto internal_error; | |
| 23600 if (ret == 0) | |
| 23601 break; | |
| 23602 } | |
| 23603 } | |
| 23604 if (ret == 1) | |
| 23605 /* Duplicate found. */ | |
| 23606 break; | |
| 23607 j++; | |
| 23608 } | |
| 23609 if (j != oldDupls) { | |
| 23610 /* Duplicate found. Skip this entry. */ | |
| 23611 continue; | |
| 23612 } | |
| 23613 } | |
| 23614 /* | |
| 23615 * ... and with every key-sequence of the parent node. | |
| 23616 */ | |
| 23617 if (oldNum) { | |
| 23618 j = 0; | |
| 23619 while (j < oldNum) { | |
| 23620 parNode = parNodes[j]; | |
| 23621 if (nbFields == 1) { | |
| 23622 ret = xmlSchemaAreValuesEqual( | |
| 23623 node->keys[0]->val, | |
| 23624 parNode->keys[0]->val); | |
| 23625 if (ret == -1) | |
| 23626 goto internal_error; | |
| 23627 if (ret == 0) { | |
| 23628 j++; | |
| 23629 continue; | |
| 23630 } | |
| 23631 } else { | |
| 23632 for (k = 0; k < nbFields; k++) { | |
| 23633 ret = xmlSchemaAreValuesEqual( | |
| 23634 node->keys[k]->val, | |
| 23635 parNode->keys[k]->val); | |
| 23636 if (ret == -1) | |
| 23637 goto internal_error; | |
| 23638 if (ret == 0) | |
| 23639 break; | |
| 23640 } | |
| 23641 } | |
| 23642 if (ret == 1) | |
| 23643 /* Duplicate found. */ | |
| 23644 break; | |
| 23645 j++; | |
| 23646 } | |
| 23647 if (j != oldNum) { | |
| 23648 /* | |
| 23649 * Handle duplicates. Move the duplicate in | |
| 23650 * the parent's node-table to the list of | |
| 23651 * duplicates. | |
| 23652 */ | |
| 23653 oldNum--; | |
| 23654 parBind->nbNodes--; | |
| 23655 /* | |
| 23656 * Move last old item to pos of duplicate. | |
| 23657 */ | |
| 23658 parNodes[j] = parNodes[oldNum]; | |
| 23659 | |
| 23660 if (parBind->nbNodes != oldNum) { | |
| 23661 /* | |
| 23662 * If new items exist, move last new item to | |
| 23663 * last of old items. | |
| 23664 */ | |
| 23665 parNodes[oldNum] = | |
| 23666 parNodes[parBind->nbNodes]; | |
| 23667 } | |
| 23668 if (parBind->dupls == NULL) { | |
| 23669 parBind->dupls = xmlSchemaItemListCreate(); | |
| 23670 if (parBind->dupls == NULL) | |
| 23671 goto internal_error; | |
| 23672 } | |
| 23673 xmlSchemaItemListAdd(parBind->dupls, parNode); | |
| 23674 } else { | |
| 23675 /* | |
| 23676 * Add the node-table entry (node and key-sequence) of | |
| 23677 * the child node to the node table of the parent node. | |
| 23678 */ | |
| 23679 if (parBind->nodeTable == NULL) { | |
| 23680 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) | |
| 23681 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr)); | |
| 23682 if (parBind->nodeTable == NULL) { | |
| 23683 xmlSchemaVErrMemory(NULL, | |
| 23684 "allocating IDC list of node-table items", N
ULL); | |
| 23685 goto internal_error; | |
| 23686 } | |
| 23687 parBind->sizeNodes = 1; | |
| 23688 } else if (parBind->nbNodes >= parBind->sizeNodes) { | |
| 23689 parBind->sizeNodes *= 2; | |
| 23690 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) | |
| 23691 xmlRealloc(parBind->nodeTable, parBind->sizeNode
s * | |
| 23692 sizeof(xmlSchemaPSVIIDCNodePtr)); | |
| 23693 if (parBind->nodeTable == NULL) { | |
| 23694 xmlSchemaVErrMemory(NULL, | |
| 23695 "re-allocating IDC list of node-table items"
, NULL); | |
| 23696 goto internal_error; | |
| 23697 } | |
| 23698 } | |
| 23699 parNodes = parBind->nodeTable; | |
| 23700 /* | |
| 23701 * Append the new node-table entry to the 'new node-table | |
| 23702 * entries' section. | |
| 23703 */ | |
| 23704 parNodes[parBind->nbNodes++] = node; | |
| 23705 } | |
| 23706 | |
| 23707 } | |
| 23708 | |
| 23709 } | |
| 23710 } else { | |
| 23711 /* | |
| 23712 * No binding for the IDC was found: create a new one and | |
| 23713 * copy all node-tables. | |
| 23714 */ | |
| 23715 parBind = xmlSchemaIDCNewBinding(bind->definition); | |
| 23716 if (parBind == NULL) | |
| 23717 goto internal_error; | |
| 23718 | |
| 23719 /* | |
| 23720 * TODO: Hmm, how to optimize the initial number of | |
| 23721 * allocated entries? | |
| 23722 */ | |
| 23723 if (bind->nbNodes != 0) { | |
| 23724 /* | |
| 23725 * Add all IDC node-table entries. | |
| 23726 */ | |
| 23727 if (! vctxt->psviExposeIDCNodeTables) { | |
| 23728 /* | |
| 23729 * Just move the entries. | |
| 23730 * NOTE: this is quite save here, since | |
| 23731 * all the keyref lookups have already been | |
| 23732 * performed. | |
| 23733 */ | |
| 23734 parBind->nodeTable = bind->nodeTable; | |
| 23735 bind->nodeTable = NULL; | |
| 23736 parBind->sizeNodes = bind->sizeNodes; | |
| 23737 bind->sizeNodes = 0; | |
| 23738 parBind->nbNodes = bind->nbNodes; | |
| 23739 bind->nbNodes = 0; | |
| 23740 } else { | |
| 23741 /* | |
| 23742 * Copy the entries. | |
| 23743 */ | |
| 23744 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) | |
| 23745 xmlMalloc(bind->nbNodes * | |
| 23746 sizeof(xmlSchemaPSVIIDCNodePtr)); | |
| 23747 if (parBind->nodeTable == NULL) { | |
| 23748 xmlSchemaVErrMemory(NULL, | |
| 23749 "allocating an array of IDC node-table " | |
| 23750 "items", NULL); | |
| 23751 xmlSchemaIDCFreeBinding(parBind); | |
| 23752 goto internal_error; | |
| 23753 } | |
| 23754 parBind->sizeNodes = bind->nbNodes; | |
| 23755 parBind->nbNodes = bind->nbNodes; | |
| 23756 memcpy(parBind->nodeTable, bind->nodeTable, | |
| 23757 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr)); | |
| 23758 } | |
| 23759 } | |
| 23760 if (bind->dupls) { | |
| 23761 /* | |
| 23762 * Move the duplicates. | |
| 23763 */ | |
| 23764 if (parBind->dupls != NULL) | |
| 23765 xmlSchemaItemListFree(parBind->dupls); | |
| 23766 parBind->dupls = bind->dupls; | |
| 23767 bind->dupls = NULL; | |
| 23768 } | |
| 23769 if (parTable != NULL) { | |
| 23770 if (*parTable == NULL) | |
| 23771 *parTable = parBind; | |
| 23772 else { | |
| 23773 parBind->next = *parTable; | |
| 23774 *parTable = parBind; | |
| 23775 } | |
| 23776 } | |
| 23777 } | |
| 23778 | |
| 23779 next_binding: | |
| 23780 bind = bind->next; | |
| 23781 } | |
| 23782 return (0); | |
| 23783 | |
| 23784 internal_error: | |
| 23785 return(-1); | |
| 23786 } | |
| 23787 | |
| 23788 /** | |
| 23789 * xmlSchemaCheckCVCIDCKeyRef: | |
| 23790 * @vctxt: the WXS validation context | |
| 23791 * @elemDecl: the element declaration | |
| 23792 * | |
| 23793 * Check the cvc-idc-keyref constraints. | |
| 23794 */ | |
| 23795 static int | |
| 23796 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt) | |
| 23797 { | |
| 23798 xmlSchemaIDCMatcherPtr matcher; | |
| 23799 xmlSchemaPSVIIDCBindingPtr bind; | |
| 23800 | |
| 23801 matcher = vctxt->inode->idcMatchers; | |
| 23802 /* | |
| 23803 * Find a keyref. | |
| 23804 */ | |
| 23805 while (matcher != NULL) { | |
| 23806 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) && | |
| 23807 matcher->targets && | |
| 23808 matcher->targets->nbItems) | |
| 23809 { | |
| 23810 int i, j, k, res, nbFields, hasDupls; | |
| 23811 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys; | |
| 23812 xmlSchemaPSVIIDCNodePtr refNode = NULL; | |
| 23813 | |
| 23814 nbFields = matcher->aidc->def->nbFields; | |
| 23815 | |
| 23816 /* | |
| 23817 * Find the IDC node-table for the referenced IDC key/unique. | |
| 23818 */ | |
| 23819 bind = vctxt->inode->idcTable; | |
| 23820 while (bind != NULL) { | |
| 23821 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item == | |
| 23822 bind->definition) | |
| 23823 break; | |
| 23824 bind = bind->next; | |
| 23825 } | |
| 23826 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0; | |
| 23827 /* | |
| 23828 * Search for a matching key-sequences. | |
| 23829 */ | |
| 23830 for (i = 0; i < matcher->targets->nbItems; i++) { | |
| 23831 res = 0; | |
| 23832 refNode = matcher->targets->items[i]; | |
| 23833 if (bind != NULL) { | |
| 23834 refKeys = refNode->keys; | |
| 23835 for (j = 0; j < bind->nbNodes; j++) { | |
| 23836 keys = bind->nodeTable[j]->keys; | |
| 23837 for (k = 0; k < nbFields; k++) { | |
| 23838 res = xmlSchemaAreValuesEqual(keys[k]->val, | |
| 23839 refKeys[k]->val); | |
| 23840 if (res == 0) | |
| 23841 break; | |
| 23842 else if (res == -1) { | |
| 23843 return (-1); | |
| 23844 } | |
| 23845 } | |
| 23846 if (res == 1) { | |
| 23847 /* | |
| 23848 * Match found. | |
| 23849 */ | |
| 23850 break; | |
| 23851 } | |
| 23852 } | |
| 23853 if ((res == 0) && hasDupls) { | |
| 23854 /* | |
| 23855 * Search in duplicates | |
| 23856 */ | |
| 23857 for (j = 0; j < bind->dupls->nbItems; j++) { | |
| 23858 keys = ((xmlSchemaPSVIIDCNodePtr) | |
| 23859 bind->dupls->items[j])->keys; | |
| 23860 for (k = 0; k < nbFields; k++) { | |
| 23861 res = xmlSchemaAreValuesEqual(keys[k]->val, | |
| 23862 refKeys[k]->val); | |
| 23863 if (res == 0) | |
| 23864 break; | |
| 23865 else if (res == -1) { | |
| 23866 return (-1); | |
| 23867 } | |
| 23868 } | |
| 23869 if (res == 1) { | |
| 23870 /* | |
| 23871 * Match in duplicates found. | |
| 23872 */ | |
| 23873 xmlChar *str = NULL, *strB = NULL; | |
| 23874 xmlSchemaKeyrefErr(vctxt, | |
| 23875 XML_SCHEMAV_CVC_IDC, refNode, | |
| 23876 (xmlSchemaTypePtr) matcher->aidc->def, | |
| 23877 "More than one match found for " | |
| 23878 "key-sequence %s of keyref '%s'", | |
| 23879 xmlSchemaFormatIDCKeySequence(vctxt, &str, | |
| 23880 refNode->keys, nbFields), | |
| 23881 xmlSchemaGetComponentQName(&strB, | |
| 23882 matcher->aidc->def)); | |
| 23883 FREE_AND_NULL(str); | |
| 23884 FREE_AND_NULL(strB); | |
| 23885 break; | |
| 23886 } | |
| 23887 } | |
| 23888 } | |
| 23889 } | |
| 23890 | |
| 23891 if (res == 0) { | |
| 23892 xmlChar *str = NULL, *strB = NULL; | |
| 23893 xmlSchemaKeyrefErr(vctxt, | |
| 23894 XML_SCHEMAV_CVC_IDC, refNode, | |
| 23895 (xmlSchemaTypePtr) matcher->aidc->def, | |
| 23896 "No match found for key-sequence %s of keyref '%s'", | |
| 23897 xmlSchemaFormatIDCKeySequence(vctxt, &str, | |
| 23898 refNode->keys, nbFields), | |
| 23899 xmlSchemaGetComponentQName(&strB, matcher->aidc->def)); | |
| 23900 FREE_AND_NULL(str); | |
| 23901 FREE_AND_NULL(strB); | |
| 23902 } | |
| 23903 } | |
| 23904 } | |
| 23905 matcher = matcher->next; | |
| 23906 } | |
| 23907 /* TODO: Return an error if any error encountered. */ | |
| 23908 return (0); | |
| 23909 } | |
| 23910 | |
| 23911 /************************************************************************ | |
| 23912 * * | |
| 23913 * XML Reader validation code * | |
| 23914 * * | |
| 23915 ************************************************************************/ | |
| 23916 | |
| 23917 static xmlSchemaAttrInfoPtr | |
| 23918 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt) | |
| 23919 { | |
| 23920 xmlSchemaAttrInfoPtr iattr; | |
| 23921 /* | |
| 23922 * Grow/create list of attribute infos. | |
| 23923 */ | |
| 23924 if (vctxt->attrInfos == NULL) { | |
| 23925 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *) | |
| 23926 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr)); | |
| 23927 vctxt->sizeAttrInfos = 1; | |
| 23928 if (vctxt->attrInfos == NULL) { | |
| 23929 xmlSchemaVErrMemory(vctxt, | |
| 23930 "allocating attribute info list", NULL); | |
| 23931 return (NULL); | |
| 23932 } | |
| 23933 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) { | |
| 23934 vctxt->sizeAttrInfos++; | |
| 23935 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *) | |
| 23936 xmlRealloc(vctxt->attrInfos, | |
| 23937 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr)); | |
| 23938 if (vctxt->attrInfos == NULL) { | |
| 23939 xmlSchemaVErrMemory(vctxt, | |
| 23940 "re-allocating attribute info list", NULL); | |
| 23941 return (NULL); | |
| 23942 } | |
| 23943 } else { | |
| 23944 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++]; | |
| 23945 if (iattr->localName != NULL) { | |
| 23946 VERROR_INT("xmlSchemaGetFreshAttrInfo", | |
| 23947 "attr info not cleared"); | |
| 23948 return (NULL); | |
| 23949 } | |
| 23950 iattr->nodeType = XML_ATTRIBUTE_NODE; | |
| 23951 return (iattr); | |
| 23952 } | |
| 23953 /* | |
| 23954 * Create an attribute info. | |
| 23955 */ | |
| 23956 iattr = (xmlSchemaAttrInfoPtr) | |
| 23957 xmlMalloc(sizeof(xmlSchemaAttrInfo)); | |
| 23958 if (iattr == NULL) { | |
| 23959 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL); | |
| 23960 return (NULL); | |
| 23961 } | |
| 23962 memset(iattr, 0, sizeof(xmlSchemaAttrInfo)); | |
| 23963 iattr->nodeType = XML_ATTRIBUTE_NODE; | |
| 23964 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr; | |
| 23965 | |
| 23966 return (iattr); | |
| 23967 } | |
| 23968 | |
| 23969 static int | |
| 23970 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt, | |
| 23971 xmlNodePtr attrNode, | |
| 23972 int nodeLine, | |
| 23973 const xmlChar *localName, | |
| 23974 const xmlChar *nsName, | |
| 23975 int ownedNames, | |
| 23976 xmlChar *value, | |
| 23977 int ownedValue) | |
| 23978 { | |
| 23979 xmlSchemaAttrInfoPtr attr; | |
| 23980 | |
| 23981 attr = xmlSchemaGetFreshAttrInfo(vctxt); | |
| 23982 if (attr == NULL) { | |
| 23983 VERROR_INT("xmlSchemaPushAttribute", | |
| 23984 "calling xmlSchemaGetFreshAttrInfo()"); | |
| 23985 return (-1); | |
| 23986 } | |
| 23987 attr->node = attrNode; | |
| 23988 attr->nodeLine = nodeLine; | |
| 23989 attr->state = XML_SCHEMAS_ATTR_UNKNOWN; | |
| 23990 attr->localName = localName; | |
| 23991 attr->nsName = nsName; | |
| 23992 if (ownedNames) | |
| 23993 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES; | |
| 23994 /* | |
| 23995 * Evaluate if it's an XSI attribute. | |
| 23996 */ | |
| 23997 if (nsName != NULL) { | |
| 23998 if (xmlStrEqual(localName, BAD_CAST "nil")) { | |
| 23999 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { | |
| 24000 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL; | |
| 24001 } | |
| 24002 } else if (xmlStrEqual(localName, BAD_CAST "type")) { | |
| 24003 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { | |
| 24004 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE; | |
| 24005 } | |
| 24006 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) { | |
| 24007 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { | |
| 24008 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC; | |
| 24009 } | |
| 24010 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation"))
{ | |
| 24011 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { | |
| 24012 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC; | |
| 24013 } | |
| 24014 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) { | |
| 24015 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS; | |
| 24016 } | |
| 24017 } | |
| 24018 attr->value = value; | |
| 24019 if (ownedValue) | |
| 24020 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; | |
| 24021 if (attr->metaType != 0) | |
| 24022 attr->state = XML_SCHEMAS_ATTR_META; | |
| 24023 return (0); | |
| 24024 } | |
| 24025 | |
| 24026 /** | |
| 24027 * xmlSchemaClearElemInfo: | |
| 24028 * @vctxt: the WXS validation context | |
| 24029 * @ielem: the element information item | |
| 24030 */ | |
| 24031 static void | |
| 24032 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt, | |
| 24033 xmlSchemaNodeInfoPtr ielem) | |
| 24034 { | |
| 24035 ielem->hasKeyrefs = 0; | |
| 24036 ielem->appliedXPath = 0; | |
| 24037 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) { | |
| 24038 FREE_AND_NULL(ielem->localName); | |
| 24039 FREE_AND_NULL(ielem->nsName); | |
| 24040 } else { | |
| 24041 ielem->localName = NULL; | |
| 24042 ielem->nsName = NULL; | |
| 24043 } | |
| 24044 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) { | |
| 24045 FREE_AND_NULL(ielem->value); | |
| 24046 } else { | |
| 24047 ielem->value = NULL; | |
| 24048 } | |
| 24049 if (ielem->val != NULL) { | |
| 24050 /* | |
| 24051 * PSVI TODO: Be careful not to free it when the value is | |
| 24052 * exposed via PSVI. | |
| 24053 */ | |
| 24054 xmlSchemaFreeValue(ielem->val); | |
| 24055 ielem->val = NULL; | |
| 24056 } | |
| 24057 if (ielem->idcMatchers != NULL) { | |
| 24058 /* | |
| 24059 * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers. | |
| 24060 * Does it work? | |
| 24061 */ | |
| 24062 xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers); | |
| 24063 #if 0 | |
| 24064 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers); | |
| 24065 #endif | |
| 24066 ielem->idcMatchers = NULL; | |
| 24067 } | |
| 24068 if (ielem->idcTable != NULL) { | |
| 24069 /* | |
| 24070 * OPTIMIZE TODO: Use a pool of IDC tables??. | |
| 24071 */ | |
| 24072 xmlSchemaIDCFreeIDCTable(ielem->idcTable); | |
| 24073 ielem->idcTable = NULL; | |
| 24074 } | |
| 24075 if (ielem->regexCtxt != NULL) { | |
| 24076 xmlRegFreeExecCtxt(ielem->regexCtxt); | |
| 24077 ielem->regexCtxt = NULL; | |
| 24078 } | |
| 24079 if (ielem->nsBindings != NULL) { | |
| 24080 xmlFree((xmlChar **)ielem->nsBindings); | |
| 24081 ielem->nsBindings = NULL; | |
| 24082 ielem->nbNsBindings = 0; | |
| 24083 ielem->sizeNsBindings = 0; | |
| 24084 } | |
| 24085 } | |
| 24086 | |
| 24087 /** | |
| 24088 * xmlSchemaGetFreshElemInfo: | |
| 24089 * @vctxt: the schema validation context | |
| 24090 * | |
| 24091 * Creates/reuses and initializes the element info item for | |
| 24092 * the currect tree depth. | |
| 24093 * | |
| 24094 * Returns the element info item or NULL on API or internal errors. | |
| 24095 */ | |
| 24096 static xmlSchemaNodeInfoPtr | |
| 24097 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt) | |
| 24098 { | |
| 24099 xmlSchemaNodeInfoPtr info = NULL; | |
| 24100 | |
| 24101 if (vctxt->depth > vctxt->sizeElemInfos) { | |
| 24102 VERROR_INT("xmlSchemaGetFreshElemInfo", | |
| 24103 "inconsistent depth encountered"); | |
| 24104 return (NULL); | |
| 24105 } | |
| 24106 if (vctxt->elemInfos == NULL) { | |
| 24107 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *) | |
| 24108 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr)); | |
| 24109 if (vctxt->elemInfos == NULL) { | |
| 24110 xmlSchemaVErrMemory(vctxt, | |
| 24111 "allocating the element info array", NULL); | |
| 24112 return (NULL); | |
| 24113 } | |
| 24114 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr)); | |
| 24115 vctxt->sizeElemInfos = 10; | |
| 24116 } else if (vctxt->sizeElemInfos <= vctxt->depth) { | |
| 24117 int i = vctxt->sizeElemInfos; | |
| 24118 | |
| 24119 vctxt->sizeElemInfos *= 2; | |
| 24120 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *) | |
| 24121 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos * | |
| 24122 sizeof(xmlSchemaNodeInfoPtr)); | |
| 24123 if (vctxt->elemInfos == NULL) { | |
| 24124 xmlSchemaVErrMemory(vctxt, | |
| 24125 "re-allocating the element info array", NULL); | |
| 24126 return (NULL); | |
| 24127 } | |
| 24128 /* | |
| 24129 * We need the new memory to be NULLed. | |
| 24130 * TODO: Use memset instead? | |
| 24131 */ | |
| 24132 for (; i < vctxt->sizeElemInfos; i++) | |
| 24133 vctxt->elemInfos[i] = NULL; | |
| 24134 } else | |
| 24135 info = vctxt->elemInfos[vctxt->depth]; | |
| 24136 | |
| 24137 if (info == NULL) { | |
| 24138 info = (xmlSchemaNodeInfoPtr) | |
| 24139 xmlMalloc(sizeof(xmlSchemaNodeInfo)); | |
| 24140 if (info == NULL) { | |
| 24141 xmlSchemaVErrMemory(vctxt, | |
| 24142 "allocating an element info", NULL); | |
| 24143 return (NULL); | |
| 24144 } | |
| 24145 vctxt->elemInfos[vctxt->depth] = info; | |
| 24146 } else { | |
| 24147 if (info->localName != NULL) { | |
| 24148 VERROR_INT("xmlSchemaGetFreshElemInfo", | |
| 24149 "elem info has not been cleared"); | |
| 24150 return (NULL); | |
| 24151 } | |
| 24152 } | |
| 24153 memset(info, 0, sizeof(xmlSchemaNodeInfo)); | |
| 24154 info->nodeType = XML_ELEMENT_NODE; | |
| 24155 info->depth = vctxt->depth; | |
| 24156 | |
| 24157 return (info); | |
| 24158 } | |
| 24159 | |
| 24160 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item; | |
| 24161 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth]; | |
| 24162 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1]; | |
| 24163 | |
| 24164 static int | |
| 24165 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt, | |
| 24166 xmlNodePtr node, | |
| 24167 xmlSchemaTypePtr type, | |
| 24168 xmlSchemaValType valType, | |
| 24169 const xmlChar * value, | |
| 24170 xmlSchemaValPtr val, | |
| 24171 unsigned long length, | |
| 24172 int fireErrors) | |
| 24173 { | |
| 24174 int ret, error = 0; | |
| 24175 | |
| 24176 xmlSchemaTypePtr tmpType; | |
| 24177 xmlSchemaFacetLinkPtr facetLink; | |
| 24178 xmlSchemaFacetPtr facet; | |
| 24179 unsigned long len = 0; | |
| 24180 xmlSchemaWhitespaceValueType ws; | |
| 24181 | |
| 24182 /* | |
| 24183 * In Libxml2, derived built-in types have currently no explicit facets. | |
| 24184 */ | |
| 24185 if (type->type == XML_SCHEMA_TYPE_BASIC) | |
| 24186 return (0); | |
| 24187 | |
| 24188 /* | |
| 24189 * NOTE: Do not jump away, if the facetSet of the given type is | |
| 24190 * empty: until now, "pattern" and "enumeration" facets of the | |
| 24191 * *base types* need to be checked as well. | |
| 24192 */ | |
| 24193 if (type->facetSet == NULL) | |
| 24194 goto pattern_and_enum; | |
| 24195 | |
| 24196 if (! WXS_IS_ATOMIC(type)) { | |
| 24197 if (WXS_IS_LIST(type)) | |
| 24198 goto WXS_IS_LIST; | |
| 24199 else | |
| 24200 goto pattern_and_enum; | |
| 24201 } | |
| 24202 | |
| 24203 /* | |
| 24204 * Whitespace handling is only of importance for string-based | |
| 24205 * types. | |
| 24206 */ | |
| 24207 tmpType = xmlSchemaGetPrimitiveType(type); | |
| 24208 if ((tmpType->builtInType == XML_SCHEMAS_STRING) || | |
| 24209 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) { | |
| 24210 ws = xmlSchemaGetWhiteSpaceFacetValue(type); | |
| 24211 } else | |
| 24212 ws = XML_SCHEMA_WHITESPACE_COLLAPSE; | |
| 24213 | |
| 24214 /* | |
| 24215 * If the value was not computed (for string or | |
| 24216 * anySimpleType based types), then use the provided | |
| 24217 * type. | |
| 24218 */ | |
| 24219 if (val != NULL) | |
| 24220 valType = xmlSchemaGetValType(val); | |
| 24221 | |
| 24222 ret = 0; | |
| 24223 for (facetLink = type->facetSet; facetLink != NULL; | |
| 24224 facetLink = facetLink->next) { | |
| 24225 /* | |
| 24226 * Skip the pattern "whiteSpace": it is used to | |
| 24227 * format the character content beforehand. | |
| 24228 */ | |
| 24229 switch (facetLink->facet->type) { | |
| 24230 case XML_SCHEMA_FACET_WHITESPACE: | |
| 24231 case XML_SCHEMA_FACET_PATTERN: | |
| 24232 case XML_SCHEMA_FACET_ENUMERATION: | |
| 24233 continue; | |
| 24234 case XML_SCHEMA_FACET_LENGTH: | |
| 24235 case XML_SCHEMA_FACET_MINLENGTH: | |
| 24236 case XML_SCHEMA_FACET_MAXLENGTH: | |
| 24237 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet, | |
| 24238 valType, value, val, &len, ws); | |
| 24239 break; | |
| 24240 default: | |
| 24241 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws, | |
| 24242 valType, value, val, ws); | |
| 24243 break; | |
| 24244 } | |
| 24245 if (ret < 0) { | |
| 24246 AERROR_INT("xmlSchemaValidateFacets", | |
| 24247 "validating against a atomic type facet"); | |
| 24248 return (-1); | |
| 24249 } else if (ret > 0) { | |
| 24250 if (fireErrors) | |
| 24251 xmlSchemaFacetErr(actxt, ret, node, | |
| 24252 value, len, type, facetLink->facet, NULL, NULL, NULL); | |
| 24253 else | |
| 24254 return (ret); | |
| 24255 if (error == 0) | |
| 24256 error = ret; | |
| 24257 } | |
| 24258 ret = 0; | |
| 24259 } | |
| 24260 | |
| 24261 WXS_IS_LIST: | |
| 24262 if (! WXS_IS_LIST(type)) | |
| 24263 goto pattern_and_enum; | |
| 24264 /* | |
| 24265 * "length", "minLength" and "maxLength" of list types. | |
| 24266 */ | |
| 24267 ret = 0; | |
| 24268 for (facetLink = type->facetSet; facetLink != NULL; | |
| 24269 facetLink = facetLink->next) { | |
| 24270 | |
| 24271 switch (facetLink->facet->type) { | |
| 24272 case XML_SCHEMA_FACET_LENGTH: | |
| 24273 case XML_SCHEMA_FACET_MINLENGTH: | |
| 24274 case XML_SCHEMA_FACET_MAXLENGTH: | |
| 24275 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet, | |
| 24276 value, length, NULL); | |
| 24277 break; | |
| 24278 default: | |
| 24279 continue; | |
| 24280 } | |
| 24281 if (ret < 0) { | |
| 24282 AERROR_INT("xmlSchemaValidateFacets", | |
| 24283 "validating against a list type facet"); | |
| 24284 return (-1); | |
| 24285 } else if (ret > 0) { | |
| 24286 if (fireErrors) | |
| 24287 xmlSchemaFacetErr(actxt, ret, node, | |
| 24288 value, length, type, facetLink->facet, NULL, NULL, NULL); | |
| 24289 else | |
| 24290 return (ret); | |
| 24291 if (error == 0) | |
| 24292 error = ret; | |
| 24293 } | |
| 24294 ret = 0; | |
| 24295 } | |
| 24296 | |
| 24297 pattern_and_enum: | |
| 24298 if (error >= 0) { | |
| 24299 int found = 0; | |
| 24300 /* | |
| 24301 * Process enumerations. Facet values are in the value space | |
| 24302 * of the defining type's base type. This seems to be a bug in the | |
| 24303 * XML Schema 1.0 spec. Use the whitespace type of the base type. | |
| 24304 * Only the first set of enumerations in the ancestor-or-self axis | |
| 24305 * is used for validation. | |
| 24306 */ | |
| 24307 ret = 0; | |
| 24308 tmpType = type; | |
| 24309 do { | |
| 24310 for (facet = tmpType->facets; facet != NULL; facet = facet->next) { | |
| 24311 if (facet->type != XML_SCHEMA_FACET_ENUMERATION) | |
| 24312 continue; | |
| 24313 found = 1; | |
| 24314 ret = xmlSchemaAreValuesEqual(facet->val, val); | |
| 24315 if (ret == 1) | |
| 24316 break; | |
| 24317 else if (ret < 0) { | |
| 24318 AERROR_INT("xmlSchemaValidateFacets", | |
| 24319 "validating against an enumeration facet"); | |
| 24320 return (-1); | |
| 24321 } | |
| 24322 } | |
| 24323 if (ret != 0) | |
| 24324 break; | |
| 24325 /* | |
| 24326 * Break on the first set of enumerations. Any additional | |
| 24327 * enumerations which might be existent on the ancestors | |
| 24328 * of the current type are restricted by this set; thus | |
| 24329 * *must* *not* be taken into account. | |
| 24330 */ | |
| 24331 if (found) | |
| 24332 break; | |
| 24333 tmpType = tmpType->baseType; | |
| 24334 } while ((tmpType != NULL) && | |
| 24335 (tmpType->type != XML_SCHEMA_TYPE_BASIC)); | |
| 24336 if (found && (ret == 0)) { | |
| 24337 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID; | |
| 24338 if (fireErrors) { | |
| 24339 xmlSchemaFacetErr(actxt, ret, node, | |
| 24340 value, 0, type, NULL, NULL, NULL, NULL); | |
| 24341 } else | |
| 24342 return (ret); | |
| 24343 if (error == 0) | |
| 24344 error = ret; | |
| 24345 } | |
| 24346 } | |
| 24347 | |
| 24348 if (error >= 0) { | |
| 24349 int found; | |
| 24350 /* | |
| 24351 * Process patters. Pattern facets are ORed at type level | |
| 24352 * and ANDed if derived. Walk the base type axis. | |
| 24353 */ | |
| 24354 tmpType = type; | |
| 24355 facet = NULL; | |
| 24356 do { | |
| 24357 found = 0; | |
| 24358 for (facetLink = tmpType->facetSet; facetLink != NULL; | |
| 24359 facetLink = facetLink->next) { | |
| 24360 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN) | |
| 24361 continue; | |
| 24362 found = 1; | |
| 24363 /* | |
| 24364 * NOTE that for patterns, @value needs to be the | |
| 24365 * normalized vaule. | |
| 24366 */ | |
| 24367 ret = xmlRegexpExec(facetLink->facet->regexp, value); | |
| 24368 if (ret == 1) | |
| 24369 break; | |
| 24370 else if (ret < 0) { | |
| 24371 AERROR_INT("xmlSchemaValidateFacets", | |
| 24372 "validating against a pattern facet"); | |
| 24373 return (-1); | |
| 24374 } else { | |
| 24375 /* | |
| 24376 * Save the last non-validating facet. | |
| 24377 */ | |
| 24378 facet = facetLink->facet; | |
| 24379 } | |
| 24380 } | |
| 24381 if (found && (ret != 1)) { | |
| 24382 ret = XML_SCHEMAV_CVC_PATTERN_VALID; | |
| 24383 if (fireErrors) { | |
| 24384 xmlSchemaFacetErr(actxt, ret, node, | |
| 24385 value, 0, type, facet, NULL, NULL, NULL); | |
| 24386 } else | |
| 24387 return (ret); | |
| 24388 if (error == 0) | |
| 24389 error = ret; | |
| 24390 break; | |
| 24391 } | |
| 24392 tmpType = tmpType->baseType; | |
| 24393 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC)); | |
| 24394 } | |
| 24395 | |
| 24396 return (error); | |
| 24397 } | |
| 24398 | |
| 24399 static xmlChar * | |
| 24400 xmlSchemaNormalizeValue(xmlSchemaTypePtr type, | |
| 24401 const xmlChar *value) | |
| 24402 { | |
| 24403 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) { | |
| 24404 case XML_SCHEMA_WHITESPACE_COLLAPSE: | |
| 24405 return (xmlSchemaCollapseString(value)); | |
| 24406 case XML_SCHEMA_WHITESPACE_REPLACE: | |
| 24407 return (xmlSchemaWhiteSpaceReplace(value)); | |
| 24408 default: | |
| 24409 return (NULL); | |
| 24410 } | |
| 24411 } | |
| 24412 | |
| 24413 static int | |
| 24414 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt, | |
| 24415 const xmlChar *value, | |
| 24416 xmlSchemaValPtr *val, | |
| 24417 int valNeeded) | |
| 24418 { | |
| 24419 int ret; | |
| 24420 const xmlChar *nsName; | |
| 24421 xmlChar *local, *prefix = NULL; | |
| 24422 | |
| 24423 ret = xmlValidateQName(value, 1); | |
| 24424 if (ret != 0) { | |
| 24425 if (ret == -1) { | |
| 24426 VERROR_INT("xmlSchemaValidateQName", | |
| 24427 "calling xmlValidateQName()"); | |
| 24428 return (-1); | |
| 24429 } | |
| 24430 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1); | |
| 24431 } | |
| 24432 /* | |
| 24433 * NOTE: xmlSplitQName2 will always return a duplicated | |
| 24434 * strings. | |
| 24435 */ | |
| 24436 local = xmlSplitQName2(value, &prefix); | |
| 24437 if (local == NULL) | |
| 24438 local = xmlStrdup(value); | |
| 24439 /* | |
| 24440 * OPTIMIZE TODO: Use flags for: | |
| 24441 * - is there any namespace binding? | |
| 24442 * - is there a default namespace? | |
| 24443 */ | |
| 24444 nsName = xmlSchemaLookupNamespace(vctxt, prefix); | |
| 24445 | |
| 24446 if (prefix != NULL) { | |
| 24447 xmlFree(prefix); | |
| 24448 /* | |
| 24449 * A namespace must be found if the prefix is | |
| 24450 * NOT NULL. | |
| 24451 */ | |
| 24452 if (nsName == NULL) { | |
| 24453 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; | |
| 24454 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL, | |
| 24455 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), | |
| 24456 "The QName value '%s' has no " | |
| 24457 "corresponding namespace declaration in " | |
| 24458 "scope", value, NULL); | |
| 24459 if (local != NULL) | |
| 24460 xmlFree(local); | |
| 24461 return (ret); | |
| 24462 } | |
| 24463 } | |
| 24464 if (valNeeded && val) { | |
| 24465 if (nsName != NULL) | |
| 24466 *val = xmlSchemaNewQNameValue( | |
| 24467 BAD_CAST xmlStrdup(nsName), BAD_CAST local); | |
| 24468 else | |
| 24469 *val = xmlSchemaNewQNameValue(NULL, | |
| 24470 BAD_CAST local); | |
| 24471 } else | |
| 24472 xmlFree(local); | |
| 24473 return (0); | |
| 24474 } | |
| 24475 | |
| 24476 /* | |
| 24477 * cvc-simple-type | |
| 24478 */ | |
| 24479 static int | |
| 24480 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt, | |
| 24481 xmlNodePtr node, | |
| 24482 xmlSchemaTypePtr type, | |
| 24483 const xmlChar *value, | |
| 24484 xmlSchemaValPtr *retVal, | |
| 24485 int fireErrors, | |
| 24486 int normalize, | |
| 24487 int isNormalized) | |
| 24488 { | |
| 24489 int ret = 0, valNeeded = (retVal) ? 1 : 0; | |
| 24490 xmlSchemaValPtr val = NULL; | |
| 24491 /* xmlSchemaWhitespaceValueType ws; */ | |
| 24492 xmlChar *normValue = NULL; | |
| 24493 | |
| 24494 #define NORMALIZE(atype) \ | |
| 24495 if ((! isNormalized) && \ | |
| 24496 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \ | |
| 24497 normValue = xmlSchemaNormalizeValue(atype, value); \ | |
| 24498 if (normValue != NULL) \ | |
| 24499 value = normValue; \ | |
| 24500 isNormalized = 1; \ | |
| 24501 } | |
| 24502 | |
| 24503 if ((retVal != NULL) && (*retVal != NULL)) { | |
| 24504 xmlSchemaFreeValue(*retVal); | |
| 24505 *retVal = NULL; | |
| 24506 } | |
| 24507 /* | |
| 24508 * 3.14.4 Simple Type Definition Validation Rules | |
| 24509 * Validation Rule: String Valid | |
| 24510 */ | |
| 24511 /* | |
| 24512 * 1 It is schema-valid with respect to that definition as defined | |
| 24513 * by Datatype Valid in [XML Schemas: Datatypes]. | |
| 24514 */ | |
| 24515 /* | |
| 24516 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given | |
| 24517 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then | |
| 24518 * the string must be a `declared entity name`. | |
| 24519 */ | |
| 24520 /* | |
| 24521 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES | |
| 24522 * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), | |
| 24523 * then every whitespace-delimited substring of the string must be a `declare
d | |
| 24524 * entity name`. | |
| 24525 */ | |
| 24526 /* | |
| 24527 * 2.3 otherwise no further condition applies. | |
| 24528 */ | |
| 24529 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)) | |
| 24530 valNeeded = 1; | |
| 24531 if (value == NULL) | |
| 24532 value = BAD_CAST ""; | |
| 24533 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) { | |
| 24534 xmlSchemaTypePtr biType; /* The built-in type. */ | |
| 24535 /* | |
| 24536 * SPEC (1.2.1) "if {variety} is `atomic` then the string must `match` | |
| 24537 * a literal in the `lexical space` of {base type definition}" | |
| 24538 */ | |
| 24539 /* | |
| 24540 * Whitespace-normalize. | |
| 24541 */ | |
| 24542 NORMALIZE(type); | |
| 24543 if (type->type != XML_SCHEMA_TYPE_BASIC) { | |
| 24544 /* | |
| 24545 * Get the built-in type. | |
| 24546 */ | |
| 24547 biType = type->baseType; | |
| 24548 while ((biType != NULL) && | |
| 24549 (biType->type != XML_SCHEMA_TYPE_BASIC)) | |
| 24550 biType = biType->baseType; | |
| 24551 | |
| 24552 if (biType == NULL) { | |
| 24553 AERROR_INT("xmlSchemaVCheckCVCSimpleType", | |
| 24554 "could not get the built-in type"); | |
| 24555 goto internal_error; | |
| 24556 } | |
| 24557 } else | |
| 24558 biType = type; | |
| 24559 /* | |
| 24560 * NOTATIONs need to be processed here, since they need | |
| 24561 * to lookup in the hashtable of NOTATION declarations of the schema. | |
| 24562 */ | |
| 24563 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) { | |
| 24564 switch (biType->builtInType) { | |
| 24565 case XML_SCHEMAS_NOTATION: | |
| 24566 ret = xmlSchemaValidateNotation( | |
| 24567 (xmlSchemaValidCtxtPtr) actxt, | |
| 24568 ((xmlSchemaValidCtxtPtr) actxt)->schema, | |
| 24569 NULL, value, &val, valNeeded); | |
| 24570 break; | |
| 24571 case XML_SCHEMAS_QNAME: | |
| 24572 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt, | |
| 24573 value, &val, valNeeded); | |
| 24574 break; | |
| 24575 default: | |
| 24576 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */ | |
| 24577 if (valNeeded) | |
| 24578 ret = xmlSchemaValPredefTypeNodeNoNorm(biType, | |
| 24579 value, &val, node); | |
| 24580 else | |
| 24581 ret = xmlSchemaValPredefTypeNodeNoNorm(biType, | |
| 24582 value, NULL, node); | |
| 24583 break; | |
| 24584 } | |
| 24585 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) { | |
| 24586 switch (biType->builtInType) { | |
| 24587 case XML_SCHEMAS_NOTATION: | |
| 24588 ret = xmlSchemaValidateNotation(NULL, | |
| 24589 ((xmlSchemaParserCtxtPtr) actxt)->schema, node, | |
| 24590 value, &val, valNeeded); | |
| 24591 break; | |
| 24592 default: | |
| 24593 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */ | |
| 24594 if (valNeeded) | |
| 24595 ret = xmlSchemaValPredefTypeNodeNoNorm(biType, | |
| 24596 value, &val, node); | |
| 24597 else | |
| 24598 ret = xmlSchemaValPredefTypeNodeNoNorm(biType, | |
| 24599 value, NULL, node); | |
| 24600 break; | |
| 24601 } | |
| 24602 } else { | |
| 24603 /* | |
| 24604 * Validation via a public API is not implemented yet. | |
| 24605 */ | |
| 24606 TODO | |
| 24607 goto internal_error; | |
| 24608 } | |
| 24609 if (ret != 0) { | |
| 24610 if (ret < 0) { | |
| 24611 AERROR_INT("xmlSchemaVCheckCVCSimpleType", | |
| 24612 "validating against a built-in type"); | |
| 24613 goto internal_error; | |
| 24614 } | |
| 24615 if (WXS_IS_LIST(type)) | |
| 24616 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; | |
| 24617 else | |
| 24618 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; | |
| 24619 } | |
| 24620 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) { | |
| 24621 /* | |
| 24622 * Check facets. | |
| 24623 */ | |
| 24624 ret = xmlSchemaValidateFacets(actxt, node, type, | |
| 24625 (xmlSchemaValType) biType->builtInType, value, val, | |
| 24626 0, fireErrors); | |
| 24627 if (ret != 0) { | |
| 24628 if (ret < 0) { | |
| 24629 AERROR_INT("xmlSchemaVCheckCVCSimpleType", | |
| 24630 "validating facets of atomic simple type"); | |
| 24631 goto internal_error; | |
| 24632 } | |
| 24633 if (WXS_IS_LIST(type)) | |
| 24634 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; | |
| 24635 else | |
| 24636 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; | |
| 24637 } | |
| 24638 } | |
| 24639 if (fireErrors && (ret > 0)) | |
| 24640 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1); | |
| 24641 } else if (WXS_IS_LIST(type)) { | |
| 24642 | |
| 24643 xmlSchemaTypePtr itemType; | |
| 24644 const xmlChar *cur, *end; | |
| 24645 xmlChar *tmpValue = NULL; | |
| 24646 unsigned long len = 0; | |
| 24647 xmlSchemaValPtr prevVal = NULL, curVal = NULL; | |
| 24648 /* 1.2.2 if {variety} is `list` then the string must be a sequence | |
| 24649 * of white space separated tokens, each of which `match`es a literal | |
| 24650 * in the `lexical space` of {item type definition} | |
| 24651 */ | |
| 24652 /* | |
| 24653 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if | |
| 24654 * the list type has an enum or pattern facet. | |
| 24655 */ | |
| 24656 NORMALIZE(type); | |
| 24657 /* | |
| 24658 * VAL TODO: Optimize validation of empty values. | |
| 24659 * VAL TODO: We do not have computed values for lists. | |
| 24660 */ | |
| 24661 itemType = WXS_LIST_ITEMTYPE(type); | |
| 24662 cur = value; | |
| 24663 do { | |
| 24664 while (IS_BLANK_CH(*cur)) | |
| 24665 cur++; | |
| 24666 end = cur; | |
| 24667 while ((*end != 0) && (!(IS_BLANK_CH(*end)))) | |
| 24668 end++; | |
| 24669 if (end == cur) | |
| 24670 break; | |
| 24671 tmpValue = xmlStrndup(cur, end - cur); | |
| 24672 len++; | |
| 24673 | |
| 24674 if (valNeeded) | |
| 24675 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType, | |
| 24676 tmpValue, &curVal, fireErrors, 0, 1); | |
| 24677 else | |
| 24678 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType, | |
| 24679 tmpValue, NULL, fireErrors, 0, 1); | |
| 24680 FREE_AND_NULL(tmpValue); | |
| 24681 if (curVal != NULL) { | |
| 24682 /* | |
| 24683 * Add to list of computed values. | |
| 24684 */ | |
| 24685 if (val == NULL) | |
| 24686 val = curVal; | |
| 24687 else | |
| 24688 xmlSchemaValueAppend(prevVal, curVal); | |
| 24689 prevVal = curVal; | |
| 24690 curVal = NULL; | |
| 24691 } | |
| 24692 if (ret != 0) { | |
| 24693 if (ret < 0) { | |
| 24694 AERROR_INT("xmlSchemaVCheckCVCSimpleType", | |
| 24695 "validating an item of list simple type"); | |
| 24696 goto internal_error; | |
| 24697 } | |
| 24698 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; | |
| 24699 break; | |
| 24700 } | |
| 24701 cur = end; | |
| 24702 } while (*cur != 0); | |
| 24703 FREE_AND_NULL(tmpValue); | |
| 24704 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) { | |
| 24705 /* | |
| 24706 * Apply facets (pattern, enumeration). | |
| 24707 */ | |
| 24708 ret = xmlSchemaValidateFacets(actxt, node, type, | |
| 24709 XML_SCHEMAS_UNKNOWN, value, val, | |
| 24710 len, fireErrors); | |
| 24711 if (ret != 0) { | |
| 24712 if (ret < 0) { | |
| 24713 AERROR_INT("xmlSchemaVCheckCVCSimpleType", | |
| 24714 "validating facets of list simple type"); | |
| 24715 goto internal_error; | |
| 24716 } | |
| 24717 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; | |
| 24718 } | |
| 24719 } | |
| 24720 if (fireErrors && (ret > 0)) { | |
| 24721 /* | |
| 24722 * Report the normalized value. | |
| 24723 */ | |
| 24724 normalize = 1; | |
| 24725 NORMALIZE(type); | |
| 24726 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1); | |
| 24727 } | |
| 24728 } else if (WXS_IS_UNION(type)) { | |
| 24729 xmlSchemaTypeLinkPtr memberLink; | |
| 24730 /* | |
| 24731 * TODO: For all datatypes `derived` by `union` whiteSpace does | |
| 24732 * not apply directly; however, the normalization behavior of `union` | |
| 24733 * types is controlled by the value of whiteSpace on that one of the | |
| 24734 * `memberTypes` against which the `union` is successfully validated. | |
| 24735 * | |
| 24736 * This means that the value is normalized by the first validating | |
| 24737 * member type, then the facets of the union type are applied. This | |
| 24738 * needs changing of the value! | |
| 24739 */ | |
| 24740 | |
| 24741 /* | |
| 24742 * 1.2.3 if {variety} is `union` then the string must `match` a | |
| 24743 * literal in the `lexical space` of at least one member of | |
| 24744 * {member type definitions} | |
| 24745 */ | |
| 24746 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type); | |
| 24747 if (memberLink == NULL) { | |
| 24748 AERROR_INT("xmlSchemaVCheckCVCSimpleType", | |
| 24749 "union simple type has no member types"); | |
| 24750 goto internal_error; | |
| 24751 } | |
| 24752 /* | |
| 24753 * Always normalize union type values, since we currently | |
| 24754 * cannot store the whitespace information with the value | |
| 24755 * itself; otherwise a later value-comparison would be | |
| 24756 * not possible. | |
| 24757 */ | |
| 24758 while (memberLink != NULL) { | |
| 24759 if (valNeeded) | |
| 24760 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, | |
| 24761 memberLink->type, value, &val, 0, 1, 0); | |
| 24762 else | |
| 24763 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, | |
| 24764 memberLink->type, value, NULL, 0, 1, 0); | |
| 24765 if (ret <= 0) | |
| 24766 break; | |
| 24767 memberLink = memberLink->next; | |
| 24768 } | |
| 24769 if (ret != 0) { | |
| 24770 if (ret < 0) { | |
| 24771 AERROR_INT("xmlSchemaVCheckCVCSimpleType", | |
| 24772 "validating members of union simple type"); | |
| 24773 goto internal_error; | |
| 24774 } | |
| 24775 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3; | |
| 24776 } | |
| 24777 /* | |
| 24778 * Apply facets (pattern, enumeration). | |
| 24779 */ | |
| 24780 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) { | |
| 24781 /* | |
| 24782 * The normalization behavior of `union` types is controlled by | |
| 24783 * the value of whiteSpace on that one of the `memberTypes` | |
| 24784 * against which the `union` is successfully validated. | |
| 24785 */ | |
| 24786 NORMALIZE(memberLink->type); | |
| 24787 ret = xmlSchemaValidateFacets(actxt, node, type, | |
| 24788 XML_SCHEMAS_UNKNOWN, value, val, | |
| 24789 0, fireErrors); | |
| 24790 if (ret != 0) { | |
| 24791 if (ret < 0) { | |
| 24792 AERROR_INT("xmlSchemaVCheckCVCSimpleType", | |
| 24793 "validating facets of union simple type"); | |
| 24794 goto internal_error; | |
| 24795 } | |
| 24796 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3; | |
| 24797 } | |
| 24798 } | |
| 24799 if (fireErrors && (ret > 0)) | |
| 24800 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1); | |
| 24801 } | |
| 24802 | |
| 24803 if (normValue != NULL) | |
| 24804 xmlFree(normValue); | |
| 24805 if (ret == 0) { | |
| 24806 if (retVal != NULL) | |
| 24807 *retVal = val; | |
| 24808 else if (val != NULL) | |
| 24809 xmlSchemaFreeValue(val); | |
| 24810 } else if (val != NULL) | |
| 24811 xmlSchemaFreeValue(val); | |
| 24812 return (ret); | |
| 24813 internal_error: | |
| 24814 if (normValue != NULL) | |
| 24815 xmlFree(normValue); | |
| 24816 if (val != NULL) | |
| 24817 xmlSchemaFreeValue(val); | |
| 24818 return (-1); | |
| 24819 } | |
| 24820 | |
| 24821 static int | |
| 24822 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt, | |
| 24823 const xmlChar *value, | |
| 24824 const xmlChar **nsName, | |
| 24825 const xmlChar **localName) | |
| 24826 { | |
| 24827 int ret = 0; | |
| 24828 | |
| 24829 if ((nsName == NULL) || (localName == NULL)) | |
| 24830 return (-1); | |
| 24831 *nsName = NULL; | |
| 24832 *localName = NULL; | |
| 24833 | |
| 24834 ret = xmlValidateQName(value, 1); | |
| 24835 if (ret == -1) | |
| 24836 return (-1); | |
| 24837 if (ret > 0) { | |
| 24838 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt, | |
| 24839 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL, | |
| 24840 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1); | |
| 24841 return (1); | |
| 24842 } | |
| 24843 { | |
| 24844 xmlChar *local = NULL; | |
| 24845 xmlChar *prefix; | |
| 24846 | |
| 24847 /* | |
| 24848 * NOTE: xmlSplitQName2 will return a duplicated | |
| 24849 * string. | |
| 24850 */ | |
| 24851 local = xmlSplitQName2(value, &prefix); | |
| 24852 if (local == NULL) | |
| 24853 *localName = xmlDictLookup(vctxt->dict, value, -1); | |
| 24854 else { | |
| 24855 *localName = xmlDictLookup(vctxt->dict, local, -1); | |
| 24856 xmlFree(local); | |
| 24857 } | |
| 24858 | |
| 24859 *nsName = xmlSchemaLookupNamespace(vctxt, prefix); | |
| 24860 | |
| 24861 if (prefix != NULL) { | |
| 24862 xmlFree(prefix); | |
| 24863 /* | |
| 24864 * A namespace must be found if the prefix is NOT NULL. | |
| 24865 */ | |
| 24866 if (*nsName == NULL) { | |
| 24867 xmlSchemaCustomErr(ACTXT_CAST vctxt, | |
| 24868 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL, | |
| 24869 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), | |
| 24870 "The QName value '%s' has no " | |
| 24871 "corresponding namespace declaration in scope", | |
| 24872 value, NULL); | |
| 24873 return (2); | |
| 24874 } | |
| 24875 } | |
| 24876 } | |
| 24877 return (0); | |
| 24878 } | |
| 24879 | |
| 24880 static int | |
| 24881 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt, | |
| 24882 xmlSchemaAttrInfoPtr iattr, | |
| 24883 xmlSchemaTypePtr *localType, | |
| 24884 xmlSchemaElementPtr elemDecl) | |
| 24885 { | |
| 24886 int ret = 0; | |
| 24887 /* | |
| 24888 * cvc-elt (3.3.4) : (4) | |
| 24889 * AND | |
| 24890 * Schema-Validity Assessment (Element) (cvc-assess-elt) | |
| 24891 * (1.2.1.2.1) - (1.2.1.2.4) | |
| 24892 * Handle 'xsi:type'. | |
| 24893 */ | |
| 24894 if (localType == NULL) | |
| 24895 return (-1); | |
| 24896 *localType = NULL; | |
| 24897 if (iattr == NULL) | |
| 24898 return (0); | |
| 24899 else { | |
| 24900 const xmlChar *nsName = NULL, *local = NULL; | |
| 24901 /* | |
| 24902 * TODO: We should report a *warning* that the type was overriden | |
| 24903 * by the instance. | |
| 24904 */ | |
| 24905 ACTIVATE_ATTRIBUTE(iattr); | |
| 24906 /* | |
| 24907 * (cvc-elt) (3.3.4) : (4.1) | |
| 24908 * (cvc-assess-elt) (1.2.1.2.2) | |
| 24909 */ | |
| 24910 ret = xmlSchemaVExpandQName(vctxt, iattr->value, | |
| 24911 &nsName, &local); | |
| 24912 if (ret != 0) { | |
| 24913 if (ret < 0) { | |
| 24914 VERROR_INT("xmlSchemaValidateElementByDeclaration", | |
| 24915 "calling xmlSchemaQNameExpand() to validate the " | |
| 24916 "attribute 'xsi:type'"); | |
| 24917 goto internal_error; | |
| 24918 } | |
| 24919 goto exit; | |
| 24920 } | |
| 24921 /* | |
| 24922 * (cvc-elt) (3.3.4) : (4.2) | |
| 24923 * (cvc-assess-elt) (1.2.1.2.3) | |
| 24924 */ | |
| 24925 *localType = xmlSchemaGetType(vctxt->schema, local, nsName); | |
| 24926 if (*localType == NULL) { | |
| 24927 xmlChar *str = NULL; | |
| 24928 | |
| 24929 xmlSchemaCustomErr(ACTXT_CAST vctxt, | |
| 24930 XML_SCHEMAV_CVC_ELT_4_2, NULL, | |
| 24931 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), | |
| 24932 "The QName value '%s' of the xsi:type attribute does not " | |
| 24933 "resolve to a type definition", | |
| 24934 xmlSchemaFormatQName(&str, nsName, local), NULL); | |
| 24935 FREE_AND_NULL(str); | |
| 24936 ret = vctxt->err; | |
| 24937 goto exit; | |
| 24938 } | |
| 24939 if (elemDecl != NULL) { | |
| 24940 int set = 0; | |
| 24941 | |
| 24942 /* | |
| 24943 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK) | |
| 24944 * "The `local type definition` must be validly | |
| 24945 * derived from the {type definition} given the union of | |
| 24946 * the {disallowed substitutions} and the {type definition}'s | |
| 24947 * {prohibited substitutions}, as defined in | |
| 24948 * Type Derivation OK (Complex) ($3.4.6) | |
| 24949 * (if it is a complex type definition), | |
| 24950 * or given {disallowed substitutions} as defined in Type | |
| 24951 * Derivation OK (Simple) ($3.14.6) (if it is a simple type | |
| 24952 * definition)." | |
| 24953 * | |
| 24954 * {disallowed substitutions}: the "block" on the element decl. | |
| 24955 * {prohibited substitutions}: the "block" on the type def. | |
| 24956 */ | |
| 24957 /* | |
| 24958 * OPTIMIZE TODO: We could map types already evaluated | |
| 24959 * to be validly derived from other types to avoid checking | |
| 24960 * this over and over for the same types. | |
| 24961 */ | |
| 24962 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) || | |
| 24963 (elemDecl->subtypes->flags & | |
| 24964 XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) | |
| 24965 set |= SUBSET_EXTENSION; | |
| 24966 | |
| 24967 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) || | |
| 24968 (elemDecl->subtypes->flags & | |
| 24969 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)) | |
| 24970 set |= SUBSET_RESTRICTION; | |
| 24971 | |
| 24972 /* | |
| 24973 * REMOVED and CHANGED since this produced a parser context | |
| 24974 * which adds to the string dict of the schema. So this would | |
| 24975 * change the schema and we don't want this. We don't need | |
| 24976 * the parser context anymore. | |
| 24977 * | |
| 24978 * if ((vctxt->pctxt == NULL) && | |
| 24979 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) | |
| 24980 * return (-1); | |
| 24981 */ | |
| 24982 | |
| 24983 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType, | |
| 24984 elemDecl->subtypes, set) != 0) { | |
| 24985 xmlChar *str = NULL; | |
| 24986 | |
| 24987 xmlSchemaCustomErr(ACTXT_CAST vctxt, | |
| 24988 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL, | |
| 24989 "The type definition '%s', specified by xsi:type, is " | |
| 24990 "blocked or not validly derived from the type definition " | |
| 24991 "of the element declaration", | |
| 24992 xmlSchemaFormatQName(&str, | |
| 24993 (*localType)->targetNamespace, | |
| 24994 (*localType)->name), | |
| 24995 NULL); | |
| 24996 FREE_AND_NULL(str); | |
| 24997 ret = vctxt->err; | |
| 24998 *localType = NULL; | |
| 24999 } | |
| 25000 } | |
| 25001 } | |
| 25002 exit: | |
| 25003 ACTIVATE_ELEM; | |
| 25004 return (ret); | |
| 25005 internal_error: | |
| 25006 ACTIVATE_ELEM; | |
| 25007 return (-1); | |
| 25008 } | |
| 25009 | |
| 25010 static int | |
| 25011 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt) | |
| 25012 { | |
| 25013 xmlSchemaElementPtr elemDecl = vctxt->inode->decl; | |
| 25014 xmlSchemaTypePtr actualType; | |
| 25015 | |
| 25016 /* | |
| 25017 * cvc-elt (3.3.4) : 1 | |
| 25018 */ | |
| 25019 if (elemDecl == NULL) { | |
| 25020 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, | |
| 25021 "No matching declaration available"); | |
| 25022 return (vctxt->err); | |
| 25023 } | |
| 25024 actualType = WXS_ELEM_TYPEDEF(elemDecl); | |
| 25025 /* | |
| 25026 * cvc-elt (3.3.4) : 2 | |
| 25027 */ | |
| 25028 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) { | |
| 25029 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL, | |
| 25030 "The element declaration is abstract"); | |
| 25031 return (vctxt->err); | |
| 25032 } | |
| 25033 if (actualType == NULL) { | |
| 25034 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL, | |
| 25035 "The type definition is absent"); | |
| 25036 return (XML_SCHEMAV_CVC_TYPE_1); | |
| 25037 } | |
| 25038 if (vctxt->nbAttrInfos != 0) { | |
| 25039 int ret; | |
| 25040 xmlSchemaAttrInfoPtr iattr; | |
| 25041 /* | |
| 25042 * cvc-elt (3.3.4) : 3 | |
| 25043 * Handle 'xsi:nil'. | |
| 25044 */ | |
| 25045 iattr = xmlSchemaGetMetaAttrInfo(vctxt, | |
| 25046 XML_SCHEMA_ATTR_INFO_META_XSI_NIL); | |
| 25047 if (iattr) { | |
| 25048 ACTIVATE_ATTRIBUTE(iattr); | |
| 25049 /* | |
| 25050 * Validate the value. | |
| 25051 */ | |
| 25052 ret = xmlSchemaVCheckCVCSimpleType( | |
| 25053 ACTXT_CAST vctxt, NULL, | |
| 25054 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN), | |
| 25055 iattr->value, &(iattr->val), 1, 0, 0); | |
| 25056 ACTIVATE_ELEM; | |
| 25057 if (ret < 0) { | |
| 25058 VERROR_INT("xmlSchemaValidateElemDecl", | |
| 25059 "calling xmlSchemaVCheckCVCSimpleType() to " | |
| 25060 "validate the attribute 'xsi:nil'"); | |
| 25061 return (-1); | |
| 25062 } | |
| 25063 if (ret == 0) { | |
| 25064 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) { | |
| 25065 /* | |
| 25066 * cvc-elt (3.3.4) : 3.1 | |
| 25067 */ | |
| 25068 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL, | |
| 25069 "The element is not 'nillable'"); | |
| 25070 /* Does not return an error on purpose. */ | |
| 25071 } else { | |
| 25072 if (xmlSchemaValueGetAsBoolean(iattr->val)) { | |
| 25073 /* | |
| 25074 * cvc-elt (3.3.4) : 3.2.2 | |
| 25075 */ | |
| 25076 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && | |
| 25077 (elemDecl->value != NULL)) { | |
| 25078 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL, | |
| 25079 "The element cannot be 'nilled' because " | |
| 25080 "there is a fixed value constraint defined " | |
| 25081 "for it"); | |
| 25082 /* Does not return an error on purpose. */ | |
| 25083 } else | |
| 25084 vctxt->inode->flags |= | |
| 25085 XML_SCHEMA_ELEM_INFO_NILLED; | |
| 25086 } | |
| 25087 } | |
| 25088 } | |
| 25089 } | |
| 25090 /* | |
| 25091 * cvc-elt (3.3.4) : 4 | |
| 25092 * Handle 'xsi:type'. | |
| 25093 */ | |
| 25094 iattr = xmlSchemaGetMetaAttrInfo(vctxt, | |
| 25095 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE); | |
| 25096 if (iattr) { | |
| 25097 xmlSchemaTypePtr localType = NULL; | |
| 25098 | |
| 25099 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType, | |
| 25100 elemDecl); | |
| 25101 if (ret != 0) { | |
| 25102 if (ret == -1) { | |
| 25103 VERROR_INT("xmlSchemaValidateElemDecl", | |
| 25104 "calling xmlSchemaProcessXSIType() to " | |
| 25105 "process the attribute 'xsi:type'"); | |
| 25106 return (-1); | |
| 25107 } | |
| 25108 /* Does not return an error on purpose. */ | |
| 25109 } | |
| 25110 if (localType != NULL) { | |
| 25111 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE; | |
| 25112 actualType = localType; | |
| 25113 } | |
| 25114 } | |
| 25115 } | |
| 25116 /* | |
| 25117 * IDC: Register identity-constraint XPath matchers. | |
| 25118 */ | |
| 25119 if ((elemDecl->idcs != NULL) && | |
| 25120 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1)) | |
| 25121 return (-1); | |
| 25122 /* | |
| 25123 * No actual type definition. | |
| 25124 */ | |
| 25125 if (actualType == NULL) { | |
| 25126 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL, | |
| 25127 "The type definition is absent"); | |
| 25128 return (XML_SCHEMAV_CVC_TYPE_1); | |
| 25129 } | |
| 25130 /* | |
| 25131 * Remember the actual type definition. | |
| 25132 */ | |
| 25133 vctxt->inode->typeDef = actualType; | |
| 25134 | |
| 25135 return (0); | |
| 25136 } | |
| 25137 | |
| 25138 static int | |
| 25139 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt) | |
| 25140 { | |
| 25141 xmlSchemaAttrInfoPtr iattr; | |
| 25142 int ret = 0, i; | |
| 25143 | |
| 25144 /* | |
| 25145 * SPEC cvc-type (3.1.1) | |
| 25146 * "The attributes of must be empty, excepting those whose namespace | |
| 25147 * name is identical to http://www.w3.org/2001/XMLSchema-instance and | |
| 25148 * whose local name is one of type, nil, schemaLocation or | |
| 25149 * noNamespaceSchemaLocation." | |
| 25150 */ | |
| 25151 if (vctxt->nbAttrInfos == 0) | |
| 25152 return (0); | |
| 25153 for (i = 0; i < vctxt->nbAttrInfos; i++) { | |
| 25154 iattr = vctxt->attrInfos[i]; | |
| 25155 if (! iattr->metaType) { | |
| 25156 ACTIVATE_ATTRIBUTE(iattr) | |
| 25157 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt, | |
| 25158 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL); | |
| 25159 ret = XML_SCHEMAV_CVC_TYPE_3_1_1; | |
| 25160 } | |
| 25161 } | |
| 25162 ACTIVATE_ELEM | |
| 25163 return (ret); | |
| 25164 } | |
| 25165 | |
| 25166 /* | |
| 25167 * Cleanup currently used attribute infos. | |
| 25168 */ | |
| 25169 static void | |
| 25170 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt) | |
| 25171 { | |
| 25172 int i; | |
| 25173 xmlSchemaAttrInfoPtr attr; | |
| 25174 | |
| 25175 if (vctxt->nbAttrInfos == 0) | |
| 25176 return; | |
| 25177 for (i = 0; i < vctxt->nbAttrInfos; i++) { | |
| 25178 attr = vctxt->attrInfos[i]; | |
| 25179 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) { | |
| 25180 if (attr->localName != NULL) | |
| 25181 xmlFree((xmlChar *) attr->localName); | |
| 25182 if (attr->nsName != NULL) | |
| 25183 xmlFree((xmlChar *) attr->nsName); | |
| 25184 } | |
| 25185 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) { | |
| 25186 if (attr->value != NULL) | |
| 25187 xmlFree((xmlChar *) attr->value); | |
| 25188 } | |
| 25189 if (attr->val != NULL) { | |
| 25190 xmlSchemaFreeValue(attr->val); | |
| 25191 attr->val = NULL; | |
| 25192 } | |
| 25193 memset(attr, 0, sizeof(xmlSchemaAttrInfo)); | |
| 25194 } | |
| 25195 vctxt->nbAttrInfos = 0; | |
| 25196 } | |
| 25197 | |
| 25198 /* | |
| 25199 * 3.4.4 Complex Type Definition Validation Rules | |
| 25200 * Element Locally Valid (Complex Type) (cvc-complex-type) | |
| 25201 * 3.2.4 Attribute Declaration Validation Rules | |
| 25202 * Validation Rule: Attribute Locally Valid (cvc-attribute) | |
| 25203 * Attribute Locally Valid (Use) (cvc-au) | |
| 25204 * | |
| 25205 * Only "assessed" attribute information items will be visible to | |
| 25206 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes. | |
| 25207 */ | |
| 25208 static int | |
| 25209 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt) | |
| 25210 { | |
| 25211 xmlSchemaTypePtr type = vctxt->inode->typeDef; | |
| 25212 xmlSchemaItemListPtr attrUseList; | |
| 25213 xmlSchemaAttributeUsePtr attrUse = NULL; | |
| 25214 xmlSchemaAttributePtr attrDecl = NULL; | |
| 25215 xmlSchemaAttrInfoPtr iattr, tmpiattr; | |
| 25216 int i, j, found, nbAttrs, nbUses; | |
| 25217 int xpathRes = 0, res, wildIDs = 0, fixed; | |
| 25218 xmlNodePtr defAttrOwnerElem = NULL; | |
| 25219 | |
| 25220 /* | |
| 25221 * SPEC (cvc-attribute) | |
| 25222 * (1) "The declaration must not be `absent` (see Missing | |
| 25223 * Sub-components ($5.3) for how this can fail to be | |
| 25224 * the case)." | |
| 25225 * (2) "Its {type definition} must not be absent." | |
| 25226 * | |
| 25227 * NOTE (1) + (2): This is not handled here, since we currently do not | |
| 25228 * allow validation against schemas which have missing sub-components. | |
| 25229 * | |
| 25230 * SPEC (cvc-complex-type) | |
| 25231 * (3) "For each attribute information item in the element information | |
| 25232 * item's [attributes] excepting those whose [namespace name] is | |
| 25233 * identical to http://www.w3.org/2001/XMLSchema-instance and whose | |
| 25234 * [local name] is one of type, nil, schemaLocation or | |
| 25235 * noNamespaceSchemaLocation, the appropriate case among the following | |
| 25236 * must be true: | |
| 25237 * | |
| 25238 */ | |
| 25239 attrUseList = (xmlSchemaItemListPtr) type->attrUses; | |
| 25240 /* | |
| 25241 * @nbAttrs is the number of attributes present in the instance. | |
| 25242 */ | |
| 25243 nbAttrs = vctxt->nbAttrInfos; | |
| 25244 if (attrUseList != NULL) | |
| 25245 nbUses = attrUseList->nbItems; | |
| 25246 else | |
| 25247 nbUses = 0; | |
| 25248 for (i = 0; i < nbUses; i++) { | |
| 25249 found = 0; | |
| 25250 attrUse = attrUseList->items[i]; | |
| 25251 attrDecl = WXS_ATTRUSE_DECL(attrUse); | |
| 25252 for (j = 0; j < nbAttrs; j++) { | |
| 25253 iattr = vctxt->attrInfos[j]; | |
| 25254 /* | |
| 25255 * SPEC (cvc-complex-type) (3) | |
| 25256 * Skip meta attributes. | |
| 25257 */ | |
| 25258 if (iattr->metaType) | |
| 25259 continue; | |
| 25260 if (iattr->localName[0] != attrDecl->name[0]) | |
| 25261 continue; | |
| 25262 if (!xmlStrEqual(iattr->localName, attrDecl->name)) | |
| 25263 continue; | |
| 25264 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace)) | |
| 25265 continue; | |
| 25266 found = 1; | |
| 25267 /* | |
| 25268 * SPEC (cvc-complex-type) | |
| 25269 * (3.1) "If there is among the {attribute uses} an attribute | |
| 25270 * use with an {attribute declaration} whose {name} matches | |
| 25271 * the attribute information item's [local name] and whose | |
| 25272 * {target namespace} is identical to the attribute information | |
| 25273 * item's [namespace name] (where an `absent` {target namespace} | |
| 25274 * is taken to be identical to a [namespace name] with no value), | |
| 25275 * then the attribute information must be `valid` with respect | |
| 25276 * to that attribute use as per Attribute Locally Valid (Use) | |
| 25277 * ($3.5.4). In this case the {attribute declaration} of that | |
| 25278 * attribute use is the `context-determined declaration` for the | |
| 25279 * attribute information item with respect to Schema-Validity | |
| 25280 * Assessment (Attribute) ($3.2.4) and | |
| 25281 * Assessment Outcome (Attribute) ($3.2.5). | |
| 25282 */ | |
| 25283 iattr->state = XML_SCHEMAS_ATTR_ASSESSED; | |
| 25284 iattr->use = attrUse; | |
| 25285 /* | |
| 25286 * Context-determined declaration. | |
| 25287 */ | |
| 25288 iattr->decl = attrDecl; | |
| 25289 iattr->typeDef = attrDecl->subtypes; | |
| 25290 break; | |
| 25291 } | |
| 25292 | |
| 25293 if (found) | |
| 25294 continue; | |
| 25295 | |
| 25296 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) { | |
| 25297 /* | |
| 25298 * Handle non-existent, required attributes. | |
| 25299 * | |
| 25300 * SPEC (cvc-complex-type) | |
| 25301 * (4) "The {attribute declaration} of each attribute use in | |
| 25302 * the {attribute uses} whose {required} is true matches one | |
| 25303 * of the attribute information items in the element information | |
| 25304 * item's [attributes] as per clause 3.1 above." | |
| 25305 */ | |
| 25306 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt); | |
| 25307 if (tmpiattr == NULL) { | |
| 25308 VERROR_INT( | |
| 25309 "xmlSchemaVAttributesComplex", | |
| 25310 "calling xmlSchemaGetFreshAttrInfo()"); | |
| 25311 return (-1); | |
| 25312 } | |
| 25313 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING; | |
| 25314 tmpiattr->use = attrUse; | |
| 25315 tmpiattr->decl = attrDecl; | |
| 25316 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) && | |
| 25317 ((attrUse->defValue != NULL) || | |
| 25318 (attrDecl->defValue != NULL))) { | |
| 25319 /* | |
| 25320 * Handle non-existent, optional, default/fixed attributes. | |
| 25321 */ | |
| 25322 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt); | |
| 25323 if (tmpiattr == NULL) { | |
| 25324 VERROR_INT( | |
| 25325 "xmlSchemaVAttributesComplex", | |
| 25326 "calling xmlSchemaGetFreshAttrInfo()"); | |
| 25327 return (-1); | |
| 25328 } | |
| 25329 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT; | |
| 25330 tmpiattr->use = attrUse; | |
| 25331 tmpiattr->decl = attrDecl; | |
| 25332 tmpiattr->typeDef = attrDecl->subtypes; | |
| 25333 tmpiattr->localName = attrDecl->name; | |
| 25334 tmpiattr->nsName = attrDecl->targetNamespace; | |
| 25335 } | |
| 25336 } | |
| 25337 | |
| 25338 if (vctxt->nbAttrInfos == 0) | |
| 25339 return (0); | |
| 25340 /* | |
| 25341 * Validate against the wildcard. | |
| 25342 */ | |
| 25343 if (type->attributeWildcard != NULL) { | |
| 25344 /* | |
| 25345 * SPEC (cvc-complex-type) | |
| 25346 * (3.2.1) "There must be an {attribute wildcard}." | |
| 25347 */ | |
| 25348 for (i = 0; i < nbAttrs; i++) { | |
| 25349 iattr = vctxt->attrInfos[i]; | |
| 25350 /* | |
| 25351 * SPEC (cvc-complex-type) (3) | |
| 25352 * Skip meta attributes. | |
| 25353 */ | |
| 25354 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN) | |
| 25355 continue; | |
| 25356 /* | |
| 25357 * SPEC (cvc-complex-type) | |
| 25358 * (3.2.2) "The attribute information item must be `valid` with | |
| 25359 * respect to it as defined in Item Valid (Wildcard) ($3.10.4)." | |
| 25360 * | |
| 25361 * SPEC Item Valid (Wildcard) (cvc-wildcard) | |
| 25362 * "... its [namespace name] must be `valid` with respect to | |
| 25363 * the wildcard constraint, as defined in Wildcard allows | |
| 25364 * Namespace Name ($3.10.4)." | |
| 25365 */ | |
| 25366 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard, | |
| 25367 iattr->nsName) == 0) { | |
| 25368 /* | |
| 25369 * Handle processContents. | |
| 25370 * | |
| 25371 * SPEC (cvc-wildcard): | |
| 25372 * processContents | context-determined declaration: | |
| 25373 * "strict" "mustFind" | |
| 25374 * "lax" "none" | |
| 25375 * "skip" "skip" | |
| 25376 */ | |
| 25377 if (type->attributeWildcard->processContents == | |
| 25378 XML_SCHEMAS_ANY_SKIP) { | |
| 25379 /* | |
| 25380 * context-determined declaration = "skip" | |
| 25381 * | |
| 25382 * SPEC PSVI Assessment Outcome (Attribute) | |
| 25383 * [validity] = "notKnown" | |
| 25384 * [validation attempted] = "none" | |
| 25385 */ | |
| 25386 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP; | |
| 25387 continue; | |
| 25388 } | |
| 25389 /* | |
| 25390 * Find an attribute declaration. | |
| 25391 */ | |
| 25392 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema, | |
| 25393 iattr->localName, iattr->nsName); | |
| 25394 if (iattr->decl != NULL) { | |
| 25395 iattr->state = XML_SCHEMAS_ATTR_ASSESSED; | |
| 25396 /* | |
| 25397 * SPEC (cvc-complex-type) | |
| 25398 * (5) "Let [Definition:] the wild IDs be the set of | |
| 25399 * all attribute information item to which clause 3.2 | |
| 25400 * applied and whose `validation` resulted in a | |
| 25401 * `context-determined declaration` of mustFind or no | |
| 25402 * `context-determined declaration` at all, and whose | |
| 25403 * [local name] and [namespace name] resolve (as | |
| 25404 * defined by QName resolution (Instance) ($3.15.4)) to | |
| 25405 * an attribute declaration whose {type definition} is | |
| 25406 * or is derived from ID. Then all of the following | |
| 25407 * must be true:" | |
| 25408 */ | |
| 25409 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl); | |
| 25410 if (xmlSchemaIsDerivedFromBuiltInType( | |
| 25411 iattr->typeDef, XML_SCHEMAS_ID)) { | |
| 25412 /* | |
| 25413 * SPEC (5.1) "There must be no more than one | |
| 25414 * item in `wild IDs`." | |
| 25415 */ | |
| 25416 if (wildIDs != 0) { | |
| 25417 /* VAL TODO */ | |
| 25418 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_I
D; | |
| 25419 TODO | |
| 25420 continue; | |
| 25421 } | |
| 25422 wildIDs++; | |
| 25423 /* | |
| 25424 * SPEC (cvc-complex-type) | |
| 25425 * (5.2) "If `wild IDs` is non-empty, there must not | |
| 25426 * be any attribute uses among the {attribute uses} | |
| 25427 * whose {attribute declaration}'s {type definition} | |
| 25428 * is or is derived from ID." | |
| 25429 */ | |
| 25430 if (attrUseList != NULL) { | |
| 25431 for (j = 0; j < attrUseList->nbItems; j++) { | |
| 25432 if (xmlSchemaIsDerivedFromBuiltInType( | |
| 25433 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]), | |
| 25434 XML_SCHEMAS_ID)) { | |
| 25435 /* URGENT VAL TODO: implement */ | |
| 25436 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID; | |
| 25437 TODO | |
| 25438 break; | |
| 25439 } | |
| 25440 } | |
| 25441 } | |
| 25442 } | |
| 25443 } else if (type->attributeWildcard->processContents == | |
| 25444 XML_SCHEMAS_ANY_LAX) { | |
| 25445 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL; | |
| 25446 /* | |
| 25447 * SPEC PSVI Assessment Outcome (Attribute) | |
| 25448 * [validity] = "notKnown" | |
| 25449 * [validation attempted] = "none" | |
| 25450 */ | |
| 25451 } else { | |
| 25452 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL; | |
| 25453 } | |
| 25454 } | |
| 25455 } | |
| 25456 } | |
| 25457 | |
| 25458 if (vctxt->nbAttrInfos == 0) | |
| 25459 return (0); | |
| 25460 | |
| 25461 /* | |
| 25462 * Get the owner element; needed for creation of default attributes. | |
| 25463 * This fixes bug #341337, reported by David Grohmann. | |
| 25464 */ | |
| 25465 if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) { | |
| 25466 xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth]; | |
| 25467 if (ielem && ielem->node && ielem->node->doc) | |
| 25468 defAttrOwnerElem = ielem->node; | |
| 25469 } | |
| 25470 /* | |
| 25471 * Validate values, create default attributes, evaluate IDCs. | |
| 25472 */ | |
| 25473 for (i = 0; i < vctxt->nbAttrInfos; i++) { | |
| 25474 iattr = vctxt->attrInfos[i]; | |
| 25475 /* | |
| 25476 * VAL TODO: Note that we won't try to resolve IDCs to | |
| 25477 * "lax" and "skip" validated attributes. Check what to | |
| 25478 * do in this case. | |
| 25479 */ | |
| 25480 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) && | |
| 25481 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT)) | |
| 25482 continue; | |
| 25483 /* | |
| 25484 * VAL TODO: What to do if the type definition is missing? | |
| 25485 */ | |
| 25486 if (iattr->typeDef == NULL) { | |
| 25487 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE; | |
| 25488 continue; | |
| 25489 } | |
| 25490 | |
| 25491 ACTIVATE_ATTRIBUTE(iattr); | |
| 25492 fixed = 0; | |
| 25493 xpathRes = 0; | |
| 25494 | |
| 25495 if (vctxt->xpathStates != NULL) { | |
| 25496 /* | |
| 25497 * Evaluate IDCs. | |
| 25498 */ | |
| 25499 xpathRes = xmlSchemaXPathEvaluate(vctxt, | |
| 25500 XML_ATTRIBUTE_NODE); | |
| 25501 if (xpathRes == -1) { | |
| 25502 VERROR_INT("xmlSchemaVAttributesComplex", | |
| 25503 "calling xmlSchemaXPathEvaluate()"); | |
| 25504 goto internal_error; | |
| 25505 } | |
| 25506 } | |
| 25507 | |
| 25508 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) { | |
| 25509 /* | |
| 25510 * Default/fixed attributes. | |
| 25511 * We need the value only if we need to resolve IDCs or | |
| 25512 * will create default attributes. | |
| 25513 */ | |
| 25514 if ((xpathRes) || (defAttrOwnerElem)) { | |
| 25515 if (iattr->use->defValue != NULL) { | |
| 25516 iattr->value = (xmlChar *) iattr->use->defValue; | |
| 25517 iattr->val = iattr->use->defVal; | |
| 25518 } else { | |
| 25519 iattr->value = (xmlChar *) iattr->decl->defValue; | |
| 25520 iattr->val = iattr->decl->defVal; | |
| 25521 } | |
| 25522 /* | |
| 25523 * IDCs will consume the precomputed default value, | |
| 25524 * so we need to clone it. | |
| 25525 */ | |
| 25526 if (iattr->val == NULL) { | |
| 25527 VERROR_INT("xmlSchemaVAttributesComplex", | |
| 25528 "default/fixed value on an attribute use was " | |
| 25529 "not precomputed"); | |
| 25530 goto internal_error; | |
| 25531 } | |
| 25532 iattr->val = xmlSchemaCopyValue(iattr->val); | |
| 25533 if (iattr->val == NULL) { | |
| 25534 VERROR_INT("xmlSchemaVAttributesComplex", | |
| 25535 "calling xmlSchemaCopyValue()"); | |
| 25536 goto internal_error; | |
| 25537 } | |
| 25538 } | |
| 25539 /* | |
| 25540 * PSVI: Add the default attribute to the current element. | |
| 25541 * VAL TODO: Should we use the *normalized* value? This currently | |
| 25542 * uses the *initial* value. | |
| 25543 */ | |
| 25544 | |
| 25545 if (defAttrOwnerElem) { | |
| 25546 xmlChar *normValue; | |
| 25547 const xmlChar *value; | |
| 25548 | |
| 25549 value = iattr->value; | |
| 25550 /* | |
| 25551 * Normalize the value. | |
| 25552 */ | |
| 25553 normValue = xmlSchemaNormalizeValue(iattr->typeDef, | |
| 25554 iattr->value); | |
| 25555 if (normValue != NULL) | |
| 25556 value = BAD_CAST normValue; | |
| 25557 | |
| 25558 if (iattr->nsName == NULL) { | |
| 25559 if (xmlNewProp(defAttrOwnerElem, | |
| 25560 iattr->localName, value) == NULL) { | |
| 25561 VERROR_INT("xmlSchemaVAttributesComplex", | |
| 25562 "calling xmlNewProp()"); | |
| 25563 if (normValue != NULL) | |
| 25564 xmlFree(normValue); | |
| 25565 goto internal_error; | |
| 25566 } | |
| 25567 } else { | |
| 25568 xmlNsPtr ns; | |
| 25569 | |
| 25570 ns = xmlSearchNsByHref(defAttrOwnerElem->doc, | |
| 25571 defAttrOwnerElem, iattr->nsName); | |
| 25572 if (ns == NULL) { | |
| 25573 xmlChar prefix[12]; | |
| 25574 int counter = 0; | |
| 25575 | |
| 25576 /* | |
| 25577 * Create a namespace declaration on the validation | |
| 25578 * root node if no namespace declaration is in scope. | |
| 25579 */ | |
| 25580 do { | |
| 25581 snprintf((char *) prefix, 12, "p%d", counter++); | |
| 25582 ns = xmlSearchNs(defAttrOwnerElem->doc, | |
| 25583 defAttrOwnerElem, BAD_CAST prefix); | |
| 25584 if (counter > 1000) { | |
| 25585 VERROR_INT( | |
| 25586 "xmlSchemaVAttributesComplex", | |
| 25587 "could not compute a ns prefix for a " | |
| 25588 "default/fixed attribute"); | |
| 25589 if (normValue != NULL) | |
| 25590 xmlFree(normValue); | |
| 25591 goto internal_error; | |
| 25592 } | |
| 25593 } while (ns != NULL); | |
| 25594 ns = xmlNewNs(vctxt->validationRoot, | |
| 25595 iattr->nsName, BAD_CAST prefix); | |
| 25596 } | |
| 25597 /* | |
| 25598 * TODO: | |
| 25599 * http://lists.w3.org/Archives/Public/www-xml-schema-comment
s/2005JulSep/0406.html | |
| 25600 * If we have QNames: do we need to ensure there's a | |
| 25601 * prefix defined for the QName? | |
| 25602 */ | |
| 25603 xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value); | |
| 25604 } | |
| 25605 if (normValue != NULL) | |
| 25606 xmlFree(normValue); | |
| 25607 } | |
| 25608 /* | |
| 25609 * Go directly to IDC evaluation. | |
| 25610 */ | |
| 25611 goto eval_idcs; | |
| 25612 } | |
| 25613 /* | |
| 25614 * Validate the value. | |
| 25615 */ | |
| 25616 if (vctxt->value != NULL) { | |
| 25617 /* | |
| 25618 * Free last computed value; just for safety reasons. | |
| 25619 */ | |
| 25620 xmlSchemaFreeValue(vctxt->value); | |
| 25621 vctxt->value = NULL; | |
| 25622 } | |
| 25623 /* | |
| 25624 * Note that the attribute *use* can be unavailable, if | |
| 25625 * the attribute was a wild attribute. | |
| 25626 */ | |
| 25627 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) || | |
| 25628 ((iattr->use != NULL) && | |
| 25629 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED))) | |
| 25630 fixed = 1; | |
| 25631 else | |
| 25632 fixed = 0; | |
| 25633 /* | |
| 25634 * SPEC (cvc-attribute) | |
| 25635 * (3) "The item's `normalized value` must be locally `valid` | |
| 25636 * with respect to that {type definition} as per | |
| 25637 * String Valid ($3.14.4)." | |
| 25638 * | |
| 25639 * VAL TODO: Do we already have the | |
| 25640 * "normalized attribute value" here? | |
| 25641 */ | |
| 25642 if (xpathRes || fixed) { | |
| 25643 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED; | |
| 25644 /* | |
| 25645 * Request a computed value. | |
| 25646 */ | |
| 25647 res = xmlSchemaVCheckCVCSimpleType( | |
| 25648 ACTXT_CAST vctxt, | |
| 25649 iattr->node, iattr->typeDef, iattr->value, &(iattr->val), | |
| 25650 1, 1, 0); | |
| 25651 } else { | |
| 25652 res = xmlSchemaVCheckCVCSimpleType( | |
| 25653 ACTXT_CAST vctxt, | |
| 25654 iattr->node, iattr->typeDef, iattr->value, NULL, | |
| 25655 1, 0, 0); | |
| 25656 } | |
| 25657 | |
| 25658 if (res != 0) { | |
| 25659 if (res == -1) { | |
| 25660 VERROR_INT("xmlSchemaVAttributesComplex", | |
| 25661 "calling xmlSchemaStreamValidateSimpleTypeValue()"); | |
| 25662 goto internal_error; | |
| 25663 } | |
| 25664 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE; | |
| 25665 /* | |
| 25666 * SPEC PSVI Assessment Outcome (Attribute) | |
| 25667 * [validity] = "invalid" | |
| 25668 */ | |
| 25669 goto eval_idcs; | |
| 25670 } | |
| 25671 | |
| 25672 if (fixed) { | |
| 25673 /* | |
| 25674 * SPEC Attribute Locally Valid (Use) (cvc-au) | |
| 25675 * "For an attribute information item to be `valid` | |
| 25676 * with respect to an attribute use its *normalized* | |
| 25677 * value must match the *canonical* lexical | |
| 25678 * representation of the attribute use's {value | |
| 25679 * constraint}value, if it is present and fixed." | |
| 25680 * | |
| 25681 * VAL TODO: The requirement for the *canonical* value | |
| 25682 * will be removed in XML Schema 1.1. | |
| 25683 */ | |
| 25684 /* | |
| 25685 * SPEC Attribute Locally Valid (cvc-attribute) | |
| 25686 * (4) "The item's *actual* value must match the *value* of | |
| 25687 * the {value constraint}, if it is present and fixed." | |
| 25688 */ | |
| 25689 if (iattr->val == NULL) { | |
| 25690 /* VAL TODO: A value was not precomputed. */ | |
| 25691 TODO | |
| 25692 goto eval_idcs; | |
| 25693 } | |
| 25694 if ((iattr->use != NULL) && | |
| 25695 (iattr->use->defValue != NULL)) { | |
| 25696 if (iattr->use->defVal == NULL) { | |
| 25697 /* VAL TODO: A default value was not precomputed. */ | |
| 25698 TODO | |
| 25699 goto eval_idcs; | |
| 25700 } | |
| 25701 iattr->vcValue = iattr->use->defValue; | |
| 25702 /* | |
| 25703 if (xmlSchemaCompareValuesWhtsp(attr->val, | |
| 25704 (xmlSchemaWhitespaceValueType) ws, | |
| 25705 attr->use->defVal, | |
| 25706 (xmlSchemaWhitespaceValueType) ws) != 0) { | |
| 25707 */ | |
| 25708 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal)) | |
| 25709 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE; | |
| 25710 } else { | |
| 25711 if (iattr->decl->defVal == NULL) { | |
| 25712 /* VAL TODO: A default value was not precomputed. */ | |
| 25713 TODO | |
| 25714 goto eval_idcs; | |
| 25715 } | |
| 25716 iattr->vcValue = iattr->decl->defValue; | |
| 25717 /* | |
| 25718 if (xmlSchemaCompareValuesWhtsp(attr->val, | |
| 25719 (xmlSchemaWhitespaceValueType) ws, | |
| 25720 attrDecl->defVal, | |
| 25721 (xmlSchemaWhitespaceValueType) ws) != 0) { | |
| 25722 */ | |
| 25723 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal)) | |
| 25724 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE; | |
| 25725 } | |
| 25726 /* | |
| 25727 * [validity] = "valid" | |
| 25728 */ | |
| 25729 } | |
| 25730 eval_idcs: | |
| 25731 /* | |
| 25732 * Evaluate IDCs. | |
| 25733 */ | |
| 25734 if (xpathRes) { | |
| 25735 if (xmlSchemaXPathProcessHistory(vctxt, | |
| 25736 vctxt->depth +1) == -1) { | |
| 25737 VERROR_INT("xmlSchemaVAttributesComplex", | |
| 25738 "calling xmlSchemaXPathEvaluate()"); | |
| 25739 goto internal_error; | |
| 25740 } | |
| 25741 } else if (vctxt->xpathStates != NULL) | |
| 25742 xmlSchemaXPathPop(vctxt); | |
| 25743 } | |
| 25744 | |
| 25745 /* | |
| 25746 * Report errors. | |
| 25747 */ | |
| 25748 for (i = 0; i < vctxt->nbAttrInfos; i++) { | |
| 25749 iattr = vctxt->attrInfos[i]; | |
| 25750 if ((iattr->state == XML_SCHEMAS_ATTR_META) || | |
| 25751 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) || | |
| 25752 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) || | |
| 25753 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL)) | |
| 25754 continue; | |
| 25755 ACTIVATE_ATTRIBUTE(iattr); | |
| 25756 switch (iattr->state) { | |
| 25757 case XML_SCHEMAS_ATTR_ERR_MISSING: { | |
| 25758 xmlChar *str = NULL; | |
| 25759 ACTIVATE_ELEM; | |
| 25760 xmlSchemaCustomErr(ACTXT_CAST vctxt, | |
| 25761 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL, | |
| 25762 "The attribute '%s' is required but missing", | |
| 25763 xmlSchemaFormatQName(&str, | |
| 25764 iattr->decl->targetNamespace, | |
| 25765 iattr->decl->name), | |
| 25766 NULL); | |
| 25767 FREE_AND_NULL(str) | |
| 25768 break; | |
| 25769 } | |
| 25770 case XML_SCHEMAS_ATTR_ERR_NO_TYPE: | |
| 25771 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL, | |
| 25772 "The type definition is absent"); | |
| 25773 break; | |
| 25774 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE: | |
| 25775 xmlSchemaCustomErr(ACTXT_CAST vctxt, | |
| 25776 XML_SCHEMAV_CVC_AU, NULL, NULL, | |
| 25777 "The value '%s' does not match the fixed " | |
| 25778 "value constraint '%s'", | |
| 25779 iattr->value, iattr->vcValue); | |
| 25780 break; | |
| 25781 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL: | |
| 25782 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL, | |
| 25783 "No matching global attribute declaration available, but " | |
| 25784 "demanded by the strict wildcard"); | |
| 25785 break; | |
| 25786 case XML_SCHEMAS_ATTR_UNKNOWN: | |
| 25787 if (iattr->metaType) | |
| 25788 break; | |
| 25789 /* | |
| 25790 * MAYBE VAL TODO: One might report different error messages | |
| 25791 * for the following errors. | |
| 25792 */ | |
| 25793 if (type->attributeWildcard == NULL) { | |
| 25794 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt, | |
| 25795 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL); | |
| 25796 } else { | |
| 25797 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt, | |
| 25798 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL); | |
| 25799 } | |
| 25800 break; | |
| 25801 default: | |
| 25802 break; | |
| 25803 } | |
| 25804 } | |
| 25805 | |
| 25806 ACTIVATE_ELEM; | |
| 25807 return (0); | |
| 25808 internal_error: | |
| 25809 ACTIVATE_ELEM; | |
| 25810 return (-1); | |
| 25811 } | |
| 25812 | |
| 25813 static int | |
| 25814 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt, | |
| 25815 int *skip) | |
| 25816 { | |
| 25817 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl; | |
| 25818 /* | |
| 25819 * The namespace of the element was already identified to be | |
| 25820 * matching the wildcard. | |
| 25821 */ | |
| 25822 if ((skip == NULL) || (wild == NULL) || | |
| 25823 (wild->type != XML_SCHEMA_TYPE_ANY)) { | |
| 25824 VERROR_INT("xmlSchemaValidateElemWildcard", | |
| 25825 "bad arguments"); | |
| 25826 return (-1); | |
| 25827 } | |
| 25828 *skip = 0; | |
| 25829 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) { | |
| 25830 /* | |
| 25831 * URGENT VAL TODO: Either we need to position the stream to the | |
| 25832 * next sibling, or walk the whole subtree. | |
| 25833 */ | |
| 25834 *skip = 1; | |
| 25835 return (0); | |
| 25836 } | |
| 25837 { | |
| 25838 xmlSchemaElementPtr decl = NULL; | |
| 25839 | |
| 25840 decl = xmlSchemaGetElem(vctxt->schema, | |
| 25841 vctxt->inode->localName, vctxt->inode->nsName); | |
| 25842 if (decl != NULL) { | |
| 25843 vctxt->inode->decl = decl; | |
| 25844 return (0); | |
| 25845 } | |
| 25846 } | |
| 25847 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) { | |
| 25848 /* VAL TODO: Change to proper error code. */ | |
| 25849 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */ | |
| 25850 "No matching global element declaration available, but " | |
| 25851 "demanded by the strict wildcard"); | |
| 25852 return (vctxt->err); | |
| 25853 } | |
| 25854 if (vctxt->nbAttrInfos != 0) { | |
| 25855 xmlSchemaAttrInfoPtr iattr; | |
| 25856 /* | |
| 25857 * SPEC Validation Rule: Schema-Validity Assessment (Element) | |
| 25858 * (1.2.1.2.1) - (1.2.1.2.3 ) | |
| 25859 * | |
| 25860 * Use the xsi:type attribute for the type definition. | |
| 25861 */ | |
| 25862 iattr = xmlSchemaGetMetaAttrInfo(vctxt, | |
| 25863 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE); | |
| 25864 if (iattr != NULL) { | |
| 25865 if (xmlSchemaProcessXSIType(vctxt, iattr, | |
| 25866 &(vctxt->inode->typeDef), NULL) == -1) { | |
| 25867 VERROR_INT("xmlSchemaValidateElemWildcard", | |
| 25868 "calling xmlSchemaProcessXSIType() to " | |
| 25869 "process the attribute 'xsi:nil'"); | |
| 25870 return (-1); | |
| 25871 } | |
| 25872 /* | |
| 25873 * Don't return an error on purpose. | |
| 25874 */ | |
| 25875 return (0); | |
| 25876 } | |
| 25877 } | |
| 25878 /* | |
| 25879 * SPEC Validation Rule: Schema-Validity Assessment (Element) | |
| 25880 * | |
| 25881 * Fallback to "anyType". | |
| 25882 */ | |
| 25883 vctxt->inode->typeDef = | |
| 25884 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); | |
| 25885 return (0); | |
| 25886 } | |
| 25887 | |
| 25888 /* | |
| 25889 * xmlSchemaCheckCOSValidDefault: | |
| 25890 * | |
| 25891 * This will be called if: not nilled, no content and a default/fixed | |
| 25892 * value is provided. | |
| 25893 */ | |
| 25894 | |
| 25895 static int | |
| 25896 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt, | |
| 25897 const xmlChar *value, | |
| 25898 xmlSchemaValPtr *val) | |
| 25899 { | |
| 25900 int ret = 0; | |
| 25901 xmlSchemaNodeInfoPtr inode = vctxt->inode; | |
| 25902 | |
| 25903 /* | |
| 25904 * cos-valid-default: | |
| 25905 * Schema Component Constraint: Element Default Valid (Immediate) | |
| 25906 * For a string to be a valid default with respect to a type | |
| 25907 * definition the appropriate case among the following must be true: | |
| 25908 */ | |
| 25909 if WXS_IS_COMPLEX(inode->typeDef) { | |
| 25910 /* | |
| 25911 * Complex type. | |
| 25912 * | |
| 25913 * SPEC (2.1) "its {content type} must be a simple type definition | |
| 25914 * or mixed." | |
| 25915 * SPEC (2.2.2) "If the {content type} is mixed, then the {content | |
| 25916 * type}'s particle must be `emptiable` as defined by | |
| 25917 * Particle Emptiable ($3.9.6)." | |
| 25918 */ | |
| 25919 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) && | |
| 25920 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) || | |
| 25921 (! WXS_EMPTIABLE(inode->typeDef)))) { | |
| 25922 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1; | |
| 25923 /* NOTE that this covers (2.2.2) as well. */ | |
| 25924 VERROR(ret, NULL, | |
| 25925 "For a string to be a valid default, the type definition " | |
| 25926 "must be a simple type or a complex type with simple content " | |
| 25927 "or mixed content and a particle emptiable"); | |
| 25928 return(ret); | |
| 25929 } | |
| 25930 } | |
| 25931 /* | |
| 25932 * 1 If the type definition is a simple type definition, then the string | |
| 25933 * must be `valid` with respect to that definition as defined by String | |
| 25934 * Valid ($3.14.4). | |
| 25935 * | |
| 25936 * AND | |
| 25937 * | |
| 25938 * 2.2.1 If the {content type} is a simple type definition, then the | |
| 25939 * string must be `valid` with respect to that simple type definition | |
| 25940 * as defined by String Valid ($3.14.4). | |
| 25941 */ | |
| 25942 if (WXS_IS_SIMPLE(inode->typeDef)) { | |
| 25943 | |
| 25944 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt, | |
| 25945 NULL, inode->typeDef, value, val, 1, 1, 0); | |
| 25946 | |
| 25947 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { | |
| 25948 | |
| 25949 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt, | |
| 25950 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0); | |
| 25951 } | |
| 25952 if (ret < 0) { | |
| 25953 VERROR_INT("xmlSchemaCheckCOSValidDefault", | |
| 25954 "calling xmlSchemaVCheckCVCSimpleType()"); | |
| 25955 } | |
| 25956 return (ret); | |
| 25957 } | |
| 25958 | |
| 25959 static void | |
| 25960 xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED, | |
| 25961 const xmlChar * name ATTRIBUTE_UNUSED, | |
| 25962 xmlSchemaElementPtr item, | |
| 25963 xmlSchemaNodeInfoPtr inode) | |
| 25964 { | |
| 25965 inode->decl = item; | |
| 25966 #ifdef DEBUG_CONTENT | |
| 25967 { | |
| 25968 xmlChar *str = NULL; | |
| 25969 | |
| 25970 if (item->type == XML_SCHEMA_TYPE_ELEMENT) { | |
| 25971 xmlGenericError(xmlGenericErrorContext, | |
| 25972 "AUTOMATON callback for '%s' [declaration]\n", | |
| 25973 xmlSchemaFormatQName(&str, | |
| 25974 inode->localName, inode->nsName)); | |
| 25975 } else { | |
| 25976 xmlGenericError(xmlGenericErrorContext, | |
| 25977 "AUTOMATON callback for '%s' [wildcard]\n", | |
| 25978 xmlSchemaFormatQName(&str, | |
| 25979 inode->localName, inode->nsName)); | |
| 25980 | |
| 25981 } | |
| 25982 FREE_AND_NULL(str) | |
| 25983 } | |
| 25984 #endif | |
| 25985 } | |
| 25986 | |
| 25987 static int | |
| 25988 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt) | |
| 25989 { | |
| 25990 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt); | |
| 25991 if (vctxt->inode == NULL) { | |
| 25992 VERROR_INT("xmlSchemaValidatorPushElem", | |
| 25993 "calling xmlSchemaGetFreshElemInfo()"); | |
| 25994 return (-1); | |
| 25995 } | |
| 25996 vctxt->nbAttrInfos = 0; | |
| 25997 return (0); | |
| 25998 } | |
| 25999 | |
| 26000 static int | |
| 26001 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt, | |
| 26002 xmlSchemaNodeInfoPtr inode, | |
| 26003 xmlSchemaTypePtr type, | |
| 26004 const xmlChar *value) | |
| 26005 { | |
| 26006 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED) | |
| 26007 return (xmlSchemaVCheckCVCSimpleType( | |
| 26008 ACTXT_CAST vctxt, NULL, | |
| 26009 type, value, &(inode->val), 1, 1, 0)); | |
| 26010 else | |
| 26011 return (xmlSchemaVCheckCVCSimpleType( | |
| 26012 ACTXT_CAST vctxt, NULL, | |
| 26013 type, value, NULL, 1, 0, 0)); | |
| 26014 } | |
| 26015 | |
| 26016 | |
| 26017 | |
| 26018 /* | |
| 26019 * Process END of element. | |
| 26020 */ | |
| 26021 static int | |
| 26022 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt) | |
| 26023 { | |
| 26024 int ret = 0; | |
| 26025 xmlSchemaNodeInfoPtr inode = vctxt->inode; | |
| 26026 | |
| 26027 if (vctxt->nbAttrInfos != 0) | |
| 26028 xmlSchemaClearAttrInfos(vctxt); | |
| 26029 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) { | |
| 26030 /* | |
| 26031 * This element was not expected; | |
| 26032 * we will not validate child elements of broken parents. | |
| 26033 * Skip validation of all content of the parent. | |
| 26034 */ | |
| 26035 vctxt->skipDepth = vctxt->depth -1; | |
| 26036 goto end_elem; | |
| 26037 } | |
| 26038 if ((inode->typeDef == NULL) || | |
| 26039 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) { | |
| 26040 /* | |
| 26041 * 1. the type definition might be missing if the element was | |
| 26042 * error prone | |
| 26043 * 2. it might be abstract. | |
| 26044 */ | |
| 26045 goto end_elem; | |
| 26046 } | |
| 26047 /* | |
| 26048 * Check the content model. | |
| 26049 */ | |
| 26050 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) || | |
| 26051 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) { | |
| 26052 | |
| 26053 /* | |
| 26054 * Workaround for "anyType". | |
| 26055 */ | |
| 26056 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE) | |
| 26057 goto character_content; | |
| 26058 | |
| 26059 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) { | |
| 26060 xmlChar *values[10]; | |
| 26061 int terminal, nbval = 10, nbneg; | |
| 26062 | |
| 26063 if (inode->regexCtxt == NULL) { | |
| 26064 /* | |
| 26065 * Create the regex context. | |
| 26066 */ | |
| 26067 inode->regexCtxt = | |
| 26068 xmlRegNewExecCtxt(inode->typeDef->contModel, | |
| 26069 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback, | |
| 26070 vctxt); | |
| 26071 if (inode->regexCtxt == NULL) { | |
| 26072 VERROR_INT("xmlSchemaValidatorPopElem", | |
| 26073 "failed to create a regex context"); | |
| 26074 goto internal_error; | |
| 26075 } | |
| 26076 #ifdef DEBUG_AUTOMATA | |
| 26077 xmlGenericError(xmlGenericErrorContext, | |
| 26078 "AUTOMATON create on '%s'\n", inode->localName); | |
| 26079 #endif | |
| 26080 } | |
| 26081 | |
| 26082 /* | |
| 26083 * Do not check further content if the node has been nilled | |
| 26084 */ | |
| 26085 if (INODE_NILLED(inode)) { | |
| 26086 ret = 0; | |
| 26087 #ifdef DEBUG_AUTOMATA | |
| 26088 xmlGenericError(xmlGenericErrorContext, | |
| 26089 "AUTOMATON succeeded on nilled '%s'\n", | |
| 26090 inode->localName); | |
| 26091 #endif | |
| 26092 goto skip_nilled; | |
| 26093 } | |
| 26094 | |
| 26095 /* | |
| 26096 * Get hold of the still expected content, since a further | |
| 26097 * call to xmlRegExecPushString() will loose this information. | |
| 26098 */ | |
| 26099 xmlRegExecNextValues(inode->regexCtxt, | |
| 26100 &nbval, &nbneg, &values[0], &terminal); | |
| 26101 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL); | |
| 26102 if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) { | |
| 26103 /* | |
| 26104 * Still missing something. | |
| 26105 */ | |
| 26106 ret = 1; | |
| 26107 inode->flags |= | |
| 26108 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT; | |
| 26109 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt, | |
| 26110 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL, | |
| 26111 "Missing child element(s)", | |
| 26112 nbval, nbneg, values); | |
| 26113 #ifdef DEBUG_AUTOMATA | |
| 26114 xmlGenericError(xmlGenericErrorContext, | |
| 26115 "AUTOMATON missing ERROR on '%s'\n", | |
| 26116 inode->localName); | |
| 26117 #endif | |
| 26118 } else { | |
| 26119 /* | |
| 26120 * Content model is satisfied. | |
| 26121 */ | |
| 26122 ret = 0; | |
| 26123 #ifdef DEBUG_AUTOMATA | |
| 26124 xmlGenericError(xmlGenericErrorContext, | |
| 26125 "AUTOMATON succeeded on '%s'\n", | |
| 26126 inode->localName); | |
| 26127 #endif | |
| 26128 } | |
| 26129 | |
| 26130 } | |
| 26131 } | |
| 26132 | |
| 26133 skip_nilled: | |
| 26134 | |
| 26135 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS) | |
| 26136 goto end_elem; | |
| 26137 | |
| 26138 character_content: | |
| 26139 | |
| 26140 if (vctxt->value != NULL) { | |
| 26141 xmlSchemaFreeValue(vctxt->value); | |
| 26142 vctxt->value = NULL; | |
| 26143 } | |
| 26144 /* | |
| 26145 * Check character content. | |
| 26146 */ | |
| 26147 if (inode->decl == NULL) { | |
| 26148 /* | |
| 26149 * Speedup if no declaration exists. | |
| 26150 */ | |
| 26151 if (WXS_IS_SIMPLE(inode->typeDef)) { | |
| 26152 ret = xmlSchemaVCheckINodeDataType(vctxt, | |
| 26153 inode, inode->typeDef, inode->value); | |
| 26154 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { | |
| 26155 ret = xmlSchemaVCheckINodeDataType(vctxt, | |
| 26156 inode, inode->typeDef->contentTypeDef, | |
| 26157 inode->value); | |
| 26158 } | |
| 26159 if (ret < 0) { | |
| 26160 VERROR_INT("xmlSchemaValidatorPopElem", | |
| 26161 "calling xmlSchemaVCheckCVCSimpleType()"); | |
| 26162 goto internal_error; | |
| 26163 } | |
| 26164 goto end_elem; | |
| 26165 } | |
| 26166 /* | |
| 26167 * cvc-elt (3.3.4) : 5 | |
| 26168 * The appropriate case among the following must be true: | |
| 26169 */ | |
| 26170 /* | |
| 26171 * cvc-elt (3.3.4) : 5.1 | |
| 26172 * If the declaration has a {value constraint}, | |
| 26173 * the item has neither element nor character [children] and | |
| 26174 * clause 3.2 has not applied, then all of the following must be true: | |
| 26175 */ | |
| 26176 if ((inode->decl->value != NULL) && | |
| 26177 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) && | |
| 26178 (! INODE_NILLED(inode))) { | |
| 26179 /* | |
| 26180 * cvc-elt (3.3.4) : 5.1.1 | |
| 26181 * If the `actual type definition` is a `local type definition` | |
| 26182 * then the canonical lexical representation of the {value constraint} | |
| 26183 * value must be a valid default for the `actual type definition` as | |
| 26184 * defined in Element Default Valid (Immediate) ($3.3.6). | |
| 26185 */ | |
| 26186 /* | |
| 26187 * NOTE: 'local' above means types acquired by xsi:type. | |
| 26188 * NOTE: Although the *canonical* value is stated, it is not | |
| 26189 * relevant if canonical or not. Additionally XML Schema 1.1 | |
| 26190 * will removed this requirement as well. | |
| 26191 */ | |
| 26192 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) { | |
| 26193 | |
| 26194 ret = xmlSchemaCheckCOSValidDefault(vctxt, | |
| 26195 inode->decl->value, &(inode->val)); | |
| 26196 if (ret != 0) { | |
| 26197 if (ret < 0) { | |
| 26198 VERROR_INT("xmlSchemaValidatorPopElem", | |
| 26199 "calling xmlSchemaCheckCOSValidDefault()"); | |
| 26200 goto internal_error; | |
| 26201 } | |
| 26202 goto end_elem; | |
| 26203 } | |
| 26204 /* | |
| 26205 * Stop here, to avoid redundant validation of the value | |
| 26206 * (see following). | |
| 26207 */ | |
| 26208 goto default_psvi; | |
| 26209 } | |
| 26210 /* | |
| 26211 * cvc-elt (3.3.4) : 5.1.2 | |
| 26212 * The element information item with the canonical lexical | |
| 26213 * representation of the {value constraint} value used as its | |
| 26214 * `normalized value` must be `valid` with respect to the | |
| 26215 * `actual type definition` as defined by Element Locally Valid (Type) | |
| 26216 * ($3.3.4). | |
| 26217 */ | |
| 26218 if (WXS_IS_SIMPLE(inode->typeDef)) { | |
| 26219 ret = xmlSchemaVCheckINodeDataType(vctxt, | |
| 26220 inode, inode->typeDef, inode->decl->value); | |
| 26221 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { | |
| 26222 ret = xmlSchemaVCheckINodeDataType(vctxt, | |
| 26223 inode, inode->typeDef->contentTypeDef, | |
| 26224 inode->decl->value); | |
| 26225 } | |
| 26226 if (ret != 0) { | |
| 26227 if (ret < 0) { | |
| 26228 VERROR_INT("xmlSchemaValidatorPopElem", | |
| 26229 "calling xmlSchemaVCheckCVCSimpleType()"); | |
| 26230 goto internal_error; | |
| 26231 } | |
| 26232 goto end_elem; | |
| 26233 } | |
| 26234 | |
| 26235 default_psvi: | |
| 26236 /* | |
| 26237 * PSVI: Create a text node on the instance element. | |
| 26238 */ | |
| 26239 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) && | |
| 26240 (inode->node != NULL)) { | |
| 26241 xmlNodePtr textChild; | |
| 26242 xmlChar *normValue; | |
| 26243 /* | |
| 26244 * VAL TODO: Normalize the value. | |
| 26245 */ | |
| 26246 normValue = xmlSchemaNormalizeValue(inode->typeDef, | |
| 26247 inode->decl->value); | |
| 26248 if (normValue != NULL) { | |
| 26249 textChild = xmlNewText(BAD_CAST normValue); | |
| 26250 xmlFree(normValue); | |
| 26251 } else | |
| 26252 textChild = xmlNewText(inode->decl->value); | |
| 26253 if (textChild == NULL) { | |
| 26254 VERROR_INT("xmlSchemaValidatorPopElem", | |
| 26255 "calling xmlNewText()"); | |
| 26256 goto internal_error; | |
| 26257 } else | |
| 26258 xmlAddChild(inode->node, textChild); | |
| 26259 } | |
| 26260 | |
| 26261 } else if (! INODE_NILLED(inode)) { | |
| 26262 /* | |
| 26263 * 5.2.1 The element information item must be `valid` with respect | |
| 26264 * to the `actual type definition` as defined by Element Locally | |
| 26265 * Valid (Type) ($3.3.4). | |
| 26266 */ | |
| 26267 if (WXS_IS_SIMPLE(inode->typeDef)) { | |
| 26268 /* | |
| 26269 * SPEC (cvc-type) (3.1) | |
| 26270 * "If the type definition is a simple type definition, ..." | |
| 26271 * (3.1.3) "If clause 3.2 of Element Locally Valid | |
| 26272 * (Element) ($3.3.4) did not apply, then the `normalized value` | |
| 26273 * must be `valid` with respect to the type definition as defined | |
| 26274 * by String Valid ($3.14.4). | |
| 26275 */ | |
| 26276 ret = xmlSchemaVCheckINodeDataType(vctxt, | |
| 26277 inode, inode->typeDef, inode->value); | |
| 26278 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { | |
| 26279 /* | |
| 26280 * SPEC (cvc-type) (3.2) "If the type definition is a complex type | |
| 26281 * definition, then the element information item must be | |
| 26282 * `valid` with respect to the type definition as per | |
| 26283 * Element Locally Valid (Complex Type) ($3.4.4);" | |
| 26284 * | |
| 26285 * SPEC (cvc-complex-type) (2.2) | |
| 26286 * "If the {content type} is a simple type definition, ... | |
| 26287 * the `normalized value` of the element information item is | |
| 26288 * `valid` with respect to that simple type definition as | |
| 26289 * defined by String Valid ($3.14.4)." | |
| 26290 */ | |
| 26291 ret = xmlSchemaVCheckINodeDataType(vctxt, | |
| 26292 inode, inode->typeDef->contentTypeDef, inode->value); | |
| 26293 } | |
| 26294 if (ret != 0) { | |
| 26295 if (ret < 0) { | |
| 26296 VERROR_INT("xmlSchemaValidatorPopElem", | |
| 26297 "calling xmlSchemaVCheckCVCSimpleType()"); | |
| 26298 goto internal_error; | |
| 26299 } | |
| 26300 goto end_elem; | |
| 26301 } | |
| 26302 /* | |
| 26303 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has | |
| 26304 * not applied, all of the following must be true: | |
| 26305 */ | |
| 26306 if ((inode->decl->value != NULL) && | |
| 26307 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) { | |
| 26308 | |
| 26309 /* | |
| 26310 * TODO: We will need a computed value, when comparison is | |
| 26311 * done on computed values. | |
| 26312 */ | |
| 26313 /* | |
| 26314 * 5.2.2.1 The element information item must have no element | |
| 26315 * information item [children]. | |
| 26316 */ | |
| 26317 if (inode->flags & | |
| 26318 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) { | |
| 26319 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1; | |
| 26320 VERROR(ret, NULL, | |
| 26321 "The content must not containt element nodes since " | |
| 26322 "there is a fixed value constraint"); | |
| 26323 goto end_elem; | |
| 26324 } else { | |
| 26325 /* | |
| 26326 * 5.2.2.2 The appropriate case among the following must | |
| 26327 * be true: | |
| 26328 */ | |
| 26329 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) { | |
| 26330 /* | |
| 26331 * 5.2.2.2.1 If the {content type} of the `actual type | |
| 26332 * definition` is mixed, then the *initial value* of the | |
| 26333 * item must match the canonical lexical representation | |
| 26334 * of the {value constraint} value. | |
| 26335 * | |
| 26336 * ... the *initial value* of an element information | |
| 26337 * item is the string composed of, in order, the | |
| 26338 * [character code] of each character information item in | |
| 26339 * the [children] of that element information item. | |
| 26340 */ | |
| 26341 if (! xmlStrEqual(inode->value, inode->decl->value)){ | |
| 26342 /* | |
| 26343 * VAL TODO: Report invalid & expected values as well. | |
| 26344 * VAL TODO: Implement the canonical stuff. | |
| 26345 */ | |
| 26346 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1; | |
| 26347 xmlSchemaCustomErr(ACTXT_CAST vctxt, | |
| 26348 ret, NULL, NULL, | |
| 26349 "The initial value '%s' does not match the fixed " | |
| 26350 "value constraint '%s'", | |
| 26351 inode->value, inode->decl->value); | |
| 26352 goto end_elem; | |
| 26353 } | |
| 26354 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { | |
| 26355 /* | |
| 26356 * 5.2.2.2.2 If the {content type} of the `actual type | |
| 26357 * definition` is a simple type definition, then the | |
| 26358 * *actual value* of the item must match the canonical | |
| 26359 * lexical representation of the {value constraint} value. | |
| 26360 */ | |
| 26361 /* | |
| 26362 * VAL TODO: *actual value* is the normalized value, impl. | |
| 26363 * this. | |
| 26364 * VAL TODO: Report invalid & expected values as well. | |
| 26365 * VAL TODO: Implement a comparison with the computed values. | |
| 26366 */ | |
| 26367 if (! xmlStrEqual(inode->value, | |
| 26368 inode->decl->value)) { | |
| 26369 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2; | |
| 26370 xmlSchemaCustomErr(ACTXT_CAST vctxt, | |
| 26371 ret, NULL, NULL, | |
| 26372 "The actual value '%s' does not match the fixed " | |
| 26373 "value constraint '%s'", | |
| 26374 inode->value, | |
| 26375 inode->decl->value); | |
| 26376 goto end_elem; | |
| 26377 } | |
| 26378 } | |
| 26379 } | |
| 26380 } | |
| 26381 } | |
| 26382 | |
| 26383 end_elem: | |
| 26384 if (vctxt->depth < 0) { | |
| 26385 /* TODO: raise error? */ | |
| 26386 return (0); | |
| 26387 } | |
| 26388 if (vctxt->depth == vctxt->skipDepth) | |
| 26389 vctxt->skipDepth = -1; | |
| 26390 /* | |
| 26391 * Evaluate the history of XPath state objects. | |
| 26392 */ | |
| 26393 if (inode->appliedXPath && | |
| 26394 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)) | |
| 26395 goto internal_error; | |
| 26396 /* | |
| 26397 * MAYBE TODO: | |
| 26398 * SPEC (6) "The element information item must be `valid` with | |
| 26399 * respect to each of the {identity-constraint definitions} as per | |
| 26400 * Identity-constraint Satisfied ($3.11.4)." | |
| 26401 */ | |
| 26402 /* | |
| 26403 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables | |
| 26404 * need to be built in any case. | |
| 26405 * We will currently build IDC node-tables and bubble them only if | |
| 26406 * keyrefs do exist. | |
| 26407 */ | |
| 26408 | |
| 26409 /* | |
| 26410 * Add the current IDC target-nodes to the IDC node-tables. | |
| 26411 */ | |
| 26412 if ((inode->idcMatchers != NULL) && | |
| 26413 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables)) | |
| 26414 { | |
| 26415 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1) | |
| 26416 goto internal_error; | |
| 26417 } | |
| 26418 /* | |
| 26419 * Validate IDC keyrefs. | |
| 26420 */ | |
| 26421 if (vctxt->inode->hasKeyrefs) | |
| 26422 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1) | |
| 26423 goto internal_error; | |
| 26424 /* | |
| 26425 * Merge/free the IDC table. | |
| 26426 */ | |
| 26427 if (inode->idcTable != NULL) { | |
| 26428 #ifdef DEBUG_IDC_NODE_TABLE | |
| 26429 xmlSchemaDebugDumpIDCTable(stdout, | |
| 26430 inode->nsName, | |
| 26431 inode->localName, | |
| 26432 inode->idcTable); | |
| 26433 #endif | |
| 26434 if ((vctxt->depth > 0) && | |
| 26435 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables)) | |
| 26436 { | |
| 26437 /* | |
| 26438 * Merge the IDC node table with the table of the parent node. | |
| 26439 */ | |
| 26440 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1) | |
| 26441 goto internal_error; | |
| 26442 } | |
| 26443 } | |
| 26444 /* | |
| 26445 * Clear the current ielem. | |
| 26446 * VAL TODO: Don't free the PSVI IDC tables if they are | |
| 26447 * requested for the PSVI. | |
| 26448 */ | |
| 26449 xmlSchemaClearElemInfo(vctxt, inode); | |
| 26450 /* | |
| 26451 * Skip further processing if we are on the validation root. | |
| 26452 */ | |
| 26453 if (vctxt->depth == 0) { | |
| 26454 vctxt->depth--; | |
| 26455 vctxt->inode = NULL; | |
| 26456 return (0); | |
| 26457 } | |
| 26458 /* | |
| 26459 * Reset the keyrefDepth if needed. | |
| 26460 */ | |
| 26461 if (vctxt->aidcs != NULL) { | |
| 26462 xmlSchemaIDCAugPtr aidc = vctxt->aidcs; | |
| 26463 do { | |
| 26464 if (aidc->keyrefDepth == vctxt->depth) { | |
| 26465 /* | |
| 26466 * A 'keyrefDepth' of a key/unique IDC matches the current | |
| 26467 * depth, this means that we are leaving the scope of the | |
| 26468 * top-most keyref IDC which refers to this IDC. | |
| 26469 */ | |
| 26470 aidc->keyrefDepth = -1; | |
| 26471 } | |
| 26472 aidc = aidc->next; | |
| 26473 } while (aidc != NULL); | |
| 26474 } | |
| 26475 vctxt->depth--; | |
| 26476 vctxt->inode = vctxt->elemInfos[vctxt->depth]; | |
| 26477 /* | |
| 26478 * VAL TODO: 7 If the element information item is the `validation root`, it m
ust be | |
| 26479 * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4). | |
| 26480 */ | |
| 26481 return (ret); | |
| 26482 | |
| 26483 internal_error: | |
| 26484 vctxt->err = -1; | |
| 26485 return (-1); | |
| 26486 } | |
| 26487 | |
| 26488 /* | |
| 26489 * 3.4.4 Complex Type Definition Validation Rules | |
| 26490 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type) | |
| 26491 */ | |
| 26492 static int | |
| 26493 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt) | |
| 26494 { | |
| 26495 xmlSchemaNodeInfoPtr pielem; | |
| 26496 xmlSchemaTypePtr ptype; | |
| 26497 int ret = 0; | |
| 26498 | |
| 26499 if (vctxt->depth <= 0) { | |
| 26500 VERROR_INT("xmlSchemaValidateChildElem", | |
| 26501 "not intended for the validation root"); | |
| 26502 return (-1); | |
| 26503 } | |
| 26504 pielem = vctxt->elemInfos[vctxt->depth -1]; | |
| 26505 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) | |
| 26506 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; | |
| 26507 /* | |
| 26508 * Handle 'nilled' elements. | |
| 26509 */ | |
| 26510 if (INODE_NILLED(pielem)) { | |
| 26511 /* | |
| 26512 * SPEC (cvc-elt) (3.3.4) : (3.2.1) | |
| 26513 */ | |
| 26514 ACTIVATE_PARENT_ELEM; | |
| 26515 ret = XML_SCHEMAV_CVC_ELT_3_2_1; | |
| 26516 VERROR(ret, NULL, | |
| 26517 "Neither character nor element content is allowed, " | |
| 26518 "because the element was 'nilled'"); | |
| 26519 ACTIVATE_ELEM; | |
| 26520 goto unexpected_elem; | |
| 26521 } | |
| 26522 | |
| 26523 ptype = pielem->typeDef; | |
| 26524 | |
| 26525 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) { | |
| 26526 /* | |
| 26527 * Workaround for "anyType": we have currently no content model | |
| 26528 * assigned for "anyType", so handle it explicitely. | |
| 26529 * "anyType" has an unbounded, lax "any" wildcard. | |
| 26530 */ | |
| 26531 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema, | |
| 26532 vctxt->inode->localName, | |
| 26533 vctxt->inode->nsName); | |
| 26534 | |
| 26535 if (vctxt->inode->decl == NULL) { | |
| 26536 xmlSchemaAttrInfoPtr iattr; | |
| 26537 /* | |
| 26538 * Process "xsi:type". | |
| 26539 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3) | |
| 26540 */ | |
| 26541 iattr = xmlSchemaGetMetaAttrInfo(vctxt, | |
| 26542 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE); | |
| 26543 if (iattr != NULL) { | |
| 26544 ret = xmlSchemaProcessXSIType(vctxt, iattr, | |
| 26545 &(vctxt->inode->typeDef), NULL); | |
| 26546 if (ret != 0) { | |
| 26547 if (ret == -1) { | |
| 26548 VERROR_INT("xmlSchemaValidateChildElem", | |
| 26549 "calling xmlSchemaProcessXSIType() to " | |
| 26550 "process the attribute 'xsi:nil'"); | |
| 26551 return (-1); | |
| 26552 } | |
| 26553 return (ret); | |
| 26554 } | |
| 26555 } else { | |
| 26556 /* | |
| 26557 * Fallback to "anyType". | |
| 26558 * | |
| 26559 * SPEC (cvc-assess-elt) | |
| 26560 * "If the item cannot be `strictly assessed`, [...] | |
| 26561 * an element information item's schema validity may be laxly | |
| 26562 * assessed if its `context-determined declaration` is not | |
| 26563 * skip by `validating` with respect to the `ur-type | |
| 26564 * definition` as per Element Locally Valid (Type) ($3.3.4)." | |
| 26565 */ | |
| 26566 vctxt->inode->typeDef = | |
| 26567 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); | |
| 26568 } | |
| 26569 } | |
| 26570 return (0); | |
| 26571 } | |
| 26572 | |
| 26573 switch (ptype->contentType) { | |
| 26574 case XML_SCHEMA_CONTENT_EMPTY: | |
| 26575 /* | |
| 26576 * SPEC (2.1) "If the {content type} is empty, then the | |
| 26577 * element information item has no character or element | |
| 26578 * information item [children]." | |
| 26579 */ | |
| 26580 ACTIVATE_PARENT_ELEM | |
| 26581 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1; | |
| 26582 VERROR(ret, NULL, | |
| 26583 "Element content is not allowed, " | |
| 26584 "because the content type is empty"); | |
| 26585 ACTIVATE_ELEM | |
| 26586 goto unexpected_elem; | |
| 26587 break; | |
| 26588 | |
| 26589 case XML_SCHEMA_CONTENT_MIXED: | |
| 26590 case XML_SCHEMA_CONTENT_ELEMENTS: { | |
| 26591 xmlRegExecCtxtPtr regexCtxt; | |
| 26592 xmlChar *values[10]; | |
| 26593 int terminal, nbval = 10, nbneg; | |
| 26594 | |
| 26595 /* VAL TODO: Optimized "anyType" validation.*/ | |
| 26596 | |
| 26597 if (ptype->contModel == NULL) { | |
| 26598 VERROR_INT("xmlSchemaValidateChildElem", | |
| 26599 "type has elem content but no content model"); | |
| 26600 return (-1); | |
| 26601 } | |
| 26602 /* | |
| 26603 * Safety belf for evaluation if the cont. model was already | |
| 26604 * examined to be invalid. | |
| 26605 */ | |
| 26606 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) { | |
| 26607 VERROR_INT("xmlSchemaValidateChildElem", | |
| 26608 "validating elem, but elem content is already invalid"); | |
| 26609 return (-1); | |
| 26610 } | |
| 26611 | |
| 26612 regexCtxt = pielem->regexCtxt; | |
| 26613 if (regexCtxt == NULL) { | |
| 26614 /* | |
| 26615 * Create the regex context. | |
| 26616 */ | |
| 26617 regexCtxt = xmlRegNewExecCtxt(ptype->contModel, | |
| 26618 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback, | |
| 26619 vctxt); | |
| 26620 if (regexCtxt == NULL) { | |
| 26621 VERROR_INT("xmlSchemaValidateChildElem", | |
| 26622 "failed to create a regex context"); | |
| 26623 return (-1); | |
| 26624 } | |
| 26625 pielem->regexCtxt = regexCtxt; | |
| 26626 #ifdef DEBUG_AUTOMATA | |
| 26627 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'
\n", | |
| 26628 pielem->localName); | |
| 26629 #endif | |
| 26630 } | |
| 26631 | |
| 26632 /* | |
| 26633 * SPEC (2.4) "If the {content type} is element-only or mixed, | |
| 26634 * then the sequence of the element information item's | |
| 26635 * element information item [children], if any, taken in | |
| 26636 * order, is `valid` with respect to the {content type}'s | |
| 26637 * particle, as defined in Element Sequence Locally Valid | |
| 26638 * (Particle) ($3.9.4)." | |
| 26639 */ | |
| 26640 ret = xmlRegExecPushString2(regexCtxt, | |
| 26641 vctxt->inode->localName, | |
| 26642 vctxt->inode->nsName, | |
| 26643 vctxt->inode); | |
| 26644 #ifdef DEBUG_AUTOMATA | |
| 26645 if (ret < 0) | |
| 26646 xmlGenericError(xmlGenericErrorContext, | |
| 26647 "AUTOMATON push ERROR for '%s' on '%s'\n", | |
| 26648 vctxt->inode->localName, pielem->localName); | |
| 26649 else | |
| 26650 xmlGenericError(xmlGenericErrorContext, | |
| 26651 "AUTOMATON push OK for '%s' on '%s'\n", | |
| 26652 vctxt->inode->localName, pielem->localName); | |
| 26653 #endif | |
| 26654 if (vctxt->err == XML_SCHEMAV_INTERNAL) { | |
| 26655 VERROR_INT("xmlSchemaValidateChildElem", | |
| 26656 "calling xmlRegExecPushString2()"); | |
| 26657 return (-1); | |
| 26658 } | |
| 26659 if (ret < 0) { | |
| 26660 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg, | |
| 26661 &values[0], &terminal); | |
| 26662 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt, | |
| 26663 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL, | |
| 26664 "This element is not expected", | |
| 26665 nbval, nbneg, values); | |
| 26666 ret = vctxt->err; | |
| 26667 goto unexpected_elem; | |
| 26668 } else | |
| 26669 ret = 0; | |
| 26670 } | |
| 26671 break; | |
| 26672 case XML_SCHEMA_CONTENT_SIMPLE: | |
| 26673 case XML_SCHEMA_CONTENT_BASIC: | |
| 26674 ACTIVATE_PARENT_ELEM | |
| 26675 if (WXS_IS_COMPLEX(ptype)) { | |
| 26676 /* | |
| 26677 * SPEC (cvc-complex-type) (2.2) | |
| 26678 * "If the {content type} is a simple type definition, then | |
| 26679 * the element information item has no element information | |
| 26680 * item [children], ..." | |
| 26681 */ | |
| 26682 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2; | |
| 26683 VERROR(ret, NULL, "Element content is not allowed, " | |
| 26684 "because the content type is a simple type definition"); | |
| 26685 } else { | |
| 26686 /* | |
| 26687 * SPEC (cvc-type) (3.1.2) "The element information item must | |
| 26688 * have no element information item [children]." | |
| 26689 */ | |
| 26690 ret = XML_SCHEMAV_CVC_TYPE_3_1_2; | |
| 26691 VERROR(ret, NULL, "Element content is not allowed, " | |
| 26692 "because the type definition is simple"); | |
| 26693 } | |
| 26694 ACTIVATE_ELEM | |
| 26695 ret = vctxt->err; | |
| 26696 goto unexpected_elem; | |
| 26697 break; | |
| 26698 | |
| 26699 default: | |
| 26700 break; | |
| 26701 } | |
| 26702 return (ret); | |
| 26703 unexpected_elem: | |
| 26704 /* | |
| 26705 * Pop this element and set the skipDepth to skip | |
| 26706 * all further content of the parent element. | |
| 26707 */ | |
| 26708 vctxt->skipDepth = vctxt->depth; | |
| 26709 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED; | |
| 26710 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT; | |
| 26711 return (ret); | |
| 26712 } | |
| 26713 | |
| 26714 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1 | |
| 26715 #define XML_SCHEMA_PUSH_TEXT_CREATED 2 | |
| 26716 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3 | |
| 26717 | |
| 26718 static int | |
| 26719 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt, | |
| 26720 int nodeType, const xmlChar *value, int len, | |
| 26721 int mode, int *consumed) | |
| 26722 { | |
| 26723 /* | |
| 26724 * Unfortunately we have to duplicate the text sometimes. | |
| 26725 * OPTIMIZE: Maybe we could skip it, if: | |
| 26726 * 1. content type is simple | |
| 26727 * 2. whitespace is "collapse" | |
| 26728 * 3. it consists of whitespace only | |
| 26729 * | |
| 26730 * Process character content. | |
| 26731 */ | |
| 26732 if (consumed != NULL) | |
| 26733 *consumed = 0; | |
| 26734 if (INODE_NILLED(vctxt->inode)) { | |
| 26735 /* | |
| 26736 * SPEC cvc-elt (3.3.4 - 3.2.1) | |
| 26737 * "The element information item must have no character or | |
| 26738 * element information item [children]." | |
| 26739 */ | |
| 26740 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL, | |
| 26741 "Neither character nor element content is allowed " | |
| 26742 "because the element is 'nilled'"); | |
| 26743 return (vctxt->err); | |
| 26744 } | |
| 26745 /* | |
| 26746 * SPEC (2.1) "If the {content type} is empty, then the | |
| 26747 * element information item has no character or element | |
| 26748 * information item [children]." | |
| 26749 */ | |
| 26750 if (vctxt->inode->typeDef->contentType == | |
| 26751 XML_SCHEMA_CONTENT_EMPTY) { | |
| 26752 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL, | |
| 26753 "Character content is not allowed, " | |
| 26754 "because the content type is empty"); | |
| 26755 return (vctxt->err); | |
| 26756 } | |
| 26757 | |
| 26758 if (vctxt->inode->typeDef->contentType == | |
| 26759 XML_SCHEMA_CONTENT_ELEMENTS) { | |
| 26760 if ((nodeType != XML_TEXT_NODE) || | |
| 26761 (! xmlSchemaIsBlank((xmlChar *) value, len))) { | |
| 26762 /* | |
| 26763 * SPEC cvc-complex-type (2.3) | |
| 26764 * "If the {content type} is element-only, then the | |
| 26765 * element information item has no character information | |
| 26766 * item [children] other than those whose [character | |
| 26767 * code] is defined as a white space in [XML 1.0 (Second | |
| 26768 * Edition)]." | |
| 26769 */ | |
| 26770 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL, | |
| 26771 "Character content other than whitespace is not allowed " | |
| 26772 "because the content type is 'element-only'"); | |
| 26773 return (vctxt->err); | |
| 26774 } | |
| 26775 return (0); | |
| 26776 } | |
| 26777 | |
| 26778 if ((value == NULL) || (value[0] == 0)) | |
| 26779 return (0); | |
| 26780 /* | |
| 26781 * Save the value. | |
| 26782 * NOTE that even if the content type is *mixed*, we need the | |
| 26783 * *initial value* for default/fixed value constraints. | |
| 26784 */ | |
| 26785 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) && | |
| 26786 ((vctxt->inode->decl == NULL) || | |
| 26787 (vctxt->inode->decl->value == NULL))) | |
| 26788 return (0); | |
| 26789 | |
| 26790 if (vctxt->inode->value == NULL) { | |
| 26791 /* | |
| 26792 * Set the value. | |
| 26793 */ | |
| 26794 switch (mode) { | |
| 26795 case XML_SCHEMA_PUSH_TEXT_PERSIST: | |
| 26796 /* | |
| 26797 * When working on a tree. | |
| 26798 */ | |
| 26799 vctxt->inode->value = value; | |
| 26800 break; | |
| 26801 case XML_SCHEMA_PUSH_TEXT_CREATED: | |
| 26802 /* | |
| 26803 * When working with the reader. | |
| 26804 * The value will be freed by the element info. | |
| 26805 */ | |
| 26806 vctxt->inode->value = value; | |
| 26807 if (consumed != NULL) | |
| 26808 *consumed = 1; | |
| 26809 vctxt->inode->flags |= | |
| 26810 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; | |
| 26811 break; | |
| 26812 case XML_SCHEMA_PUSH_TEXT_VOLATILE: | |
| 26813 /* | |
| 26814 * When working with SAX. | |
| 26815 * The value will be freed by the element info. | |
| 26816 */ | |
| 26817 if (len != -1) | |
| 26818 vctxt->inode->value = BAD_CAST xmlStrndup(value, len); | |
| 26819 else | |
| 26820 vctxt->inode->value = BAD_CAST xmlStrdup(value); | |
| 26821 vctxt->inode->flags |= | |
| 26822 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; | |
| 26823 break; | |
| 26824 default: | |
| 26825 break; | |
| 26826 } | |
| 26827 } else { | |
| 26828 if (len < 0) | |
| 26829 len = xmlStrlen(value); | |
| 26830 /* | |
| 26831 * Concat the value. | |
| 26832 */ | |
| 26833 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) { | |
| 26834 vctxt->inode->value = BAD_CAST xmlStrncat( | |
| 26835 (xmlChar *) vctxt->inode->value, value, len); | |
| 26836 } else { | |
| 26837 vctxt->inode->value = | |
| 26838 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len); | |
| 26839 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; | |
| 26840 } | |
| 26841 } | |
| 26842 | |
| 26843 return (0); | |
| 26844 } | |
| 26845 | |
| 26846 static int | |
| 26847 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt) | |
| 26848 { | |
| 26849 int ret = 0; | |
| 26850 | |
| 26851 if ((vctxt->skipDepth != -1) && | |
| 26852 (vctxt->depth >= vctxt->skipDepth)) { | |
| 26853 VERROR_INT("xmlSchemaValidateElem", | |
| 26854 "in skip-state"); | |
| 26855 goto internal_error; | |
| 26856 } | |
| 26857 if (vctxt->xsiAssemble) { | |
| 26858 /* | |
| 26859 * We will stop validation if there was an error during | |
| 26860 * dynamic schema construction. | |
| 26861 * Note that we simply set @skipDepth to 0, this could | |
| 26862 * mean that a streaming document via SAX would be | |
| 26863 * still read to the end but it won't be validated any more. | |
| 26864 * TODO: If we are sure how to stop the validation at once | |
| 26865 * for all input scenarios, then this should be changed to | |
| 26866 * instantly stop the validation. | |
| 26867 */ | |
| 26868 ret = xmlSchemaAssembleByXSI(vctxt); | |
| 26869 if (ret != 0) { | |
| 26870 if (ret == -1) | |
| 26871 goto internal_error; | |
| 26872 vctxt->skipDepth = 0; | |
| 26873 return(ret); | |
| 26874 } | |
| 26875 /* | |
| 26876 * Augment the IDC definitions for the main schema and all imported ones | |
| 26877 * NOTE: main schema is the first in the imported list | |
| 26878 */ | |
| 26879 xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugme
ntImportedIDC, vctxt); | |
| 26880 } | |
| 26881 if (vctxt->depth > 0) { | |
| 26882 /* | |
| 26883 * Validate this element against the content model | |
| 26884 * of the parent. | |
| 26885 */ | |
| 26886 ret = xmlSchemaValidateChildElem(vctxt); | |
| 26887 if (ret != 0) { | |
| 26888 if (ret < 0) { | |
| 26889 VERROR_INT("xmlSchemaValidateElem", | |
| 26890 "calling xmlSchemaStreamValidateChildElement()"); | |
| 26891 goto internal_error; | |
| 26892 } | |
| 26893 goto exit; | |
| 26894 } | |
| 26895 if (vctxt->depth == vctxt->skipDepth) | |
| 26896 goto exit; | |
| 26897 if ((vctxt->inode->decl == NULL) && | |
| 26898 (vctxt->inode->typeDef == NULL)) { | |
| 26899 VERROR_INT("xmlSchemaValidateElem", | |
| 26900 "the child element was valid but neither the " | |
| 26901 "declaration nor the type was set"); | |
| 26902 goto internal_error; | |
| 26903 } | |
| 26904 } else { | |
| 26905 /* | |
| 26906 * Get the declaration of the validation root. | |
| 26907 */ | |
| 26908 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema, | |
| 26909 vctxt->inode->localName, | |
| 26910 vctxt->inode->nsName); | |
| 26911 if (vctxt->inode->decl == NULL) { | |
| 26912 ret = XML_SCHEMAV_CVC_ELT_1; | |
| 26913 VERROR(ret, NULL, | |
| 26914 "No matching global declaration available " | |
| 26915 "for the validation root"); | |
| 26916 goto exit; | |
| 26917 } | |
| 26918 } | |
| 26919 | |
| 26920 if (vctxt->inode->decl == NULL) | |
| 26921 goto type_validation; | |
| 26922 | |
| 26923 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) { | |
| 26924 int skip; | |
| 26925 /* | |
| 26926 * Wildcards. | |
| 26927 */ | |
| 26928 ret = xmlSchemaValidateElemWildcard(vctxt, &skip); | |
| 26929 if (ret != 0) { | |
| 26930 if (ret < 0) { | |
| 26931 VERROR_INT("xmlSchemaValidateElem", | |
| 26932 "calling xmlSchemaValidateElemWildcard()"); | |
| 26933 goto internal_error; | |
| 26934 } | |
| 26935 goto exit; | |
| 26936 } | |
| 26937 if (skip) { | |
| 26938 vctxt->skipDepth = vctxt->depth; | |
| 26939 goto exit; | |
| 26940 } | |
| 26941 /* | |
| 26942 * The declaration might be set by the wildcard validation, | |
| 26943 * when the processContents is "lax" or "strict". | |
| 26944 */ | |
| 26945 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) { | |
| 26946 /* | |
| 26947 * Clear the "decl" field to not confuse further processing. | |
| 26948 */ | |
| 26949 vctxt->inode->decl = NULL; | |
| 26950 goto type_validation; | |
| 26951 } | |
| 26952 } | |
| 26953 /* | |
| 26954 * Validate against the declaration. | |
| 26955 */ | |
| 26956 ret = xmlSchemaValidateElemDecl(vctxt); | |
| 26957 if (ret != 0) { | |
| 26958 if (ret < 0) { | |
| 26959 VERROR_INT("xmlSchemaValidateElem", | |
| 26960 "calling xmlSchemaValidateElemDecl()"); | |
| 26961 goto internal_error; | |
| 26962 } | |
| 26963 goto exit; | |
| 26964 } | |
| 26965 /* | |
| 26966 * Validate against the type definition. | |
| 26967 */ | |
| 26968 type_validation: | |
| 26969 | |
| 26970 if (vctxt->inode->typeDef == NULL) { | |
| 26971 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE; | |
| 26972 ret = XML_SCHEMAV_CVC_TYPE_1; | |
| 26973 VERROR(ret, NULL, | |
| 26974 "The type definition is absent"); | |
| 26975 goto exit; | |
| 26976 } | |
| 26977 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) { | |
| 26978 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE; | |
| 26979 ret = XML_SCHEMAV_CVC_TYPE_2; | |
| 26980 VERROR(ret, NULL, | |
| 26981 "The type definition is abstract"); | |
| 26982 goto exit; | |
| 26983 } | |
| 26984 /* | |
| 26985 * Evaluate IDCs. Do it here, since new IDC matchers are registered | |
| 26986 * during validation against the declaration. This must be done | |
| 26987 * _before_ attribute validation. | |
| 26988 */ | |
| 26989 if (vctxt->xpathStates != NULL) { | |
| 26990 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE); | |
| 26991 vctxt->inode->appliedXPath = 1; | |
| 26992 if (ret == -1) { | |
| 26993 VERROR_INT("xmlSchemaValidateElem", | |
| 26994 "calling xmlSchemaXPathEvaluate()"); | |
| 26995 goto internal_error; | |
| 26996 } | |
| 26997 } | |
| 26998 /* | |
| 26999 * Validate attributes. | |
| 27000 */ | |
| 27001 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) { | |
| 27002 if ((vctxt->nbAttrInfos != 0) || | |
| 27003 (vctxt->inode->typeDef->attrUses != NULL)) { | |
| 27004 | |
| 27005 ret = xmlSchemaVAttributesComplex(vctxt); | |
| 27006 } | |
| 27007 } else if (vctxt->nbAttrInfos != 0) { | |
| 27008 | |
| 27009 ret = xmlSchemaVAttributesSimple(vctxt); | |
| 27010 } | |
| 27011 /* | |
| 27012 * Clear registered attributes. | |
| 27013 */ | |
| 27014 if (vctxt->nbAttrInfos != 0) | |
| 27015 xmlSchemaClearAttrInfos(vctxt); | |
| 27016 if (ret == -1) { | |
| 27017 VERROR_INT("xmlSchemaValidateElem", | |
| 27018 "calling attributes validation"); | |
| 27019 goto internal_error; | |
| 27020 } | |
| 27021 /* | |
| 27022 * Don't return an error if attributes are invalid on purpose. | |
| 27023 */ | |
| 27024 ret = 0; | |
| 27025 | |
| 27026 exit: | |
| 27027 if (ret != 0) | |
| 27028 vctxt->skipDepth = vctxt->depth; | |
| 27029 return (ret); | |
| 27030 internal_error: | |
| 27031 return (-1); | |
| 27032 } | |
| 27033 | |
| 27034 #ifdef XML_SCHEMA_READER_ENABLED | |
| 27035 static int | |
| 27036 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt) | |
| 27037 { | |
| 27038 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15; | |
| 27039 int depth, nodeType, ret = 0, consumed; | |
| 27040 xmlSchemaNodeInfoPtr ielem; | |
| 27041 | |
| 27042 vctxt->depth = -1; | |
| 27043 ret = xmlTextReaderRead(vctxt->reader); | |
| 27044 /* | |
| 27045 * Move to the document element. | |
| 27046 */ | |
| 27047 while (ret == 1) { | |
| 27048 nodeType = xmlTextReaderNodeType(vctxt->reader); | |
| 27049 if (nodeType == XML_ELEMENT_NODE) | |
| 27050 goto root_found; | |
| 27051 ret = xmlTextReaderRead(vctxt->reader); | |
| 27052 } | |
| 27053 goto exit; | |
| 27054 | |
| 27055 root_found: | |
| 27056 | |
| 27057 do { | |
| 27058 depth = xmlTextReaderDepth(vctxt->reader); | |
| 27059 nodeType = xmlTextReaderNodeType(vctxt->reader); | |
| 27060 | |
| 27061 if (nodeType == XML_ELEMENT_NODE) { | |
| 27062 | |
| 27063 vctxt->depth++; | |
| 27064 if (xmlSchemaValidatorPushElem(vctxt) == -1) { | |
| 27065 VERROR_INT("xmlSchemaVReaderWalk", | |
| 27066 "calling xmlSchemaValidatorPushElem()"); | |
| 27067 goto internal_error; | |
| 27068 } | |
| 27069 ielem = vctxt->inode; | |
| 27070 ielem->localName = xmlTextReaderLocalName(vctxt->reader); | |
| 27071 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader); | |
| 27072 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES; | |
| 27073 /* | |
| 27074 * Is the element empty? | |
| 27075 */ | |
| 27076 ret = xmlTextReaderIsEmptyElement(vctxt->reader); | |
| 27077 if (ret == -1) { | |
| 27078 VERROR_INT("xmlSchemaVReaderWalk", | |
| 27079 "calling xmlTextReaderIsEmptyElement()"); | |
| 27080 goto internal_error; | |
| 27081 } | |
| 27082 if (ret) { | |
| 27083 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY; | |
| 27084 } | |
| 27085 /* | |
| 27086 * Register attributes. | |
| 27087 */ | |
| 27088 vctxt->nbAttrInfos = 0; | |
| 27089 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader); | |
| 27090 if (ret == -1) { | |
| 27091 VERROR_INT("xmlSchemaVReaderWalk", | |
| 27092 "calling xmlTextReaderMoveToFirstAttribute()"); | |
| 27093 goto internal_error; | |
| 27094 } | |
| 27095 if (ret == 1) { | |
| 27096 do { | |
| 27097 /* | |
| 27098 * VAL TODO: How do we know that the reader works on a | |
| 27099 * node tree, to be able to pass a node here? | |
| 27100 */ | |
| 27101 if (xmlSchemaValidatorPushAttribute(vctxt, NULL, | |
| 27102 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader), | |
| 27103 xmlTextReaderNamespaceUri(vctxt->reader), 1, | |
| 27104 xmlTextReaderValue(vctxt->reader), 1) == -1) { | |
| 27105 | |
| 27106 VERROR_INT("xmlSchemaVReaderWalk", | |
| 27107 "calling xmlSchemaValidatorPushAttribute()"); | |
| 27108 goto internal_error; | |
| 27109 } | |
| 27110 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader); | |
| 27111 if (ret == -1) { | |
| 27112 VERROR_INT("xmlSchemaVReaderWalk", | |
| 27113 "calling xmlTextReaderMoveToFirstAttribute()"); | |
| 27114 goto internal_error; | |
| 27115 } | |
| 27116 } while (ret == 1); | |
| 27117 /* | |
| 27118 * Back to element position. | |
| 27119 */ | |
| 27120 ret = xmlTextReaderMoveToElement(vctxt->reader); | |
| 27121 if (ret == -1) { | |
| 27122 VERROR_INT("xmlSchemaVReaderWalk", | |
| 27123 "calling xmlTextReaderMoveToElement()"); | |
| 27124 goto internal_error; | |
| 27125 } | |
| 27126 } | |
| 27127 /* | |
| 27128 * Validate the element. | |
| 27129 */ | |
| 27130 ret= xmlSchemaValidateElem(vctxt); | |
| 27131 if (ret != 0) { | |
| 27132 if (ret == -1) { | |
| 27133 VERROR_INT("xmlSchemaVReaderWalk", | |
| 27134 "calling xmlSchemaValidateElem()"); | |
| 27135 goto internal_error; | |
| 27136 } | |
| 27137 goto exit; | |
| 27138 } | |
| 27139 if (vctxt->depth == vctxt->skipDepth) { | |
| 27140 int curDepth; | |
| 27141 /* | |
| 27142 * Skip all content. | |
| 27143 */ | |
| 27144 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) { | |
| 27145 ret = xmlTextReaderRead(vctxt->reader); | |
| 27146 curDepth = xmlTextReaderDepth(vctxt->reader); | |
| 27147 while ((ret == 1) && (curDepth != depth)) { | |
| 27148 ret = xmlTextReaderRead(vctxt->reader); | |
| 27149 curDepth = xmlTextReaderDepth(vctxt->reader); | |
| 27150 } | |
| 27151 if (ret < 0) { | |
| 27152 /* | |
| 27153 * VAL TODO: A reader error occured; what to do here? | |
| 27154 */ | |
| 27155 ret = 1; | |
| 27156 goto exit; | |
| 27157 } | |
| 27158 } | |
| 27159 goto leave_elem; | |
| 27160 } | |
| 27161 /* | |
| 27162 * READER VAL TODO: Is an END_ELEM really never called | |
| 27163 * if the elem is empty? | |
| 27164 */ | |
| 27165 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) | |
| 27166 goto leave_elem; | |
| 27167 } else if (nodeType == END_ELEM) { | |
| 27168 /* | |
| 27169 * Process END of element. | |
| 27170 */ | |
| 27171 leave_elem: | |
| 27172 ret = xmlSchemaValidatorPopElem(vctxt); | |
| 27173 if (ret != 0) { | |
| 27174 if (ret < 0) { | |
| 27175 VERROR_INT("xmlSchemaVReaderWalk", | |
| 27176 "calling xmlSchemaValidatorPopElem()"); | |
| 27177 goto internal_error; | |
| 27178 } | |
| 27179 goto exit; | |
| 27180 } | |
| 27181 if (vctxt->depth >= 0) | |
| 27182 ielem = vctxt->inode; | |
| 27183 else | |
| 27184 ielem = NULL; | |
| 27185 } else if ((nodeType == XML_TEXT_NODE) || | |
| 27186 (nodeType == XML_CDATA_SECTION_NODE) || | |
| 27187 (nodeType == WHTSP) || | |
| 27188 (nodeType == SIGN_WHTSP)) { | |
| 27189 /* | |
| 27190 * Process character content. | |
| 27191 */ | |
| 27192 xmlChar *value; | |
| 27193 | |
| 27194 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP)) | |
| 27195 nodeType = XML_TEXT_NODE; | |
| 27196 | |
| 27197 value = xmlTextReaderValue(vctxt->reader); | |
| 27198 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value, | |
| 27199 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed); | |
| 27200 if (! consumed) | |
| 27201 xmlFree(value); | |
| 27202 if (ret == -1) { | |
| 27203 VERROR_INT("xmlSchemaVReaderWalk", | |
| 27204 "calling xmlSchemaVPushText()"); | |
| 27205 goto internal_error; | |
| 27206 } | |
| 27207 } else if ((nodeType == XML_ENTITY_NODE) || | |
| 27208 (nodeType == XML_ENTITY_REF_NODE)) { | |
| 27209 /* | |
| 27210 * VAL TODO: What to do with entities? | |
| 27211 */ | |
| 27212 TODO | |
| 27213 } | |
| 27214 /* | |
| 27215 * Read next node. | |
| 27216 */ | |
| 27217 ret = xmlTextReaderRead(vctxt->reader); | |
| 27218 } while (ret == 1); | |
| 27219 | |
| 27220 exit: | |
| 27221 return (ret); | |
| 27222 internal_error: | |
| 27223 return (-1); | |
| 27224 } | |
| 27225 #endif | |
| 27226 | |
| 27227 /************************************************************************ | |
| 27228 * * | |
| 27229 * SAX validation handlers * | |
| 27230 * * | |
| 27231 ************************************************************************/ | |
| 27232 | |
| 27233 /* | |
| 27234 * Process text content. | |
| 27235 */ | |
| 27236 static void | |
| 27237 xmlSchemaSAXHandleText(void *ctx, | |
| 27238 const xmlChar * ch, | |
| 27239 int len) | |
| 27240 { | |
| 27241 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; | |
| 27242 | |
| 27243 if (vctxt->depth < 0) | |
| 27244 return; | |
| 27245 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) | |
| 27246 return; | |
| 27247 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) | |
| 27248 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; | |
| 27249 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len, | |
| 27250 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) { | |
| 27251 VERROR_INT("xmlSchemaSAXHandleCDataSection", | |
| 27252 "calling xmlSchemaVPushText()"); | |
| 27253 vctxt->err = -1; | |
| 27254 xmlStopParser(vctxt->parserCtxt); | |
| 27255 } | |
| 27256 } | |
| 27257 | |
| 27258 /* | |
| 27259 * Process CDATA content. | |
| 27260 */ | |
| 27261 static void | |
| 27262 xmlSchemaSAXHandleCDataSection(void *ctx, | |
| 27263 const xmlChar * ch, | |
| 27264 int len) | |
| 27265 { | |
| 27266 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; | |
| 27267 | |
| 27268 if (vctxt->depth < 0) | |
| 27269 return; | |
| 27270 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) | |
| 27271 return; | |
| 27272 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) | |
| 27273 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; | |
| 27274 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len, | |
| 27275 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) { | |
| 27276 VERROR_INT("xmlSchemaSAXHandleCDataSection", | |
| 27277 "calling xmlSchemaVPushText()"); | |
| 27278 vctxt->err = -1; | |
| 27279 xmlStopParser(vctxt->parserCtxt); | |
| 27280 } | |
| 27281 } | |
| 27282 | |
| 27283 static void | |
| 27284 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED, | |
| 27285 const xmlChar * name ATTRIBUTE_UNUSED) | |
| 27286 { | |
| 27287 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; | |
| 27288 | |
| 27289 if (vctxt->depth < 0) | |
| 27290 return; | |
| 27291 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) | |
| 27292 return; | |
| 27293 /* SAX VAL TODO: What to do here? */ | |
| 27294 TODO | |
| 27295 } | |
| 27296 | |
| 27297 static void | |
| 27298 xmlSchemaSAXHandleStartElementNs(void *ctx, | |
| 27299 const xmlChar * localname, | |
| 27300 const xmlChar * prefix ATTRIBUTE_UNUSED, | |
| 27301 const xmlChar * URI, | |
| 27302 int nb_namespaces, | |
| 27303 const xmlChar ** namespaces, | |
| 27304 int nb_attributes, | |
| 27305 int nb_defaulted ATTRIBUTE_UNUSED, | |
| 27306 const xmlChar ** attributes) | |
| 27307 { | |
| 27308 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; | |
| 27309 int ret; | |
| 27310 xmlSchemaNodeInfoPtr ielem; | |
| 27311 int i, j; | |
| 27312 | |
| 27313 /* | |
| 27314 * SAX VAL TODO: What to do with nb_defaulted? | |
| 27315 */ | |
| 27316 /* | |
| 27317 * Skip elements if inside a "skip" wildcard or invalid. | |
| 27318 */ | |
| 27319 vctxt->depth++; | |
| 27320 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) | |
| 27321 return; | |
| 27322 /* | |
| 27323 * Push the element. | |
| 27324 */ | |
| 27325 if (xmlSchemaValidatorPushElem(vctxt) == -1) { | |
| 27326 VERROR_INT("xmlSchemaSAXHandleStartElementNs", | |
| 27327 "calling xmlSchemaValidatorPushElem()"); | |
| 27328 goto internal_error; | |
| 27329 } | |
| 27330 ielem = vctxt->inode; | |
| 27331 /* | |
| 27332 * TODO: Is this OK? | |
| 27333 */ | |
| 27334 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt); | |
| 27335 ielem->localName = localname; | |
| 27336 ielem->nsName = URI; | |
| 27337 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY; | |
| 27338 /* | |
| 27339 * Register namespaces on the elem info. | |
| 27340 */ | |
| 27341 if (nb_namespaces != 0) { | |
| 27342 /* | |
| 27343 * Although the parser builds its own namespace list, | |
| 27344 * we have no access to it, so we'll use an own one. | |
| 27345 */ | |
| 27346 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) { | |
| 27347 /* | |
| 27348 * Store prefix and namespace name. | |
| 27349 */ | |
| 27350 if (ielem->nsBindings == NULL) { | |
| 27351 ielem->nsBindings = | |
| 27352 (const xmlChar **) xmlMalloc(10 * | |
| 27353 sizeof(const xmlChar *)); | |
| 27354 if (ielem->nsBindings == NULL) { | |
| 27355 xmlSchemaVErrMemory(vctxt, | |
| 27356 "allocating namespace bindings for SAX validation", | |
| 27357 NULL); | |
| 27358 goto internal_error; | |
| 27359 } | |
| 27360 ielem->nbNsBindings = 0; | |
| 27361 ielem->sizeNsBindings = 5; | |
| 27362 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) { | |
| 27363 ielem->sizeNsBindings *= 2; | |
| 27364 ielem->nsBindings = | |
| 27365 (const xmlChar **) xmlRealloc( | |
| 27366 (void *) ielem->nsBindings, | |
| 27367 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *)); | |
| 27368 if (ielem->nsBindings == NULL) { | |
| 27369 xmlSchemaVErrMemory(vctxt, | |
| 27370 "re-allocating namespace bindings for SAX validation", | |
| 27371 NULL); | |
| 27372 goto internal_error; | |
| 27373 } | |
| 27374 } | |
| 27375 | |
| 27376 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j]; | |
| 27377 if (namespaces[j+1][0] == 0) { | |
| 27378 /* | |
| 27379 * Handle xmlns="". | |
| 27380 */ | |
| 27381 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL; | |
| 27382 } else | |
| 27383 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = | |
| 27384 namespaces[j+1]; | |
| 27385 ielem->nbNsBindings++; | |
| 27386 } | |
| 27387 } | |
| 27388 /* | |
| 27389 * Register attributes. | |
| 27390 * SAX VAL TODO: We are not adding namespace declaration | |
| 27391 * attributes yet. | |
| 27392 */ | |
| 27393 if (nb_attributes != 0) { | |
| 27394 int valueLen, k, l; | |
| 27395 xmlChar *value; | |
| 27396 | |
| 27397 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) { | |
| 27398 /* | |
| 27399 * Duplicate the value, changing any & to a literal ampersand. | |
| 27400 * | |
| 27401 * libxml2 differs from normal SAX here in that it escapes all ampers
ands | |
| 27402 * as & instead of delivering the raw converted string. Changing
the | |
| 27403 * behavior at this point would break applications that use this API,
so | |
| 27404 * we are forced to work around it. | |
| 27405 */ | |
| 27406 valueLen = attributes[j+4] - attributes[j+3]; | |
| 27407 value = xmlMallocAtomic(valueLen + 1); | |
| 27408 if (value == NULL) { | |
| 27409 xmlSchemaVErrMemory(vctxt, | |
| 27410 "allocating string for decoded attribute", | |
| 27411 NULL); | |
| 27412 goto internal_error; | |
| 27413 } | |
| 27414 for (k = 0, l = 0; k < valueLen; l++) { | |
| 27415 if (k < valueLen - 4 && | |
| 27416 attributes[j+3][k+0] == '&' && | |
| 27417 attributes[j+3][k+1] == '#' && | |
| 27418 attributes[j+3][k+2] == '3' && | |
| 27419 attributes[j+3][k+3] == '8' && | |
| 27420 attributes[j+3][k+4] == ';') { | |
| 27421 value[l] = '&'; | |
| 27422 k += 5; | |
| 27423 } else { | |
| 27424 value[l] = attributes[j+3][k]; | |
| 27425 k++; | |
| 27426 } | |
| 27427 } | |
| 27428 value[l] = '\0'; | |
| 27429 /* | |
| 27430 * TODO: Set the node line. | |
| 27431 */ | |
| 27432 ret = xmlSchemaValidatorPushAttribute(vctxt, | |
| 27433 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0, | |
| 27434 value, 1); | |
| 27435 if (ret == -1) { | |
| 27436 VERROR_INT("xmlSchemaSAXHandleStartElementNs", | |
| 27437 "calling xmlSchemaValidatorPushAttribute()"); | |
| 27438 goto internal_error; | |
| 27439 } | |
| 27440 } | |
| 27441 } | |
| 27442 /* | |
| 27443 * Validate the element. | |
| 27444 */ | |
| 27445 ret = xmlSchemaValidateElem(vctxt); | |
| 27446 if (ret != 0) { | |
| 27447 if (ret == -1) { | |
| 27448 VERROR_INT("xmlSchemaSAXHandleStartElementNs", | |
| 27449 "calling xmlSchemaValidateElem()"); | |
| 27450 goto internal_error; | |
| 27451 } | |
| 27452 goto exit; | |
| 27453 } | |
| 27454 | |
| 27455 exit: | |
| 27456 return; | |
| 27457 internal_error: | |
| 27458 vctxt->err = -1; | |
| 27459 xmlStopParser(vctxt->parserCtxt); | |
| 27460 return; | |
| 27461 } | |
| 27462 | |
| 27463 static void | |
| 27464 xmlSchemaSAXHandleEndElementNs(void *ctx, | |
| 27465 const xmlChar * localname ATTRIBUTE_UNUSED, | |
| 27466 const xmlChar * prefix ATTRIBUTE_UNUSED, | |
| 27467 const xmlChar * URI ATTRIBUTE_UNUSED) | |
| 27468 { | |
| 27469 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; | |
| 27470 int res; | |
| 27471 | |
| 27472 /* | |
| 27473 * Skip elements if inside a "skip" wildcard or if invalid. | |
| 27474 */ | |
| 27475 if (vctxt->skipDepth != -1) { | |
| 27476 if (vctxt->depth > vctxt->skipDepth) { | |
| 27477 vctxt->depth--; | |
| 27478 return; | |
| 27479 } else | |
| 27480 vctxt->skipDepth = -1; | |
| 27481 } | |
| 27482 /* | |
| 27483 * SAX VAL TODO: Just a temporary check. | |
| 27484 */ | |
| 27485 if ((!xmlStrEqual(vctxt->inode->localName, localname)) || | |
| 27486 (!xmlStrEqual(vctxt->inode->nsName, URI))) { | |
| 27487 VERROR_INT("xmlSchemaSAXHandleEndElementNs", | |
| 27488 "elem pop mismatch"); | |
| 27489 } | |
| 27490 res = xmlSchemaValidatorPopElem(vctxt); | |
| 27491 if (res != 0) { | |
| 27492 if (res < 0) { | |
| 27493 VERROR_INT("xmlSchemaSAXHandleEndElementNs", | |
| 27494 "calling xmlSchemaValidatorPopElem()"); | |
| 27495 goto internal_error; | |
| 27496 } | |
| 27497 goto exit; | |
| 27498 } | |
| 27499 exit: | |
| 27500 return; | |
| 27501 internal_error: | |
| 27502 vctxt->err = -1; | |
| 27503 xmlStopParser(vctxt->parserCtxt); | |
| 27504 return; | |
| 27505 } | |
| 27506 | |
| 27507 /************************************************************************ | |
| 27508 * * | |
| 27509 * Validation interfaces * | |
| 27510 * * | |
| 27511 ************************************************************************/ | |
| 27512 | |
| 27513 /** | |
| 27514 * xmlSchemaNewValidCtxt: | |
| 27515 * @schema: a precompiled XML Schemas | |
| 27516 * | |
| 27517 * Create an XML Schemas validation context based on the given schema. | |
| 27518 * | |
| 27519 * Returns the validation context or NULL in case of error | |
| 27520 */ | |
| 27521 xmlSchemaValidCtxtPtr | |
| 27522 xmlSchemaNewValidCtxt(xmlSchemaPtr schema) | |
| 27523 { | |
| 27524 xmlSchemaValidCtxtPtr ret; | |
| 27525 | |
| 27526 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt)); | |
| 27527 if (ret == NULL) { | |
| 27528 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL); | |
| 27529 return (NULL); | |
| 27530 } | |
| 27531 memset(ret, 0, sizeof(xmlSchemaValidCtxt)); | |
| 27532 ret->type = XML_SCHEMA_CTXT_VALIDATOR; | |
| 27533 ret->dict = xmlDictCreate(); | |
| 27534 ret->nodeQNames = xmlSchemaItemListCreate(); | |
| 27535 ret->schema = schema; | |
| 27536 return (ret); | |
| 27537 } | |
| 27538 | |
| 27539 /** | |
| 27540 * xmlSchemaValidateSetFilename: | |
| 27541 * @vctxt: the schema validation context | |
| 27542 * @filename: the file name | |
| 27543 * | |
| 27544 * Workaround to provide file error reporting information when this is | |
| 27545 * not provided by current APIs | |
| 27546 */ | |
| 27547 void | |
| 27548 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename)
{ | |
| 27549 if (vctxt == NULL) | |
| 27550 return; | |
| 27551 if (vctxt->filename != NULL) | |
| 27552 xmlFree(vctxt->filename); | |
| 27553 if (filename != NULL) | |
| 27554 vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename); | |
| 27555 else | |
| 27556 vctxt->filename = NULL; | |
| 27557 } | |
| 27558 | |
| 27559 /** | |
| 27560 * xmlSchemaClearValidCtxt: | |
| 27561 * @vctxt: the schema validation context | |
| 27562 * | |
| 27563 * Free the resources associated to the schema validation context; | |
| 27564 * leaves some fields alive intended for reuse of the context. | |
| 27565 */ | |
| 27566 static void | |
| 27567 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt) | |
| 27568 { | |
| 27569 if (vctxt == NULL) | |
| 27570 return; | |
| 27571 | |
| 27572 /* | |
| 27573 * TODO: Should we clear the flags? | |
| 27574 * Might be problematic if one reuses the context | |
| 27575 * and assumes that the options remain the same. | |
| 27576 */ | |
| 27577 vctxt->flags = 0; | |
| 27578 vctxt->validationRoot = NULL; | |
| 27579 vctxt->doc = NULL; | |
| 27580 #ifdef LIBXML_READER_ENABLED | |
| 27581 vctxt->reader = NULL; | |
| 27582 #endif | |
| 27583 vctxt->hasKeyrefs = 0; | |
| 27584 | |
| 27585 if (vctxt->value != NULL) { | |
| 27586 xmlSchemaFreeValue(vctxt->value); | |
| 27587 vctxt->value = NULL; | |
| 27588 } | |
| 27589 /* | |
| 27590 * Augmented IDC information. | |
| 27591 */ | |
| 27592 if (vctxt->aidcs != NULL) { | |
| 27593 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next; | |
| 27594 do { | |
| 27595 next = cur->next; | |
| 27596 xmlFree(cur); | |
| 27597 cur = next; | |
| 27598 } while (cur != NULL); | |
| 27599 vctxt->aidcs = NULL; | |
| 27600 } | |
| 27601 if (vctxt->idcMatcherCache != NULL) { | |
| 27602 xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp; | |
| 27603 | |
| 27604 while (matcher) { | |
| 27605 tmp = matcher; | |
| 27606 matcher = matcher->nextCached; | |
| 27607 xmlSchemaIDCFreeMatcherList(tmp); | |
| 27608 } | |
| 27609 vctxt->idcMatcherCache = NULL; | |
| 27610 } | |
| 27611 | |
| 27612 | |
| 27613 if (vctxt->idcNodes != NULL) { | |
| 27614 int i; | |
| 27615 xmlSchemaPSVIIDCNodePtr item; | |
| 27616 | |
| 27617 for (i = 0; i < vctxt->nbIdcNodes; i++) { | |
| 27618 item = vctxt->idcNodes[i]; | |
| 27619 xmlFree(item->keys); | |
| 27620 xmlFree(item); | |
| 27621 } | |
| 27622 xmlFree(vctxt->idcNodes); | |
| 27623 vctxt->idcNodes = NULL; | |
| 27624 vctxt->nbIdcNodes = 0; | |
| 27625 vctxt->sizeIdcNodes = 0; | |
| 27626 } | |
| 27627 /* | |
| 27628 * Note that we won't delete the XPath state pool here. | |
| 27629 */ | |
| 27630 if (vctxt->xpathStates != NULL) { | |
| 27631 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates); | |
| 27632 vctxt->xpathStates = NULL; | |
| 27633 } | |
| 27634 /* | |
| 27635 * Attribute info. | |
| 27636 */ | |
| 27637 if (vctxt->nbAttrInfos != 0) { | |
| 27638 xmlSchemaClearAttrInfos(vctxt); | |
| 27639 } | |
| 27640 /* | |
| 27641 * Element info. | |
| 27642 */ | |
| 27643 if (vctxt->elemInfos != NULL) { | |
| 27644 int i; | |
| 27645 xmlSchemaNodeInfoPtr ei; | |
| 27646 | |
| 27647 for (i = 0; i < vctxt->sizeElemInfos; i++) { | |
| 27648 ei = vctxt->elemInfos[i]; | |
| 27649 if (ei == NULL) | |
| 27650 break; | |
| 27651 xmlSchemaClearElemInfo(vctxt, ei); | |
| 27652 } | |
| 27653 } | |
| 27654 xmlSchemaItemListClear(vctxt->nodeQNames); | |
| 27655 /* Recreate the dict. */ | |
| 27656 xmlDictFree(vctxt->dict); | |
| 27657 /* | |
| 27658 * TODO: Is is save to recreate it? Do we have a scenario | |
| 27659 * where the user provides the dict? | |
| 27660 */ | |
| 27661 vctxt->dict = xmlDictCreate(); | |
| 27662 | |
| 27663 if (vctxt->filename != NULL) { | |
| 27664 xmlFree(vctxt->filename); | |
| 27665 vctxt->filename = NULL; | |
| 27666 } | |
| 27667 } | |
| 27668 | |
| 27669 /** | |
| 27670 * xmlSchemaFreeValidCtxt: | |
| 27671 * @ctxt: the schema validation context | |
| 27672 * | |
| 27673 * Free the resources associated to the schema validation context | |
| 27674 */ | |
| 27675 void | |
| 27676 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) | |
| 27677 { | |
| 27678 if (ctxt == NULL) | |
| 27679 return; | |
| 27680 if (ctxt->value != NULL) | |
| 27681 xmlSchemaFreeValue(ctxt->value); | |
| 27682 if (ctxt->pctxt != NULL) | |
| 27683 xmlSchemaFreeParserCtxt(ctxt->pctxt); | |
| 27684 if (ctxt->idcNodes != NULL) { | |
| 27685 int i; | |
| 27686 xmlSchemaPSVIIDCNodePtr item; | |
| 27687 | |
| 27688 for (i = 0; i < ctxt->nbIdcNodes; i++) { | |
| 27689 item = ctxt->idcNodes[i]; | |
| 27690 xmlFree(item->keys); | |
| 27691 xmlFree(item); | |
| 27692 } | |
| 27693 xmlFree(ctxt->idcNodes); | |
| 27694 } | |
| 27695 if (ctxt->idcKeys != NULL) { | |
| 27696 int i; | |
| 27697 for (i = 0; i < ctxt->nbIdcKeys; i++) | |
| 27698 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]); | |
| 27699 xmlFree(ctxt->idcKeys); | |
| 27700 } | |
| 27701 | |
| 27702 if (ctxt->xpathStates != NULL) { | |
| 27703 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates); | |
| 27704 ctxt->xpathStates = NULL; | |
| 27705 } | |
| 27706 if (ctxt->xpathStatePool != NULL) { | |
| 27707 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool); | |
| 27708 ctxt->xpathStatePool = NULL; | |
| 27709 } | |
| 27710 | |
| 27711 /* | |
| 27712 * Augmented IDC information. | |
| 27713 */ | |
| 27714 if (ctxt->aidcs != NULL) { | |
| 27715 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next; | |
| 27716 do { | |
| 27717 next = cur->next; | |
| 27718 xmlFree(cur); | |
| 27719 cur = next; | |
| 27720 } while (cur != NULL); | |
| 27721 } | |
| 27722 if (ctxt->attrInfos != NULL) { | |
| 27723 int i; | |
| 27724 xmlSchemaAttrInfoPtr attr; | |
| 27725 | |
| 27726 /* Just a paranoid call to the cleanup. */ | |
| 27727 if (ctxt->nbAttrInfos != 0) | |
| 27728 xmlSchemaClearAttrInfos(ctxt); | |
| 27729 for (i = 0; i < ctxt->sizeAttrInfos; i++) { | |
| 27730 attr = ctxt->attrInfos[i]; | |
| 27731 xmlFree(attr); | |
| 27732 } | |
| 27733 xmlFree(ctxt->attrInfos); | |
| 27734 } | |
| 27735 if (ctxt->elemInfos != NULL) { | |
| 27736 int i; | |
| 27737 xmlSchemaNodeInfoPtr ei; | |
| 27738 | |
| 27739 for (i = 0; i < ctxt->sizeElemInfos; i++) { | |
| 27740 ei = ctxt->elemInfos[i]; | |
| 27741 if (ei == NULL) | |
| 27742 break; | |
| 27743 xmlSchemaClearElemInfo(ctxt, ei); | |
| 27744 xmlFree(ei); | |
| 27745 } | |
| 27746 xmlFree(ctxt->elemInfos); | |
| 27747 } | |
| 27748 if (ctxt->nodeQNames != NULL) | |
| 27749 xmlSchemaItemListFree(ctxt->nodeQNames); | |
| 27750 if (ctxt->dict != NULL) | |
| 27751 xmlDictFree(ctxt->dict); | |
| 27752 if (ctxt->filename != NULL) | |
| 27753 xmlFree(ctxt->filename); | |
| 27754 xmlFree(ctxt); | |
| 27755 } | |
| 27756 | |
| 27757 /** | |
| 27758 * xmlSchemaIsValid: | |
| 27759 * @ctxt: the schema validation context | |
| 27760 * | |
| 27761 * Check if any error was detected during validation. | |
| 27762 * | |
| 27763 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case | |
| 27764 * of internal error. | |
| 27765 */ | |
| 27766 int | |
| 27767 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt) | |
| 27768 { | |
| 27769 if (ctxt == NULL) | |
| 27770 return(-1); | |
| 27771 return(ctxt->err == 0); | |
| 27772 } | |
| 27773 | |
| 27774 /** | |
| 27775 * xmlSchemaSetValidErrors: | |
| 27776 * @ctxt: a schema validation context | |
| 27777 * @err: the error function | |
| 27778 * @warn: the warning function | |
| 27779 * @ctx: the functions context | |
| 27780 * | |
| 27781 * Set the error and warning callback informations | |
| 27782 */ | |
| 27783 void | |
| 27784 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt, | |
| 27785 xmlSchemaValidityErrorFunc err, | |
| 27786 xmlSchemaValidityWarningFunc warn, void *ctx) | |
| 27787 { | |
| 27788 if (ctxt == NULL) | |
| 27789 return; | |
| 27790 ctxt->error = err; | |
| 27791 ctxt->warning = warn; | |
| 27792 ctxt->errCtxt = ctx; | |
| 27793 if (ctxt->pctxt != NULL) | |
| 27794 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx); | |
| 27795 } | |
| 27796 | |
| 27797 /** | |
| 27798 * xmlSchemaSetValidStructuredErrors: | |
| 27799 * @ctxt: a schema validation context | |
| 27800 * @serror: the structured error function | |
| 27801 * @ctx: the functions context | |
| 27802 * | |
| 27803 * Set the structured error callback | |
| 27804 */ | |
| 27805 void | |
| 27806 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt, | |
| 27807 xmlStructuredErrorFunc serror, void *ctx) | |
| 27808 { | |
| 27809 if (ctxt == NULL) | |
| 27810 return; | |
| 27811 ctxt->serror = serror; | |
| 27812 ctxt->error = NULL; | |
| 27813 ctxt->warning = NULL; | |
| 27814 ctxt->errCtxt = ctx; | |
| 27815 if (ctxt->pctxt != NULL) | |
| 27816 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx); | |
| 27817 } | |
| 27818 | |
| 27819 /** | |
| 27820 * xmlSchemaGetValidErrors: | |
| 27821 * @ctxt: a XML-Schema validation context | |
| 27822 * @err: the error function result | |
| 27823 * @warn: the warning function result | |
| 27824 * @ctx: the functions context result | |
| 27825 * | |
| 27826 * Get the error and warning callback informations | |
| 27827 * | |
| 27828 * Returns -1 in case of error and 0 otherwise | |
| 27829 */ | |
| 27830 int | |
| 27831 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt, | |
| 27832 xmlSchemaValidityErrorFunc * err, | |
| 27833 xmlSchemaValidityWarningFunc * warn, void **ctx) | |
| 27834 { | |
| 27835 if (ctxt == NULL) | |
| 27836 return (-1); | |
| 27837 if (err != NULL) | |
| 27838 *err = ctxt->error; | |
| 27839 if (warn != NULL) | |
| 27840 *warn = ctxt->warning; | |
| 27841 if (ctx != NULL) | |
| 27842 *ctx = ctxt->errCtxt; | |
| 27843 return (0); | |
| 27844 } | |
| 27845 | |
| 27846 | |
| 27847 /** | |
| 27848 * xmlSchemaSetValidOptions: | |
| 27849 * @ctxt: a schema validation context | |
| 27850 * @options: a combination of xmlSchemaValidOption | |
| 27851 * | |
| 27852 * Sets the options to be used during the validation. | |
| 27853 * | |
| 27854 * Returns 0 in case of success, -1 in case of an | |
| 27855 * API error. | |
| 27856 */ | |
| 27857 int | |
| 27858 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt, | |
| 27859 int options) | |
| 27860 | |
| 27861 { | |
| 27862 int i; | |
| 27863 | |
| 27864 if (ctxt == NULL) | |
| 27865 return (-1); | |
| 27866 /* | |
| 27867 * WARNING: Change the start value if adding to the | |
| 27868 * xmlSchemaValidOption. | |
| 27869 * TODO: Is there an other, more easy to maintain, | |
| 27870 * way? | |
| 27871 */ | |
| 27872 for (i = 1; i < (int) sizeof(int) * 8; i++) { | |
| 27873 if (options & 1<<i) | |
| 27874 return (-1); | |
| 27875 } | |
| 27876 ctxt->options = options; | |
| 27877 return (0); | |
| 27878 } | |
| 27879 | |
| 27880 /** | |
| 27881 * xmlSchemaValidCtxtGetOptions: | |
| 27882 * @ctxt: a schema validation context | |
| 27883 * | |
| 27884 * Get the validation context options. | |
| 27885 * | |
| 27886 * Returns the option combination or -1 on error. | |
| 27887 */ | |
| 27888 int | |
| 27889 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt) | |
| 27890 | |
| 27891 { | |
| 27892 if (ctxt == NULL) | |
| 27893 return (-1); | |
| 27894 else | |
| 27895 return (ctxt->options); | |
| 27896 } | |
| 27897 | |
| 27898 static int | |
| 27899 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt) | |
| 27900 { | |
| 27901 xmlAttrPtr attr; | |
| 27902 int ret = 0; | |
| 27903 xmlSchemaNodeInfoPtr ielem = NULL; | |
| 27904 xmlNodePtr node, valRoot; | |
| 27905 const xmlChar *nsName; | |
| 27906 | |
| 27907 /* DOC VAL TODO: Move this to the start function. */ | |
| 27908 if (vctxt->validationRoot != NULL) | |
| 27909 valRoot = vctxt->validationRoot; | |
| 27910 else | |
| 27911 valRoot = xmlDocGetRootElement(vctxt->doc); | |
| 27912 if (valRoot == NULL) { | |
| 27913 /* VAL TODO: Error code? */ | |
| 27914 VERROR(1, NULL, "The document has no document element"); | |
| 27915 return (1); | |
| 27916 } | |
| 27917 vctxt->depth = -1; | |
| 27918 vctxt->validationRoot = valRoot; | |
| 27919 node = valRoot; | |
| 27920 while (node != NULL) { | |
| 27921 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) | |
| 27922 goto next_sibling; | |
| 27923 if (node->type == XML_ELEMENT_NODE) { | |
| 27924 | |
| 27925 /* | |
| 27926 * Init the node-info. | |
| 27927 */ | |
| 27928 vctxt->depth++; | |
| 27929 if (xmlSchemaValidatorPushElem(vctxt) == -1) | |
| 27930 goto internal_error; | |
| 27931 ielem = vctxt->inode; | |
| 27932 ielem->node = node; | |
| 27933 ielem->nodeLine = node->line; | |
| 27934 ielem->localName = node->name; | |
| 27935 if (node->ns != NULL) | |
| 27936 ielem->nsName = node->ns->href; | |
| 27937 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY; | |
| 27938 /* | |
| 27939 * Register attributes. | |
| 27940 * DOC VAL TODO: We do not register namespace declaration | |
| 27941 * attributes yet. | |
| 27942 */ | |
| 27943 vctxt->nbAttrInfos = 0; | |
| 27944 if (node->properties != NULL) { | |
| 27945 attr = node->properties; | |
| 27946 do { | |
| 27947 if (attr->ns != NULL) | |
| 27948 nsName = attr->ns->href; | |
| 27949 else | |
| 27950 nsName = NULL; | |
| 27951 ret = xmlSchemaValidatorPushAttribute(vctxt, | |
| 27952 (xmlNodePtr) attr, | |
| 27953 /* | |
| 27954 * Note that we give it the line number of the | |
| 27955 * parent element. | |
| 27956 */ | |
| 27957 ielem->nodeLine, | |
| 27958 attr->name, nsName, 0, | |
| 27959 xmlNodeListGetString(attr->doc, attr->children, 1), 1); | |
| 27960 if (ret == -1) { | |
| 27961 VERROR_INT("xmlSchemaDocWalk", | |
| 27962 "calling xmlSchemaValidatorPushAttribute()"); | |
| 27963 goto internal_error; | |
| 27964 } | |
| 27965 attr = attr->next; | |
| 27966 } while (attr); | |
| 27967 } | |
| 27968 /* | |
| 27969 * Validate the element. | |
| 27970 */ | |
| 27971 ret = xmlSchemaValidateElem(vctxt); | |
| 27972 if (ret != 0) { | |
| 27973 if (ret == -1) { | |
| 27974 VERROR_INT("xmlSchemaDocWalk", | |
| 27975 "calling xmlSchemaValidateElem()"); | |
| 27976 goto internal_error; | |
| 27977 } | |
| 27978 /* | |
| 27979 * Don't stop validation; just skip the content | |
| 27980 * of this element. | |
| 27981 */ | |
| 27982 goto leave_node; | |
| 27983 } | |
| 27984 if ((vctxt->skipDepth != -1) && | |
| 27985 (vctxt->depth >= vctxt->skipDepth)) | |
| 27986 goto leave_node; | |
| 27987 } else if ((node->type == XML_TEXT_NODE) || | |
| 27988 (node->type == XML_CDATA_SECTION_NODE)) { | |
| 27989 /* | |
| 27990 * Process character content. | |
| 27991 */ | |
| 27992 if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)) | |
| 27993 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; | |
| 27994 ret = xmlSchemaVPushText(vctxt, node->type, node->content, | |
| 27995 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL); | |
| 27996 if (ret < 0) { | |
| 27997 VERROR_INT("xmlSchemaVDocWalk", | |
| 27998 "calling xmlSchemaVPushText()"); | |
| 27999 goto internal_error; | |
| 28000 } | |
| 28001 /* | |
| 28002 * DOC VAL TODO: Should we skip further validation of the | |
| 28003 * element content here? | |
| 28004 */ | |
| 28005 } else if ((node->type == XML_ENTITY_NODE) || | |
| 28006 (node->type == XML_ENTITY_REF_NODE)) { | |
| 28007 /* | |
| 28008 * DOC VAL TODO: What to do with entities? | |
| 28009 */ | |
| 28010 VERROR_INT("xmlSchemaVDocWalk", | |
| 28011 "there is at least one entity reference in the node-tree " | |
| 28012 "currently being validated. Processing of entities with " | |
| 28013 "this XML Schema processor is not supported (yet). Please " | |
| 28014 "substitute entities before validation."); | |
| 28015 goto internal_error; | |
| 28016 } else { | |
| 28017 goto leave_node; | |
| 28018 /* | |
| 28019 * DOC VAL TODO: XInclude nodes, etc. | |
| 28020 */ | |
| 28021 } | |
| 28022 /* | |
| 28023 * Walk the doc. | |
| 28024 */ | |
| 28025 if (node->children != NULL) { | |
| 28026 node = node->children; | |
| 28027 continue; | |
| 28028 } | |
| 28029 leave_node: | |
| 28030 if (node->type == XML_ELEMENT_NODE) { | |
| 28031 /* | |
| 28032 * Leaving the scope of an element. | |
| 28033 */ | |
| 28034 if (node != vctxt->inode->node) { | |
| 28035 VERROR_INT("xmlSchemaVDocWalk", | |
| 28036 "element position mismatch"); | |
| 28037 goto internal_error; | |
| 28038 } | |
| 28039 ret = xmlSchemaValidatorPopElem(vctxt); | |
| 28040 if (ret != 0) { | |
| 28041 if (ret < 0) { | |
| 28042 VERROR_INT("xmlSchemaVDocWalk", | |
| 28043 "calling xmlSchemaValidatorPopElem()"); | |
| 28044 goto internal_error; | |
| 28045 } | |
| 28046 } | |
| 28047 if (node == valRoot) | |
| 28048 goto exit; | |
| 28049 } | |
| 28050 next_sibling: | |
| 28051 if (node->next != NULL) | |
| 28052 node = node->next; | |
| 28053 else { | |
| 28054 node = node->parent; | |
| 28055 goto leave_node; | |
| 28056 } | |
| 28057 } | |
| 28058 | |
| 28059 exit: | |
| 28060 return (ret); | |
| 28061 internal_error: | |
| 28062 return (-1); | |
| 28063 } | |
| 28064 | |
| 28065 static int | |
| 28066 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) { | |
| 28067 /* | |
| 28068 * Some initialization. | |
| 28069 */ | |
| 28070 vctxt->err = 0; | |
| 28071 vctxt->nberrors = 0; | |
| 28072 vctxt->depth = -1; | |
| 28073 vctxt->skipDepth = -1; | |
| 28074 vctxt->xsiAssemble = 0; | |
| 28075 vctxt->hasKeyrefs = 0; | |
| 28076 #ifdef ENABLE_IDC_NODE_TABLES_TEST | |
| 28077 vctxt->createIDCNodeTables = 1; | |
| 28078 #else | |
| 28079 vctxt->createIDCNodeTables = 0; | |
| 28080 #endif | |
| 28081 /* | |
| 28082 * Create a schema + parser if necessary. | |
| 28083 */ | |
| 28084 if (vctxt->schema == NULL) { | |
| 28085 xmlSchemaParserCtxtPtr pctxt; | |
| 28086 | |
| 28087 vctxt->xsiAssemble = 1; | |
| 28088 /* | |
| 28089 * If not schema was given then we will create a schema | |
| 28090 * dynamically using XSI schema locations. | |
| 28091 * | |
| 28092 * Create the schema parser context. | |
| 28093 */ | |
| 28094 if ((vctxt->pctxt == NULL) && | |
| 28095 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) | |
| 28096 return (-1); | |
| 28097 pctxt = vctxt->pctxt; | |
| 28098 pctxt->xsiAssemble = 1; | |
| 28099 /* | |
| 28100 * Create the schema. | |
| 28101 */ | |
| 28102 vctxt->schema = xmlSchemaNewSchema(pctxt); | |
| 28103 if (vctxt->schema == NULL) | |
| 28104 return (-1); | |
| 28105 /* | |
| 28106 * Create the schema construction context. | |
| 28107 */ | |
| 28108 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict); | |
| 28109 if (pctxt->constructor == NULL) | |
| 28110 return(-1); | |
| 28111 pctxt->constructor->mainSchema = vctxt->schema; | |
| 28112 /* | |
| 28113 * Take ownership of the constructor to be able to free it. | |
| 28114 */ | |
| 28115 pctxt->ownsConstructor = 1; | |
| 28116 } | |
| 28117 /* | |
| 28118 * Augment the IDC definitions for the main schema and all imported ones | |
| 28119 * NOTE: main schema if the first in the imported list | |
| 28120 */ | |
| 28121 xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentIm
portedIDC, vctxt); | |
| 28122 | |
| 28123 return(0); | |
| 28124 } | |
| 28125 | |
| 28126 static void | |
| 28127 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) { | |
| 28128 if (vctxt->xsiAssemble) { | |
| 28129 if (vctxt->schema != NULL) { | |
| 28130 xmlSchemaFree(vctxt->schema); | |
| 28131 vctxt->schema = NULL; | |
| 28132 } | |
| 28133 } | |
| 28134 xmlSchemaClearValidCtxt(vctxt); | |
| 28135 } | |
| 28136 | |
| 28137 static int | |
| 28138 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt) | |
| 28139 { | |
| 28140 int ret = 0; | |
| 28141 | |
| 28142 if (xmlSchemaPreRun(vctxt) < 0) | |
| 28143 return(-1); | |
| 28144 | |
| 28145 if (vctxt->doc != NULL) { | |
| 28146 /* | |
| 28147 * Tree validation. | |
| 28148 */ | |
| 28149 ret = xmlSchemaVDocWalk(vctxt); | |
| 28150 #ifdef LIBXML_READER_ENABLED | |
| 28151 } else if (vctxt->reader != NULL) { | |
| 28152 /* | |
| 28153 * XML Reader validation. | |
| 28154 */ | |
| 28155 #ifdef XML_SCHEMA_READER_ENABLED | |
| 28156 ret = xmlSchemaVReaderWalk(vctxt); | |
| 28157 #endif | |
| 28158 #endif | |
| 28159 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) { | |
| 28160 /* | |
| 28161 * SAX validation. | |
| 28162 */ | |
| 28163 ret = xmlParseDocument(vctxt->parserCtxt); | |
| 28164 } else { | |
| 28165 VERROR_INT("xmlSchemaVStart", | |
| 28166 "no instance to validate"); | |
| 28167 ret = -1; | |
| 28168 } | |
| 28169 | |
| 28170 xmlSchemaPostRun(vctxt); | |
| 28171 if (ret == 0) | |
| 28172 ret = vctxt->err; | |
| 28173 return (ret); | |
| 28174 } | |
| 28175 | |
| 28176 /** | |
| 28177 * xmlSchemaValidateOneElement: | |
| 28178 * @ctxt: a schema validation context | |
| 28179 * @elem: an element node | |
| 28180 * | |
| 28181 * Validate a branch of a tree, starting with the given @elem. | |
| 28182 * | |
| 28183 * Returns 0 if the element and its subtree is valid, a positive error | |
| 28184 * code number otherwise and -1 in case of an internal or API error. | |
| 28185 */ | |
| 28186 int | |
| 28187 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem) | |
| 28188 { | |
| 28189 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE)) | |
| 28190 return (-1); | |
| 28191 | |
| 28192 if (ctxt->schema == NULL) | |
| 28193 return (-1); | |
| 28194 | |
| 28195 ctxt->doc = elem->doc; | |
| 28196 ctxt->node = elem; | |
| 28197 ctxt->validationRoot = elem; | |
| 28198 return(xmlSchemaVStart(ctxt)); | |
| 28199 } | |
| 28200 | |
| 28201 /** | |
| 28202 * xmlSchemaValidateDoc: | |
| 28203 * @ctxt: a schema validation context | |
| 28204 * @doc: a parsed document tree | |
| 28205 * | |
| 28206 * Validate a document tree in memory. | |
| 28207 * | |
| 28208 * Returns 0 if the document is schemas valid, a positive error code | |
| 28209 * number otherwise and -1 in case of internal or API error. | |
| 28210 */ | |
| 28211 int | |
| 28212 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) | |
| 28213 { | |
| 28214 if ((ctxt == NULL) || (doc == NULL)) | |
| 28215 return (-1); | |
| 28216 | |
| 28217 ctxt->doc = doc; | |
| 28218 ctxt->node = xmlDocGetRootElement(doc); | |
| 28219 if (ctxt->node == NULL) { | |
| 28220 xmlSchemaCustomErr(ACTXT_CAST ctxt, | |
| 28221 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING, | |
| 28222 (xmlNodePtr) doc, NULL, | |
| 28223 "The document has no document element", NULL, NULL); | |
| 28224 return (ctxt->err); | |
| 28225 } | |
| 28226 ctxt->validationRoot = ctxt->node; | |
| 28227 return (xmlSchemaVStart(ctxt)); | |
| 28228 } | |
| 28229 | |
| 28230 | |
| 28231 /************************************************************************ | |
| 28232 * * | |
| 28233 * Function and data for SAX streaming API * | |
| 28234 * * | |
| 28235 ************************************************************************/ | |
| 28236 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData; | |
| 28237 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr; | |
| 28238 | |
| 28239 struct _xmlSchemaSplitSAXData { | |
| 28240 xmlSAXHandlerPtr user_sax; | |
| 28241 void *user_data; | |
| 28242 xmlSchemaValidCtxtPtr ctxt; | |
| 28243 xmlSAXHandlerPtr schemas_sax; | |
| 28244 }; | |
| 28245 | |
| 28246 #define XML_SAX_PLUG_MAGIC 0xdc43ba21 | |
| 28247 | |
| 28248 struct _xmlSchemaSAXPlug { | |
| 28249 unsigned int magic; | |
| 28250 | |
| 28251 /* the original callbacks informations */ | |
| 28252 xmlSAXHandlerPtr *user_sax_ptr; | |
| 28253 xmlSAXHandlerPtr user_sax; | |
| 28254 void **user_data_ptr; | |
| 28255 void *user_data; | |
| 28256 | |
| 28257 /* the block plugged back and validation informations */ | |
| 28258 xmlSAXHandler schemas_sax; | |
| 28259 xmlSchemaValidCtxtPtr ctxt; | |
| 28260 }; | |
| 28261 | |
| 28262 /* All those functions just bounces to the user provided SAX handlers */ | |
| 28263 static void | |
| 28264 internalSubsetSplit(void *ctx, const xmlChar *name, | |
| 28265 const xmlChar *ExternalID, const xmlChar *SystemID) | |
| 28266 { | |
| 28267 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28268 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28269 (ctxt->user_sax->internalSubset != NULL)) | |
| 28270 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID, | |
| 28271 SystemID); | |
| 28272 } | |
| 28273 | |
| 28274 static int | |
| 28275 isStandaloneSplit(void *ctx) | |
| 28276 { | |
| 28277 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28278 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28279 (ctxt->user_sax->isStandalone != NULL)) | |
| 28280 return(ctxt->user_sax->isStandalone(ctxt->user_data)); | |
| 28281 return(0); | |
| 28282 } | |
| 28283 | |
| 28284 static int | |
| 28285 hasInternalSubsetSplit(void *ctx) | |
| 28286 { | |
| 28287 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28288 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28289 (ctxt->user_sax->hasInternalSubset != NULL)) | |
| 28290 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data)); | |
| 28291 return(0); | |
| 28292 } | |
| 28293 | |
| 28294 static int | |
| 28295 hasExternalSubsetSplit(void *ctx) | |
| 28296 { | |
| 28297 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28298 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28299 (ctxt->user_sax->hasExternalSubset != NULL)) | |
| 28300 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data)); | |
| 28301 return(0); | |
| 28302 } | |
| 28303 | |
| 28304 static void | |
| 28305 externalSubsetSplit(void *ctx, const xmlChar *name, | |
| 28306 const xmlChar *ExternalID, const xmlChar *SystemID) | |
| 28307 { | |
| 28308 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28309 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28310 (ctxt->user_sax->externalSubset != NULL)) | |
| 28311 ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID, | |
| 28312 SystemID); | |
| 28313 } | |
| 28314 | |
| 28315 static xmlParserInputPtr | |
| 28316 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId) | |
| 28317 { | |
| 28318 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28319 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28320 (ctxt->user_sax->resolveEntity != NULL)) | |
| 28321 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId, | |
| 28322 systemId)); | |
| 28323 return(NULL); | |
| 28324 } | |
| 28325 | |
| 28326 static xmlEntityPtr | |
| 28327 getEntitySplit(void *ctx, const xmlChar *name) | |
| 28328 { | |
| 28329 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28330 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28331 (ctxt->user_sax->getEntity != NULL)) | |
| 28332 return(ctxt->user_sax->getEntity(ctxt->user_data, name)); | |
| 28333 return(NULL); | |
| 28334 } | |
| 28335 | |
| 28336 static xmlEntityPtr | |
| 28337 getParameterEntitySplit(void *ctx, const xmlChar *name) | |
| 28338 { | |
| 28339 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28340 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28341 (ctxt->user_sax->getParameterEntity != NULL)) | |
| 28342 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name)); | |
| 28343 return(NULL); | |
| 28344 } | |
| 28345 | |
| 28346 | |
| 28347 static void | |
| 28348 entityDeclSplit(void *ctx, const xmlChar *name, int type, | |
| 28349 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) | |
| 28350 { | |
| 28351 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28352 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28353 (ctxt->user_sax->entityDecl != NULL)) | |
| 28354 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId, | |
| 28355 systemId, content); | |
| 28356 } | |
| 28357 | |
| 28358 static void | |
| 28359 attributeDeclSplit(void *ctx, const xmlChar * elem, | |
| 28360 const xmlChar * name, int type, int def, | |
| 28361 const xmlChar * defaultValue, xmlEnumerationPtr tree) | |
| 28362 { | |
| 28363 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28364 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28365 (ctxt->user_sax->attributeDecl != NULL)) { | |
| 28366 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type, | |
| 28367 def, defaultValue, tree); | |
| 28368 } else { | |
| 28369 xmlFreeEnumeration(tree); | |
| 28370 } | |
| 28371 } | |
| 28372 | |
| 28373 static void | |
| 28374 elementDeclSplit(void *ctx, const xmlChar *name, int type, | |
| 28375 xmlElementContentPtr content) | |
| 28376 { | |
| 28377 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28378 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28379 (ctxt->user_sax->elementDecl != NULL)) | |
| 28380 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content); | |
| 28381 } | |
| 28382 | |
| 28383 static void | |
| 28384 notationDeclSplit(void *ctx, const xmlChar *name, | |
| 28385 const xmlChar *publicId, const xmlChar *systemId) | |
| 28386 { | |
| 28387 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28388 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28389 (ctxt->user_sax->notationDecl != NULL)) | |
| 28390 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId, | |
| 28391 systemId); | |
| 28392 } | |
| 28393 | |
| 28394 static void | |
| 28395 unparsedEntityDeclSplit(void *ctx, const xmlChar *name, | |
| 28396 const xmlChar *publicId, const xmlChar *systemId, | |
| 28397 const xmlChar *notationName) | |
| 28398 { | |
| 28399 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28400 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28401 (ctxt->user_sax->unparsedEntityDecl != NULL)) | |
| 28402 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId, | |
| 28403 systemId, notationName); | |
| 28404 } | |
| 28405 | |
| 28406 static void | |
| 28407 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc) | |
| 28408 { | |
| 28409 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28410 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28411 (ctxt->user_sax->setDocumentLocator != NULL)) | |
| 28412 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc); | |
| 28413 } | |
| 28414 | |
| 28415 static void | |
| 28416 startDocumentSplit(void *ctx) | |
| 28417 { | |
| 28418 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28419 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28420 (ctxt->user_sax->startDocument != NULL)) | |
| 28421 ctxt->user_sax->startDocument(ctxt->user_data); | |
| 28422 } | |
| 28423 | |
| 28424 static void | |
| 28425 endDocumentSplit(void *ctx) | |
| 28426 { | |
| 28427 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28428 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28429 (ctxt->user_sax->endDocument != NULL)) | |
| 28430 ctxt->user_sax->endDocument(ctxt->user_data); | |
| 28431 } | |
| 28432 | |
| 28433 static void | |
| 28434 processingInstructionSplit(void *ctx, const xmlChar *target, | |
| 28435 const xmlChar *data) | |
| 28436 { | |
| 28437 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28438 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28439 (ctxt->user_sax->processingInstruction != NULL)) | |
| 28440 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data); | |
| 28441 } | |
| 28442 | |
| 28443 static void | |
| 28444 commentSplit(void *ctx, const xmlChar *value) | |
| 28445 { | |
| 28446 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28447 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28448 (ctxt->user_sax->comment != NULL)) | |
| 28449 ctxt->user_sax->comment(ctxt->user_data, value); | |
| 28450 } | |
| 28451 | |
| 28452 /* | |
| 28453 * Varargs error callbacks to the user application, harder ... | |
| 28454 */ | |
| 28455 | |
| 28456 static void XMLCDECL | |
| 28457 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { | |
| 28458 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28459 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28460 (ctxt->user_sax->warning != NULL)) { | |
| 28461 TODO | |
| 28462 } | |
| 28463 } | |
| 28464 static void XMLCDECL | |
| 28465 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { | |
| 28466 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28467 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28468 (ctxt->user_sax->error != NULL)) { | |
| 28469 TODO | |
| 28470 } | |
| 28471 } | |
| 28472 static void XMLCDECL | |
| 28473 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { | |
| 28474 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28475 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28476 (ctxt->user_sax->fatalError != NULL)) { | |
| 28477 TODO | |
| 28478 } | |
| 28479 } | |
| 28480 | |
| 28481 /* | |
| 28482 * Those are function where both the user handler and the schemas handler | |
| 28483 * need to be called. | |
| 28484 */ | |
| 28485 static void | |
| 28486 charactersSplit(void *ctx, const xmlChar *ch, int len) | |
| 28487 { | |
| 28488 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28489 if (ctxt == NULL) | |
| 28490 return; | |
| 28491 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL)) | |
| 28492 ctxt->user_sax->characters(ctxt->user_data, ch, len); | |
| 28493 if (ctxt->ctxt != NULL) | |
| 28494 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len); | |
| 28495 } | |
| 28496 | |
| 28497 static void | |
| 28498 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len) | |
| 28499 { | |
| 28500 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28501 if (ctxt == NULL) | |
| 28502 return; | |
| 28503 if ((ctxt->user_sax != NULL) && | |
| 28504 (ctxt->user_sax->ignorableWhitespace != NULL)) | |
| 28505 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len); | |
| 28506 if (ctxt->ctxt != NULL) | |
| 28507 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len); | |
| 28508 } | |
| 28509 | |
| 28510 static void | |
| 28511 cdataBlockSplit(void *ctx, const xmlChar *value, int len) | |
| 28512 { | |
| 28513 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28514 if (ctxt == NULL) | |
| 28515 return; | |
| 28516 if ((ctxt->user_sax != NULL) && | |
| 28517 (ctxt->user_sax->cdataBlock != NULL)) | |
| 28518 ctxt->user_sax->cdataBlock(ctxt->user_data, value, len); | |
| 28519 if (ctxt->ctxt != NULL) | |
| 28520 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len); | |
| 28521 } | |
| 28522 | |
| 28523 static void | |
| 28524 referenceSplit(void *ctx, const xmlChar *name) | |
| 28525 { | |
| 28526 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28527 if (ctxt == NULL) | |
| 28528 return; | |
| 28529 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | |
| 28530 (ctxt->user_sax->reference != NULL)) | |
| 28531 ctxt->user_sax->reference(ctxt->user_data, name); | |
| 28532 if (ctxt->ctxt != NULL) | |
| 28533 xmlSchemaSAXHandleReference(ctxt->user_data, name); | |
| 28534 } | |
| 28535 | |
| 28536 static void | |
| 28537 startElementNsSplit(void *ctx, const xmlChar * localname, | |
| 28538 const xmlChar * prefix, const xmlChar * URI, | |
| 28539 int nb_namespaces, const xmlChar ** namespaces, | |
| 28540 int nb_attributes, int nb_defaulted, | |
| 28541 const xmlChar ** attributes) { | |
| 28542 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28543 if (ctxt == NULL) | |
| 28544 return; | |
| 28545 if ((ctxt->user_sax != NULL) && | |
| 28546 (ctxt->user_sax->startElementNs != NULL)) | |
| 28547 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix, | |
| 28548 URI, nb_namespaces, namespaces, | |
| 28549 nb_attributes, nb_defaulted, | |
| 28550 attributes); | |
| 28551 if (ctxt->ctxt != NULL) | |
| 28552 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix, | |
| 28553 URI, nb_namespaces, namespaces, | |
| 28554 nb_attributes, nb_defaulted, | |
| 28555 attributes); | |
| 28556 } | |
| 28557 | |
| 28558 static void | |
| 28559 endElementNsSplit(void *ctx, const xmlChar * localname, | |
| 28560 const xmlChar * prefix, const xmlChar * URI) { | |
| 28561 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | |
| 28562 if (ctxt == NULL) | |
| 28563 return; | |
| 28564 if ((ctxt->user_sax != NULL) && | |
| 28565 (ctxt->user_sax->endElementNs != NULL)) | |
| 28566 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI); | |
| 28567 if (ctxt->ctxt != NULL) | |
| 28568 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI); | |
| 28569 } | |
| 28570 | |
| 28571 /** | |
| 28572 * xmlSchemaSAXPlug: | |
| 28573 * @ctxt: a schema validation context | |
| 28574 * @sax: a pointer to the original xmlSAXHandlerPtr | |
| 28575 * @user_data: a pointer to the original SAX user data pointer | |
| 28576 * | |
| 28577 * Plug a SAX based validation layer in a SAX parsing event flow. | |
| 28578 * The original @saxptr and @dataptr data are replaced by new pointers | |
| 28579 * but the calls to the original will be maintained. | |
| 28580 * | |
| 28581 * Returns a pointer to a data structure needed to unplug the validation layer | |
| 28582 * or NULL in case of errors. | |
| 28583 */ | |
| 28584 xmlSchemaSAXPlugPtr | |
| 28585 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt, | |
| 28586 xmlSAXHandlerPtr *sax, void **user_data) | |
| 28587 { | |
| 28588 xmlSchemaSAXPlugPtr ret; | |
| 28589 xmlSAXHandlerPtr old_sax; | |
| 28590 | |
| 28591 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL)) | |
| 28592 return(NULL); | |
| 28593 | |
| 28594 /* | |
| 28595 * We only allow to plug into SAX2 event streams | |
| 28596 */ | |
| 28597 old_sax = *sax; | |
| 28598 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC)) | |
| 28599 return(NULL); | |
| 28600 if ((old_sax != NULL) && | |
| 28601 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) && | |
| 28602 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL))) | |
| 28603 return(NULL); | |
| 28604 | |
| 28605 /* | |
| 28606 * everything seems right allocate the local data needed for that layer | |
| 28607 */ | |
| 28608 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct)); | |
| 28609 if (ret == NULL) { | |
| 28610 return(NULL); | |
| 28611 } | |
| 28612 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct)); | |
| 28613 ret->magic = XML_SAX_PLUG_MAGIC; | |
| 28614 ret->schemas_sax.initialized = XML_SAX2_MAGIC; | |
| 28615 ret->ctxt = ctxt; | |
| 28616 ret->user_sax_ptr = sax; | |
| 28617 ret->user_sax = old_sax; | |
| 28618 if (old_sax == NULL) { | |
| 28619 /* | |
| 28620 * go direct, no need for the split block and functions. | |
| 28621 */ | |
| 28622 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs; | |
| 28623 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs; | |
| 28624 /* | |
| 28625 * Note that we use the same text-function for both, to prevent | |
| 28626 * the parser from testing for ignorable whitespace. | |
| 28627 */ | |
| 28628 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText; | |
| 28629 ret->schemas_sax.characters = xmlSchemaSAXHandleText; | |
| 28630 | |
| 28631 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection; | |
| 28632 ret->schemas_sax.reference = xmlSchemaSAXHandleReference; | |
| 28633 | |
| 28634 ret->user_data = ctxt; | |
| 28635 *user_data = ctxt; | |
| 28636 } else { | |
| 28637 /* | |
| 28638 * for each callback unused by Schemas initialize it to the Split | |
| 28639 * routine only if non NULL in the user block, this can speed up | |
| 28640 * things at the SAX level. | |
| 28641 */ | |
| 28642 if (old_sax->internalSubset != NULL) | |
| 28643 ret->schemas_sax.internalSubset = internalSubsetSplit; | |
| 28644 if (old_sax->isStandalone != NULL) | |
| 28645 ret->schemas_sax.isStandalone = isStandaloneSplit; | |
| 28646 if (old_sax->hasInternalSubset != NULL) | |
| 28647 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit; | |
| 28648 if (old_sax->hasExternalSubset != NULL) | |
| 28649 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit; | |
| 28650 if (old_sax->resolveEntity != NULL) | |
| 28651 ret->schemas_sax.resolveEntity = resolveEntitySplit; | |
| 28652 if (old_sax->getEntity != NULL) | |
| 28653 ret->schemas_sax.getEntity = getEntitySplit; | |
| 28654 if (old_sax->entityDecl != NULL) | |
| 28655 ret->schemas_sax.entityDecl = entityDeclSplit; | |
| 28656 if (old_sax->notationDecl != NULL) | |
| 28657 ret->schemas_sax.notationDecl = notationDeclSplit; | |
| 28658 if (old_sax->attributeDecl != NULL) | |
| 28659 ret->schemas_sax.attributeDecl = attributeDeclSplit; | |
| 28660 if (old_sax->elementDecl != NULL) | |
| 28661 ret->schemas_sax.elementDecl = elementDeclSplit; | |
| 28662 if (old_sax->unparsedEntityDecl != NULL) | |
| 28663 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit; | |
| 28664 if (old_sax->setDocumentLocator != NULL) | |
| 28665 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit; | |
| 28666 if (old_sax->startDocument != NULL) | |
| 28667 ret->schemas_sax.startDocument = startDocumentSplit; | |
| 28668 if (old_sax->endDocument != NULL) | |
| 28669 ret->schemas_sax.endDocument = endDocumentSplit; | |
| 28670 if (old_sax->processingInstruction != NULL) | |
| 28671 ret->schemas_sax.processingInstruction = processingInstructionSplit; | |
| 28672 if (old_sax->comment != NULL) | |
| 28673 ret->schemas_sax.comment = commentSplit; | |
| 28674 if (old_sax->warning != NULL) | |
| 28675 ret->schemas_sax.warning = warningSplit; | |
| 28676 if (old_sax->error != NULL) | |
| 28677 ret->schemas_sax.error = errorSplit; | |
| 28678 if (old_sax->fatalError != NULL) | |
| 28679 ret->schemas_sax.fatalError = fatalErrorSplit; | |
| 28680 if (old_sax->getParameterEntity != NULL) | |
| 28681 ret->schemas_sax.getParameterEntity = getParameterEntitySplit; | |
| 28682 if (old_sax->externalSubset != NULL) | |
| 28683 ret->schemas_sax.externalSubset = externalSubsetSplit; | |
| 28684 | |
| 28685 /* | |
| 28686 * the 6 schemas callback have to go to the splitter functions | |
| 28687 * Note that we use the same text-function for ignorableWhitespace | |
| 28688 * if possible, to prevent the parser from testing for ignorable | |
| 28689 * whitespace. | |
| 28690 */ | |
| 28691 ret->schemas_sax.characters = charactersSplit; | |
| 28692 if ((old_sax->ignorableWhitespace != NULL) && | |
| 28693 (old_sax->ignorableWhitespace != old_sax->characters)) | |
| 28694 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit; | |
| 28695 else | |
| 28696 ret->schemas_sax.ignorableWhitespace = charactersSplit; | |
| 28697 ret->schemas_sax.cdataBlock = cdataBlockSplit; | |
| 28698 ret->schemas_sax.reference = referenceSplit; | |
| 28699 ret->schemas_sax.startElementNs = startElementNsSplit; | |
| 28700 ret->schemas_sax.endElementNs = endElementNsSplit; | |
| 28701 | |
| 28702 ret->user_data_ptr = user_data; | |
| 28703 ret->user_data = *user_data; | |
| 28704 *user_data = ret; | |
| 28705 } | |
| 28706 | |
| 28707 /* | |
| 28708 * plug the pointers back. | |
| 28709 */ | |
| 28710 *sax = &(ret->schemas_sax); | |
| 28711 ctxt->sax = *sax; | |
| 28712 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM; | |
| 28713 xmlSchemaPreRun(ctxt); | |
| 28714 return(ret); | |
| 28715 } | |
| 28716 | |
| 28717 /** | |
| 28718 * xmlSchemaSAXUnplug: | |
| 28719 * @plug: a data structure returned by xmlSchemaSAXPlug | |
| 28720 * | |
| 28721 * Unplug a SAX based validation layer in a SAX parsing event flow. | |
| 28722 * The original pointers used in the call are restored. | |
| 28723 * | |
| 28724 * Returns 0 in case of success and -1 in case of failure. | |
| 28725 */ | |
| 28726 int | |
| 28727 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug) | |
| 28728 { | |
| 28729 xmlSAXHandlerPtr *sax; | |
| 28730 void **user_data; | |
| 28731 | |
| 28732 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC)) | |
| 28733 return(-1); | |
| 28734 plug->magic = 0; | |
| 28735 | |
| 28736 xmlSchemaPostRun(plug->ctxt); | |
| 28737 /* restore the data */ | |
| 28738 sax = plug->user_sax_ptr; | |
| 28739 *sax = plug->user_sax; | |
| 28740 if (plug->user_sax != NULL) { | |
| 28741 user_data = plug->user_data_ptr; | |
| 28742 *user_data = plug->user_data; | |
| 28743 } | |
| 28744 | |
| 28745 /* free and return */ | |
| 28746 xmlFree(plug); | |
| 28747 return(0); | |
| 28748 } | |
| 28749 | |
| 28750 /** | |
| 28751 * xmlSchemaValidateSetLocator: | |
| 28752 * @vctxt: a schema validation context | |
| 28753 * @f: the locator function pointer | |
| 28754 * @ctxt: the locator context | |
| 28755 * | |
| 28756 * Allows to set a locator function to the validation context, | |
| 28757 * which will be used to provide file and line information since | |
| 28758 * those are not provided as part of the SAX validation flow | |
| 28759 * Setting @f to NULL disable the locator. | |
| 28760 */ | |
| 28761 | |
| 28762 void | |
| 28763 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt, | |
| 28764 xmlSchemaValidityLocatorFunc f, | |
| 28765 void *ctxt) | |
| 28766 { | |
| 28767 if (vctxt == NULL) return; | |
| 28768 vctxt->locFunc = f; | |
| 28769 vctxt->locCtxt = ctxt; | |
| 28770 } | |
| 28771 | |
| 28772 /** | |
| 28773 * xmlSchemaValidateStreamLocator: | |
| 28774 * @ctx: the xmlTextReaderPtr used | |
| 28775 * @file: returned file information | |
| 28776 * @line: returned line information | |
| 28777 * | |
| 28778 * Internal locator function for the readers | |
| 28779 * | |
| 28780 * Returns 0 in case the Schema validation could be (des)activated and | |
| 28781 * -1 in case of error. | |
| 28782 */ | |
| 28783 static int | |
| 28784 xmlSchemaValidateStreamLocator(void *ctx, const char **file, | |
| 28785 unsigned long *line) { | |
| 28786 xmlParserCtxtPtr ctxt; | |
| 28787 | |
| 28788 if ((ctx == NULL) || ((file == NULL) && (line == NULL))) | |
| 28789 return(-1); | |
| 28790 | |
| 28791 if (file != NULL) | |
| 28792 *file = NULL; | |
| 28793 if (line != NULL) | |
| 28794 *line = 0; | |
| 28795 | |
| 28796 ctxt = (xmlParserCtxtPtr) ctx; | |
| 28797 if (ctxt->input != NULL) { | |
| 28798 if (file != NULL) | |
| 28799 *file = ctxt->input->filename; | |
| 28800 if (line != NULL) | |
| 28801 *line = ctxt->input->line; | |
| 28802 return(0); | |
| 28803 } | |
| 28804 return(-1); | |
| 28805 } | |
| 28806 | |
| 28807 /** | |
| 28808 * xmlSchemaValidateStream: | |
| 28809 * @ctxt: a schema validation context | |
| 28810 * @input: the input to use for reading the data | |
| 28811 * @enc: an optional encoding information | |
| 28812 * @sax: a SAX handler for the resulting events | |
| 28813 * @user_data: the context to provide to the SAX handler. | |
| 28814 * | |
| 28815 * Validate an input based on a flow of SAX event from the parser | |
| 28816 * and forward the events to the @sax handler with the provided @user_data | |
| 28817 * the user provided @sax handler must be a SAX2 one. | |
| 28818 * | |
| 28819 * Returns 0 if the document is schemas valid, a positive error code | |
| 28820 * number otherwise and -1 in case of internal or API error. | |
| 28821 */ | |
| 28822 int | |
| 28823 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt, | |
| 28824 xmlParserInputBufferPtr input, xmlCharEncoding enc, | |
| 28825 xmlSAXHandlerPtr sax, void *user_data) | |
| 28826 { | |
| 28827 xmlSchemaSAXPlugPtr plug = NULL; | |
| 28828 xmlSAXHandlerPtr old_sax = NULL; | |
| 28829 xmlParserCtxtPtr pctxt = NULL; | |
| 28830 xmlParserInputPtr inputStream = NULL; | |
| 28831 int ret; | |
| 28832 | |
| 28833 if ((ctxt == NULL) || (input == NULL)) | |
| 28834 return (-1); | |
| 28835 | |
| 28836 /* | |
| 28837 * prepare the parser | |
| 28838 */ | |
| 28839 pctxt = xmlNewParserCtxt(); | |
| 28840 if (pctxt == NULL) | |
| 28841 return (-1); | |
| 28842 old_sax = pctxt->sax; | |
| 28843 pctxt->sax = sax; | |
| 28844 pctxt->userData = user_data; | |
| 28845 #if 0 | |
| 28846 if (options) | |
| 28847 xmlCtxtUseOptions(pctxt, options); | |
| 28848 #endif | |
| 28849 pctxt->linenumbers = 1; | |
| 28850 xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt); | |
| 28851 | |
| 28852 inputStream = xmlNewIOInputStream(pctxt, input, enc);; | |
| 28853 if (inputStream == NULL) { | |
| 28854 ret = -1; | |
| 28855 goto done; | |
| 28856 } | |
| 28857 inputPush(pctxt, inputStream); | |
| 28858 ctxt->parserCtxt = pctxt; | |
| 28859 ctxt->input = input; | |
| 28860 | |
| 28861 /* | |
| 28862 * Plug the validation and launch the parsing | |
| 28863 */ | |
| 28864 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData)); | |
| 28865 if (plug == NULL) { | |
| 28866 ret = -1; | |
| 28867 goto done; | |
| 28868 } | |
| 28869 ctxt->input = input; | |
| 28870 ctxt->enc = enc; | |
| 28871 ctxt->sax = pctxt->sax; | |
| 28872 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM; | |
| 28873 ret = xmlSchemaVStart(ctxt); | |
| 28874 | |
| 28875 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) { | |
| 28876 ret = ctxt->parserCtxt->errNo; | |
| 28877 if (ret == 0) | |
| 28878 ret = 1; | |
| 28879 } | |
| 28880 | |
| 28881 done: | |
| 28882 ctxt->parserCtxt = NULL; | |
| 28883 ctxt->sax = NULL; | |
| 28884 ctxt->input = NULL; | |
| 28885 if (plug != NULL) { | |
| 28886 xmlSchemaSAXUnplug(plug); | |
| 28887 } | |
| 28888 /* cleanup */ | |
| 28889 if (pctxt != NULL) { | |
| 28890 pctxt->sax = old_sax; | |
| 28891 xmlFreeParserCtxt(pctxt); | |
| 28892 } | |
| 28893 return (ret); | |
| 28894 } | |
| 28895 | |
| 28896 /** | |
| 28897 * xmlSchemaValidateFile: | |
| 28898 * @ctxt: a schema validation context | |
| 28899 * @filename: the URI of the instance | |
| 28900 * @options: a future set of options, currently unused | |
| 28901 * | |
| 28902 * Do a schemas validation of the given resource, it will use the | |
| 28903 * SAX streamable validation internally. | |
| 28904 * | |
| 28905 * Returns 0 if the document is valid, a positive error code | |
| 28906 * number otherwise and -1 in case of an internal or API error. | |
| 28907 */ | |
| 28908 int | |
| 28909 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt, | |
| 28910 const char * filename, | |
| 28911 int options ATTRIBUTE_UNUSED) | |
| 28912 { | |
| 28913 int ret; | |
| 28914 xmlParserInputBufferPtr input; | |
| 28915 | |
| 28916 if ((ctxt == NULL) || (filename == NULL)) | |
| 28917 return (-1); | |
| 28918 | |
| 28919 input = xmlParserInputBufferCreateFilename(filename, | |
| 28920 XML_CHAR_ENCODING_NONE); | |
| 28921 if (input == NULL) | |
| 28922 return (-1); | |
| 28923 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE, | |
| 28924 NULL, NULL); | |
| 28925 return (ret); | |
| 28926 } | |
| 28927 | |
| 28928 /** | |
| 28929 * xmlSchemaValidCtxtGetParserCtxt: | |
| 28930 * @ctxt: a schema validation context | |
| 28931 * | |
| 28932 * allow access to the parser context of the schema validation context | |
| 28933 * | |
| 28934 * Returns the parser context of the schema validation context or NULL | |
| 28935 * in case of error. | |
| 28936 */ | |
| 28937 xmlParserCtxtPtr | |
| 28938 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt) | |
| 28939 { | |
| 28940 if (ctxt == NULL) | |
| 28941 return(NULL); | |
| 28942 return (ctxt->parserCtxt); | |
| 28943 } | |
| 28944 | |
| 28945 #define bottom_xmlschemas | |
| 28946 #include "elfgcchack.h" | |
| 28947 #endif /* LIBXML_SCHEMAS_ENABLED */ | |
| OLD | NEW |