1/* 2 * schemas.c : implementation of the XML Schema handling and 3 * schema validity checking 4 * 5 * See Copyright for the status of this software. 6 * 7 * Daniel Veillard <veillard@redhat.com> 8 */ 9 10/* 11 * TODO: 12 * - when types are redefined in includes, check that all 13 * types in the redef list are equal 14 * -> need a type equality operation. 15 * - if we don't intend to use the schema for schemas, we 16 * need to validate all schema attributes (ref, type, name) 17 * against their types. 18 * - Eliminate item creation for: ?? 19 * 20 * URGENT TODO: 21 * - For xsi-driven schema acquisition, augment the IDCs after every 22 * acquisition episode (xmlSchemaAugmentIDC). 23 * 24 * NOTES: 25 * - Elimated item creation for: <restriction>, <extension>, 26 * <simpleContent>, <complexContent>, <list>, <union> 27 * 28 * PROBLEMS: 29 * - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html 30 * IDC XPath expression and chameleon includes: the targetNamespace is changed, so 31 * XPath will have trouble to resolve to this namespace, since not known. 32 * 33 * 34 * CONSTRAINTS: 35 * 36 * Schema Component Constraint: 37 * All Group Limited (cos-all-limited) 38 * Status: complete 39 * (1.2) 40 * In xmlSchemaGroupDefReferenceTermFixup() and 41 * (2) 42 * In xmlSchemaParseModelGroup() 43 * TODO: Actually this should go to component-level checks, 44 * but is done here due to performance. Move it to an other layer 45 * is schema construction via an API is implemented. 46 */ 47#define IN_LIBXML 48#include "libxml.h" 49 50#ifdef LIBXML_SCHEMAS_ENABLED 51 52#include <string.h> 53#include <libxml/xmlmemory.h> 54#include <libxml/parser.h> 55#include <libxml/parserInternals.h> 56#include <libxml/hash.h> 57#include <libxml/uri.h> 58#include <libxml/xmlschemas.h> 59#include <libxml/schemasInternals.h> 60#include <libxml/xmlschemastypes.h> 61#include <libxml/xmlautomata.h> 62#include <libxml/xmlregexp.h> 63#include <libxml/dict.h> 64#include <libxml/encoding.h> 65#include <libxml/xmlIO.h> 66#ifdef LIBXML_PATTERN_ENABLED 67#include <libxml/pattern.h> 68#endif 69#ifdef LIBXML_READER_ENABLED 70#include <libxml/xmlreader.h> 71#endif 72 73/* #define DEBUG 1 */ 74 75/* #define DEBUG_CONTENT 1 */ 76 77/* #define DEBUG_TYPE 1 */ 78 79/* #define DEBUG_CONTENT_REGEXP 1 */ 80 81/* #define DEBUG_AUTOMATA 1 */ 82 83/* #define DEBUG_IDC */ 84 85/* #define DEBUG_IDC_NODE_TABLE */ 86 87/* #define WXS_ELEM_DECL_CONS_ENABLED */ 88 89#ifdef DEBUG_IDC 90 #ifndef DEBUG_IDC_NODE_TABLE 91 #define DEBUG_IDC_NODE_TABLE 92 #endif 93#endif 94 95/* #define ENABLE_PARTICLE_RESTRICTION 1 */ 96 97#define ENABLE_REDEFINE 98 99/* #define ENABLE_NAMED_LOCALS */ 100 101/* #define ENABLE_IDC_NODE_TABLES_TEST */ 102 103#define DUMP_CONTENT_MODEL 104 105#ifdef LIBXML_READER_ENABLED 106/* #define XML_SCHEMA_READER_ENABLED */ 107#endif 108 109#define UNBOUNDED (1 << 30) 110#define TODO \ 111 xmlGenericError(xmlGenericErrorContext, \ 112 "Unimplemented block at %s:%d\n", \ 113 __FILE__, __LINE__); 114 115#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##" 116 117/* 118 * The XML Schemas namespaces 119 */ 120static const xmlChar *xmlSchemaNs = (const xmlChar *) 121 "http://www.w3.org/2001/XMLSchema"; 122 123static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *) 124 "http://www.w3.org/2001/XMLSchema-instance"; 125 126static const xmlChar *xmlNamespaceNs = (const xmlChar *) 127 "http://www.w3.org/2000/xmlns/"; 128 129/* 130* Come casting macros. 131*/ 132#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr) 133#define PCTXT_CAST (xmlSchemaParserCtxtPtr) 134#define VCTXT_CAST (xmlSchemaValidCtxtPtr) 135#define WXS_BASIC_CAST (xmlSchemaBasicItemPtr) 136#define WXS_TREE_CAST (xmlSchemaTreeItemPtr) 137#define WXS_PTC_CAST (xmlSchemaParticlePtr) 138#define WXS_TYPE_CAST (xmlSchemaTypePtr) 139#define WXS_ELEM_CAST (xmlSchemaElementPtr) 140#define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr) 141#define WXS_ATTR_CAST (xmlSchemaAttributePtr) 142#define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr) 143#define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr) 144#define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr) 145#define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr) 146#define WXS_IDC_CAST (xmlSchemaIDCPtr) 147#define WXS_QNAME_CAST (xmlSchemaQNameRefPtr) 148#define WXS_LIST_CAST (xmlSchemaItemListPtr) 149 150/* 151* Macros to query common properties of components. 152*/ 153#define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i)) 154 155#define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i)) 156/* 157* Macros for element declarations. 158*/ 159#define WXS_ELEM_TYPEDEF(e) (e)->subtypes 160 161#define WXS_SUBST_HEAD(item) (item)->refDecl 162/* 163* Macros for attribute declarations. 164*/ 165#define WXS_ATTR_TYPEDEF(a) (a)->subtypes 166/* 167* Macros for attribute uses. 168*/ 169#define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl 170 171#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au)) 172 173#define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name 174 175#define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace 176/* 177* Macros for attribute groups. 178*/ 179#define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) 180#define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) 181/* 182* Macros for particles. 183*/ 184#define WXS_PARTICLE(p) WXS_PTC_CAST (p) 185 186#define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children 187 188#define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p)) 189 190#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children 191/* 192* Macros for model groups definitions. 193*/ 194#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children 195/* 196* Macros for model groups. 197*/ 198#define WXS_IS_MODEL_GROUP(i) \ 199 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \ 200 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \ 201 ((i)->type == XML_SCHEMA_TYPE_ALL)) 202 203#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children 204/* 205* Macros for schema buckets. 206*/ 207#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \ 208 ((t) == XML_SCHEMA_SCHEMA_REDEFINE)) 209 210#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \ 211 ((t) == XML_SCHEMA_SCHEMA_IMPORT)) 212 213#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b)) 214 215#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b)) 216/* 217* Macros for complex/simple types. 218*/ 219#define WXS_IS_ANYTYPE(i) \ 220 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \ 221 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE)) 222 223#define WXS_IS_COMPLEX(i) \ 224 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \ 225 ((i)->builtInType == XML_SCHEMAS_ANYTYPE)) 226 227#define WXS_IS_SIMPLE(item) \ 228 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \ 229 ((item->type == XML_SCHEMA_TYPE_BASIC) && \ 230 (item->builtInType != XML_SCHEMAS_ANYTYPE))) 231 232#define WXS_IS_ANY_SIMPLE_TYPE(i) \ 233 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \ 234 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) 235 236#define WXS_IS_RESTRICTION(t) \ 237 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) 238 239#define WXS_IS_EXTENSION(t) \ 240 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) 241 242#define WXS_IS_TYPE_NOT_FIXED(i) \ 243 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \ 244 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0)) 245 246#define WXS_IS_TYPE_NOT_FIXED_1(item) \ 247 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \ 248 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0)) 249 250#define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) 251 252#define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) 253/* 254* Macros for exclusively for complex types. 255*/ 256#define WXS_HAS_COMPLEX_CONTENT(item) \ 257 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \ 258 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \ 259 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) 260 261#define WXS_HAS_SIMPLE_CONTENT(item) \ 262 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \ 263 (item->contentType == XML_SCHEMA_CONTENT_BASIC)) 264 265#define WXS_HAS_MIXED_CONTENT(item) \ 266 (item->contentType == XML_SCHEMA_CONTENT_MIXED) 267 268#define WXS_EMPTIABLE(t) \ 269 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes)) 270 271#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes 272 273#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes 274 275#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t)) 276/* 277* Macros for exclusively for simple types. 278*/ 279#define WXS_LIST_ITEMTYPE(t) (t)->subtypes 280 281#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) 282 283#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) 284 285#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) 286/* 287* Misc parser context macros. 288*/ 289#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor 290 291#define WXS_HAS_BUCKETS(ctx) \ 292( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \ 293(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) ) 294 295#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups 296 297#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket 298 299#define WXS_SCHEMA(ctx) (ctx)->schema 300 301#define WXS_ADD_LOCAL(ctx, item) \ 302 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item) 303 304#define WXS_ADD_GLOBAL(ctx, item) \ 305 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item) 306 307#define WXS_ADD_PENDING(ctx, item) \ 308 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item) 309/* 310* xmlSchemaItemList macros. 311*/ 312#define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0)) 313/* 314* Misc macros. 315*/ 316#define IS_SCHEMA(node, type) \ 317 ((node != NULL) && (node->ns != NULL) && \ 318 (xmlStrEqual(node->name, (const xmlChar *) type)) && \ 319 (xmlStrEqual(node->ns->href, xmlSchemaNs))) 320 321#define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; } 322 323/* 324* Since we put the default/fixed values into the dict, we can 325* use pointer comparison for those values. 326* REMOVED: (xmlStrEqual((v1), (v2))) 327*/ 328#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2)) 329 330#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED) 331 332#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0)) 333 334#define HFAILURE if (res == -1) goto exit_failure; 335 336#define HERROR if (res != 0) goto exit_error; 337 338#define HSTOP(ctx) if ((ctx)->stop) goto exit; 339/* 340* Some flags used for various schema constraints. 341*/ 342#define SUBSET_RESTRICTION 1<<0 343#define SUBSET_EXTENSION 1<<1 344#define SUBSET_SUBSTITUTION 1<<2 345#define SUBSET_LIST 1<<3 346#define SUBSET_UNION 1<<4 347 348typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo; 349typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr; 350 351typedef struct _xmlSchemaItemList xmlSchemaItemList; 352typedef xmlSchemaItemList *xmlSchemaItemListPtr; 353struct _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 362typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt; 363typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr; 364struct _xmlSchemaAbstractCtxt { 365 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */ 366}; 367 368typedef struct _xmlSchemaBucket xmlSchemaBucket; 369typedef 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 */ 381typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation; 382typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr; 383struct _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 393struct _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 */ 417typedef struct _xmlSchemaImport xmlSchemaImport; 418typedef xmlSchemaImport *xmlSchemaImportPtr; 419struct _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*/ 446typedef struct _xmlSchemaInclude xmlSchemaInclude; 447typedef xmlSchemaInclude *xmlSchemaIncludePtr; 448struct _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 */ 472typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem; 473typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr; 474struct _xmlSchemaBasicItem { 475 xmlSchemaTypeType type; 476}; 477 478/** 479 * xmlSchemaAnnotItem: 480 * 481 * The abstract base type for annotated schema components. 482 * (Extends xmlSchemaBasicItem) 483 */ 484typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem; 485typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr; 486struct _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 */ 497typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem; 498typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr; 499struct _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 */ 514typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse; 515typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr; 516struct _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 */ 539typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib; 540typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr; 541struct _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 */ 552typedef struct _xmlSchemaRedef xmlSchemaRedef; 553typedef xmlSchemaRedef *xmlSchemaRedefPtr; 554struct _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 */ 568typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt; 569typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr; 570struct _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 587struct _xmlSchemaParserCtxt { 588 int type; 589 void *errCtxt; /* user specific error context */ 590 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */ 591 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */ 592 int err; 593 int nberrors; 594 xmlStructuredErrorFunc serror; 595 596 xmlSchemaConstructionCtxtPtr constructor; 597 int ownsConstructor; /* TODO: Move this to parser *flags*. */ 598 599 /* xmlSchemaPtr topschema; */ 600 /* xmlHashTablePtr namespaces; */ 601 602 xmlSchemaPtr schema; /* The main schema in use */ 603 int counter; 604 605 const xmlChar *URL; 606 xmlDocPtr doc; 607 int preserve; /* Whether the doc should be freed */ 608 609 const char *buffer; 610 int size; 611 612 /* 613 * Used to build complex element content models 614 */ 615 xmlAutomataPtr am; 616 xmlAutomataStatePtr start; 617 xmlAutomataStatePtr end; 618 xmlAutomataStatePtr state; 619 620 xmlDictPtr dict; /* dictionnary for interned string names */ 621 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */ 622 int options; 623 xmlSchemaValidCtxtPtr vctxt; 624 int isS4S; 625 int isRedefine; 626 int xsiAssemble; 627 int stop; /* If the parser should stop; i.e. a critical error. */ 628 const xmlChar *targetNamespace; 629 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */ 630 631 xmlSchemaRedefPtr redef; /* Used for redefinitions. */ 632 int redefCounter; /* Used for redefinitions. */ 633 xmlSchemaItemListPtr attrProhibs; 634}; 635 636/** 637 * xmlSchemaQNameRef: 638 * 639 * A component reference item (not a schema component) 640 * (Extends xmlSchemaBasicItem) 641 */ 642typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef; 643typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr; 644struct _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 */ 659typedef struct _xmlSchemaParticle xmlSchemaParticle; 660typedef xmlSchemaParticle *xmlSchemaParticlePtr; 661struct _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 */ 679typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup; 680typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr; 681struct _xmlSchemaModelGroup { 682 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */ 683 xmlSchemaAnnotPtr annot; 684 xmlSchemaTreeItemPtr next; /* not used */ 685 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */ 686 xmlNodePtr node; 687}; 688 689#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0 690#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1 691/** 692 * xmlSchemaModelGroupDef: 693 * 694 * A model group definition component. 695 * (Extends xmlSchemaTreeItem) 696 */ 697typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef; 698typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr; 699struct _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 710typedef struct _xmlSchemaIDC xmlSchemaIDC; 711typedef xmlSchemaIDC *xmlSchemaIDCPtr; 712 713/** 714 * xmlSchemaIDCSelect: 715 * 716 * The identity-constraint "field" and "selector" item, holding the 717 * XPath expression. 718 */ 719typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect; 720typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr; 721struct _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 736struct _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 */ 754typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug; 755typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr; 756struct _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 */ 768typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey; 769typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr; 770struct _xmlSchemaPSVIIDCKey { 771 xmlSchemaTypePtr type; 772 xmlSchemaValPtr val; 773}; 774 775/** 776 * xmlSchemaPSVIIDCNode: 777 * 778 * The node table item of a node table. 779 */ 780typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode; 781typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr; 782struct _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 */ 795typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding; 796typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr; 797struct _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 813typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher; 814typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr; 815 816/** 817 * xmlSchemaIDCStateObj: 818 * 819 * The state object used to evaluate XPath expressions. 820 */ 821typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj; 822typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr; 823struct _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 */ 843struct _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 */ 879struct _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 936typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo; 937typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr; 938struct _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 */ 964struct _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 */ 1043typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup; 1044typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr; 1045struct _xmlSchemaSubstGroup { 1046 xmlSchemaElementPtr head; 1047 xmlSchemaItemListPtr members; 1048}; 1049 1050/************************************************************************ 1051 * * 1052 * Some predeclarations * 1053 * * 1054 ************************************************************************/ 1055 1056static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, 1057 xmlSchemaPtr schema, 1058 xmlNodePtr node); 1059static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt, 1060 xmlSchemaPtr schema, 1061 xmlNodePtr node); 1062static int 1063xmlSchemaTypeFixup(xmlSchemaTypePtr type, 1064 xmlSchemaAbstractCtxtPtr ctxt); 1065static const xmlChar * 1066xmlSchemaFacetTypeToString(xmlSchemaTypeType type); 1067static int 1068xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 1069 xmlNodePtr node); 1070static int 1071xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl, 1072 xmlSchemaParserCtxtPtr ctxt); 1073static void 1074xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt); 1075static xmlSchemaWhitespaceValueType 1076xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type); 1077static xmlSchemaTreeItemPtr 1078xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 1079 xmlNodePtr node, xmlSchemaTypeType type, 1080 int withParticle); 1081static const xmlChar * 1082xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item); 1083static xmlSchemaTypeLinkPtr 1084xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type); 1085static void 1086xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt, 1087 const char *funcName, 1088 const char *message); 1089static int 1090xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt, 1091 xmlSchemaTypePtr type, 1092 xmlSchemaTypePtr baseType, 1093 int subset); 1094static void 1095xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl, 1096 xmlSchemaParserCtxtPtr ctxt); 1097static void 1098xmlSchemaComponentListFree(xmlSchemaItemListPtr list); 1099static xmlSchemaQNameRefPtr 1100xmlSchemaParseAttributeGroupRef(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 */ 1116static const xmlChar * 1117xmlSchemaItemTypeToStr(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 */ 1172static const xmlChar * 1173xmlSchemaGetComponentTypeStr(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 */ 1196static xmlNodePtr 1197xmlSchemaGetComponentNode(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 */ 1244static xmlSchemaBasicItemPtr 1245xmlSchemaGetNextComponent(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 */ 1291static const xmlChar* 1292xmlSchemaFormatQName(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 1312static const xmlChar* 1313xmlSchemaFormatQNameNs(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 1321static const xmlChar * 1322xmlSchemaGetComponentName(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/* 1363static const xmlChar * 1364xmlSchemaGetQNameRefName(void *ref) 1365{ 1366 return(((xmlSchemaQNameRefPtr) ref)->name); 1367} 1368 1369static const xmlChar * 1370xmlSchemaGetQNameRefTargetNs(void *ref) 1371{ 1372 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace); 1373} 1374*/ 1375 1376static const xmlChar * 1377xmlSchemaGetComponentTargetNs(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 1417static const xmlChar* 1418xmlSchemaGetComponentQName(xmlChar **buf, 1419 void *item) 1420{ 1421 return (xmlSchemaFormatQName(buf, 1422 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item), 1423 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item))); 1424} 1425 1426static const xmlChar* 1427xmlSchemaGetComponentDesignation(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 1440static const xmlChar* 1441xmlSchemaGetIDCDesignation(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 */ 1453static const xmlChar * 1454xmlSchemaWildcardPCToString(int pc) 1455{ 1456 switch (pc) { 1457 case XML_SCHEMAS_ANY_SKIP: 1458 return (BAD_CAST "skip"); 1459 case XML_SCHEMAS_ANY_LAX: 1460 return (BAD_CAST "lax"); 1461 case XML_SCHEMAS_ANY_STRICT: 1462 return (BAD_CAST "strict"); 1463 default: 1464 return (BAD_CAST "invalid process contents"); 1465 } 1466} 1467 1468/** 1469 * xmlSchemaGetCanonValueWhtspExt: 1470 * @val: the precomputed value 1471 * @retValue: the returned value 1472 * @ws: the whitespace type of the value 1473 * 1474 * Get a the cononical representation of the value. 1475 * The caller has to free the returned retValue. 1476 * 1477 * Returns 0 if the value could be built and -1 in case of 1478 * API errors or if the value type is not supported yet. 1479 */ 1480static int 1481xmlSchemaGetCanonValueWhtspExt(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); 1535internal_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 */ 1569static xmlChar* 1570xmlSchemaFormatItemForReport(xmlChar **buf, 1571 const xmlChar *itemDes, 1572 xmlSchemaBasicItemPtr item, 1573 xmlNodePtr itemNode) 1574{ 1575 xmlChar *str = NULL; 1576 int named = 1; 1577 1578 if (*buf != NULL) { 1579 xmlFree(*buf); 1580 *buf = NULL; 1581 } 1582 1583 if (itemDes != NULL) { 1584 *buf = xmlStrdup(itemDes); 1585 } else if (item != NULL) { 1586 switch (item->type) { 1587 case XML_SCHEMA_TYPE_BASIC: { 1588 xmlSchemaTypePtr type = WXS_TYPE_CAST item; 1589 1590 if (WXS_IS_ATOMIC(type)) 1591 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:"); 1592 else if (WXS_IS_LIST(type)) 1593 *buf = xmlStrdup(BAD_CAST "list type 'xs:"); 1594 else if (WXS_IS_UNION(type)) 1595 *buf = xmlStrdup(BAD_CAST "union type 'xs:"); 1596 else 1597 *buf = xmlStrdup(BAD_CAST "simple type 'xs:"); 1598 *buf = xmlStrcat(*buf, type->name); 1599 *buf = xmlStrcat(*buf, BAD_CAST "'"); 1600 } 1601 break; 1602 case XML_SCHEMA_TYPE_SIMPLE: { 1603 xmlSchemaTypePtr type = WXS_TYPE_CAST item; 1604 1605 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) { 1606 *buf = xmlStrdup(BAD_CAST""); 1607 } else { 1608 *buf = xmlStrdup(BAD_CAST "local "); 1609 } 1610 if (WXS_IS_ATOMIC(type)) 1611 *buf = xmlStrcat(*buf, BAD_CAST "atomic type"); 1612 else if (WXS_IS_LIST(type)) 1613 *buf = xmlStrcat(*buf, BAD_CAST "list type"); 1614 else if (WXS_IS_UNION(type)) 1615 *buf = xmlStrcat(*buf, BAD_CAST "union type"); 1616 else 1617 *buf = xmlStrcat(*buf, BAD_CAST "simple type"); 1618 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) { 1619 *buf = xmlStrcat(*buf, BAD_CAST " '"); 1620 *buf = xmlStrcat(*buf, type->name); 1621 *buf = xmlStrcat(*buf, BAD_CAST "'"); 1622 } 1623 } 1624 break; 1625 case XML_SCHEMA_TYPE_COMPLEX: { 1626 xmlSchemaTypePtr type = WXS_TYPE_CAST item; 1627 1628 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) 1629 *buf = xmlStrdup(BAD_CAST ""); 1630 else 1631 *buf = xmlStrdup(BAD_CAST "local "); 1632 *buf = xmlStrcat(*buf, BAD_CAST "complex type"); 1633 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) { 1634 *buf = xmlStrcat(*buf, BAD_CAST " '"); 1635 *buf = xmlStrcat(*buf, type->name); 1636 *buf = xmlStrcat(*buf, BAD_CAST "'"); 1637 } 1638 } 1639 break; 1640 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: { 1641 xmlSchemaAttributeUsePtr ause; 1642 1643 ause = WXS_ATTR_USE_CAST item; 1644 *buf = xmlStrdup(BAD_CAST "attribute use "); 1645 if (WXS_ATTRUSE_DECL(ause) != NULL) { 1646 *buf = xmlStrcat(*buf, BAD_CAST "'"); 1647 *buf = xmlStrcat(*buf, 1648 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause))); 1649 FREE_AND_NULL(str) 1650 *buf = xmlStrcat(*buf, BAD_CAST "'"); 1651 } else { 1652 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)"); 1653 } 1654 } 1655 break; 1656 case XML_SCHEMA_TYPE_ATTRIBUTE: { 1657 xmlSchemaAttributePtr attr; 1658 1659 attr = (xmlSchemaAttributePtr) item; 1660 *buf = xmlStrdup(BAD_CAST "attribute decl."); 1661 *buf = xmlStrcat(*buf, BAD_CAST " '"); 1662 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str, 1663 attr->targetNamespace, attr->name)); 1664 FREE_AND_NULL(str) 1665 *buf = xmlStrcat(*buf, BAD_CAST "'"); 1666 } 1667 break; 1668 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: 1669 xmlSchemaGetComponentDesignation(buf, item); 1670 break; 1671 case XML_SCHEMA_TYPE_ELEMENT: { 1672 xmlSchemaElementPtr elem; 1673 1674 elem = (xmlSchemaElementPtr) item; 1675 *buf = xmlStrdup(BAD_CAST "element decl."); 1676 *buf = xmlStrcat(*buf, BAD_CAST " '"); 1677 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str, 1678 elem->targetNamespace, elem->name)); 1679 *buf = xmlStrcat(*buf, BAD_CAST "'"); 1680 } 1681 break; 1682 case XML_SCHEMA_TYPE_IDC_UNIQUE: 1683 case XML_SCHEMA_TYPE_IDC_KEY: 1684 case XML_SCHEMA_TYPE_IDC_KEYREF: 1685 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE) 1686 *buf = xmlStrdup(BAD_CAST "unique '"); 1687 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY) 1688 *buf = xmlStrdup(BAD_CAST "key '"); 1689 else 1690 *buf = xmlStrdup(BAD_CAST "keyRef '"); 1691 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name); 1692 *buf = xmlStrcat(*buf, BAD_CAST "'"); 1693 break; 1694 case XML_SCHEMA_TYPE_ANY: 1695 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: 1696 *buf = xmlStrdup(xmlSchemaWildcardPCToString( 1697 ((xmlSchemaWildcardPtr) item)->processContents)); 1698 *buf = xmlStrcat(*buf, BAD_CAST " wildcard"); 1699 break; 1700 case XML_SCHEMA_FACET_MININCLUSIVE: 1701 case XML_SCHEMA_FACET_MINEXCLUSIVE: 1702 case XML_SCHEMA_FACET_MAXINCLUSIVE: 1703 case XML_SCHEMA_FACET_MAXEXCLUSIVE: 1704 case XML_SCHEMA_FACET_TOTALDIGITS: 1705 case XML_SCHEMA_FACET_FRACTIONDIGITS: 1706 case XML_SCHEMA_FACET_PATTERN: 1707 case XML_SCHEMA_FACET_ENUMERATION: 1708 case XML_SCHEMA_FACET_WHITESPACE: 1709 case XML_SCHEMA_FACET_LENGTH: 1710 case XML_SCHEMA_FACET_MAXLENGTH: 1711 case XML_SCHEMA_FACET_MINLENGTH: 1712 *buf = xmlStrdup(BAD_CAST "facet '"); 1713 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type)); 1714 *buf = xmlStrcat(*buf, BAD_CAST "'"); 1715 break; 1716 case XML_SCHEMA_TYPE_GROUP: { 1717 *buf = xmlStrdup(BAD_CAST "model group def."); 1718 *buf = xmlStrcat(*buf, BAD_CAST " '"); 1719 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item)); 1720 *buf = xmlStrcat(*buf, BAD_CAST "'"); 1721 FREE_AND_NULL(str) 1722 } 1723 break; 1724 case XML_SCHEMA_TYPE_SEQUENCE: 1725 case XML_SCHEMA_TYPE_CHOICE: 1726 case XML_SCHEMA_TYPE_ALL: 1727 case XML_SCHEMA_TYPE_PARTICLE: 1728 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item)); 1729 break; 1730 case XML_SCHEMA_TYPE_NOTATION: { 1731 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item)); 1732 *buf = xmlStrcat(*buf, BAD_CAST " '"); 1733 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item)); 1734 *buf = xmlStrcat(*buf, BAD_CAST "'"); 1735 FREE_AND_NULL(str); 1736 } 1737 default: 1738 named = 0; 1739 } 1740 } else 1741 named = 0; 1742 1743 if ((named == 0) && (itemNode != NULL)) { 1744 xmlNodePtr elem; 1745 1746 if (itemNode->type == XML_ATTRIBUTE_NODE) 1747 elem = itemNode->parent; 1748 else 1749 elem = itemNode; 1750 *buf = xmlStrdup(BAD_CAST "Element '"); 1751 if (elem->ns != NULL) { 1752 *buf = xmlStrcat(*buf, 1753 xmlSchemaFormatQName(&str, elem->ns->href, elem->name)); 1754 FREE_AND_NULL(str) 1755 } else 1756 *buf = xmlStrcat(*buf, elem->name); 1757 *buf = xmlStrcat(*buf, BAD_CAST "'"); 1758 1759 } 1760 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) { 1761 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '"); 1762 if (itemNode->ns != NULL) { 1763 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str, 1764 itemNode->ns->href, itemNode->name)); 1765 FREE_AND_NULL(str) 1766 } else 1767 *buf = xmlStrcat(*buf, itemNode->name); 1768 *buf = xmlStrcat(*buf, BAD_CAST "'"); 1769 } 1770 FREE_AND_NULL(str) 1771 1772 return (*buf); 1773} 1774 1775/** 1776 * xmlSchemaFormatFacetEnumSet: 1777 * @buf: the string buffer 1778 * @type: the type holding the enumeration facets 1779 * 1780 * Builds a string consisting of all enumeration elements. 1781 * 1782 * Returns a string of all enumeration elements. 1783 */ 1784static const xmlChar * 1785xmlSchemaFormatFacetEnumSet(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 1849static void 1850xmlSchemaErrMemory(const char *msg) 1851{ 1852 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL, 1853 msg); 1854} 1855#endif 1856 1857static void 1858xmlSchemaPSimpleErr(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 */ 1871static void 1872xmlSchemaPErrMemory(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 */ 1892static void 1893xmlSchemaPErr(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 */ 1925static void 1926xmlSchemaPErr2(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 */ 1954static void 1955xmlSchemaPErrExt(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 */ 1993static void 1994xmlSchemaVErrMemory(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 2005static void 2006xmlSchemaPSimpleInternalErr(xmlNodePtr node, 2007 const char *msg, const xmlChar *str) 2008{ 2009 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node, 2010 msg, (const char *) str); 2011} 2012 2013#define WXS_ERROR_TYPE_ERROR 1 2014#define WXS_ERROR_TYPE_WARNING 2 2015/** 2016 * xmlSchemaErr3: 2017 * @ctxt: the validation context 2018 * @node: the context node 2019 * @error: the error code 2020 * @msg: the error message 2021 * @str1: extra data 2022 * @str2: extra data 2023 * @str3: extra data 2024 * 2025 * Handle a validation error 2026 */ 2027static void 2028xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt, 2029 xmlErrorLevel errorLevel, 2030 int error, xmlNodePtr node, int line, const char *msg, 2031 const xmlChar *str1, const xmlChar *str2, 2032 const xmlChar *str3, const xmlChar *str4) 2033{ 2034 xmlStructuredErrorFunc schannel = NULL; 2035 xmlGenericErrorFunc channel = NULL; 2036 void *data = NULL; 2037 2038 if (ctxt != NULL) { 2039 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) { 2040 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt; 2041 const char *file = NULL; 2042 if (errorLevel != XML_ERR_WARNING) { 2043 vctxt->nberrors++; 2044 vctxt->err = error; 2045 channel = vctxt->error; 2046 } else { 2047 channel = vctxt->warning; 2048 } 2049 schannel = vctxt->serror; 2050 data = vctxt->errCtxt; 2051 2052 /* 2053 * Error node. If we specify a line number, then 2054 * do not channel any node to the error function. 2055 */ 2056 if (line == 0) { 2057 if ((node == NULL) && 2058 (vctxt->depth >= 0) && 2059 (vctxt->inode != NULL)) { 2060 node = vctxt->inode->node; 2061 } 2062 /* 2063 * Get filename and line if no node-tree. 2064 */ 2065 if ((node == NULL) && 2066 (vctxt->parserCtxt != NULL) && 2067 (vctxt->parserCtxt->input != NULL)) { 2068 file = vctxt->parserCtxt->input->filename; 2069 line = vctxt->parserCtxt->input->line; 2070 } 2071 } else { 2072 /* 2073 * Override the given node's (if any) position 2074 * and channel only the given line number. 2075 */ 2076 node = NULL; 2077 /* 2078 * Get filename. 2079 */ 2080 if (vctxt->doc != NULL) 2081 file = (const char *) vctxt->doc->URL; 2082 else if ((vctxt->parserCtxt != NULL) && 2083 (vctxt->parserCtxt->input != NULL)) 2084 file = vctxt->parserCtxt->input->filename; 2085 } 2086 if (vctxt->locFunc != NULL) { 2087 if ((file == NULL) || (line == 0)) { 2088 unsigned long l; 2089 const char *f; 2090 vctxt->locFunc(vctxt->locCtxt, &f, &l); 2091 if (file == NULL) 2092 file = f; 2093 if (line == 0) 2094 line = (int) l; 2095 } 2096 } 2097 if ((file == NULL) && (vctxt->filename != NULL)) 2098 file = vctxt->filename; 2099 2100 __xmlRaiseError(schannel, channel, data, ctxt, 2101 node, XML_FROM_SCHEMASV, 2102 error, errorLevel, file, line, 2103 (const char *) str1, (const char *) str2, 2104 (const char *) str3, 0, 0, msg, str1, str2, str3, str4); 2105 2106 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) { 2107 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt; 2108 if (errorLevel != XML_ERR_WARNING) { 2109 pctxt->nberrors++; 2110 pctxt->err = error; 2111 channel = pctxt->error; 2112 } else { 2113 channel = pctxt->warning; 2114 } 2115 schannel = pctxt->serror; 2116 data = pctxt->errCtxt; 2117 __xmlRaiseError(schannel, channel, data, ctxt, 2118 node, XML_FROM_SCHEMASP, error, 2119 errorLevel, NULL, 0, 2120 (const char *) str1, (const char *) str2, 2121 (const char *) str3, 0, 0, msg, str1, str2, str3, str4); 2122 } else { 2123 TODO 2124 } 2125 } 2126} 2127 2128/** 2129 * xmlSchemaErr3: 2130 * @ctxt: the validation context 2131 * @node: the context node 2132 * @error: the error code 2133 * @msg: the error message 2134 * @str1: extra data 2135 * @str2: extra data 2136 * @str3: extra data 2137 * 2138 * Handle a validation error 2139 */ 2140static void 2141xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt, 2142 int error, xmlNodePtr node, const char *msg, 2143 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3) 2144{ 2145 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0, 2146 msg, str1, str2, str3, NULL); 2147} 2148 2149static void 2150xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt, 2151 int error, xmlNodePtr node, const char *msg, 2152 const xmlChar *str1, const xmlChar *str2, 2153 const xmlChar *str3, const xmlChar *str4) 2154{ 2155 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0, 2156 msg, str1, str2, str3, str4); 2157} 2158 2159static void 2160xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt, 2161 int error, xmlNodePtr node, const char *msg, 2162 const xmlChar *str1, const xmlChar *str2) 2163{ 2164 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL); 2165} 2166 2167static xmlChar * 2168xmlSchemaFormatNodeForError(xmlChar ** msg, 2169 xmlSchemaAbstractCtxtPtr actxt, 2170 xmlNodePtr node) 2171{ 2172 xmlChar *str = NULL; 2173 2174 *msg = NULL; 2175 if ((node != NULL) && 2176 (node->type != XML_ELEMENT_NODE) && 2177 (node->type != XML_ATTRIBUTE_NODE)) 2178 { 2179 /* 2180 * Don't try to format other nodes than element and 2181 * attribute nodes. 2182 * Play save and return an empty string. 2183 */ 2184 *msg = xmlStrdup(BAD_CAST ""); 2185 return(*msg); 2186 } 2187 if (node != NULL) { 2188 /* 2189 * Work on tree nodes. 2190 */ 2191 if (node->type == XML_ATTRIBUTE_NODE) { 2192 xmlNodePtr elem = node->parent; 2193 2194 *msg = xmlStrdup(BAD_CAST "Element '"); 2195 if (elem->ns != NULL) 2196 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, 2197 elem->ns->href, elem->name)); 2198 else 2199 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, 2200 NULL, elem->name)); 2201 FREE_AND_NULL(str); 2202 *msg = xmlStrcat(*msg, BAD_CAST "', "); 2203 *msg = xmlStrcat(*msg, BAD_CAST "attribute '"); 2204 } else { 2205 *msg = xmlStrdup(BAD_CAST "Element '"); 2206 } 2207 if (node->ns != NULL) 2208 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, 2209 node->ns->href, node->name)); 2210 else 2211 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, 2212 NULL, node->name)); 2213 FREE_AND_NULL(str); 2214 *msg = xmlStrcat(*msg, BAD_CAST "': "); 2215 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) { 2216 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt; 2217 /* 2218 * Work on node infos. 2219 */ 2220 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) { 2221 xmlSchemaNodeInfoPtr ielem = 2222 vctxt->elemInfos[vctxt->depth]; 2223 2224 *msg = xmlStrdup(BAD_CAST "Element '"); 2225 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, 2226 ielem->nsName, ielem->localName)); 2227 FREE_AND_NULL(str); 2228 *msg = xmlStrcat(*msg, BAD_CAST "', "); 2229 *msg = xmlStrcat(*msg, BAD_CAST "attribute '"); 2230 } else { 2231 *msg = xmlStrdup(BAD_CAST "Element '"); 2232 } 2233 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, 2234 vctxt->inode->nsName, vctxt->inode->localName)); 2235 FREE_AND_NULL(str); 2236 *msg = xmlStrcat(*msg, BAD_CAST "': "); 2237 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) { 2238 /* 2239 * Hmm, no node while parsing? 2240 * Return an empty string, in case NULL will break something. 2241 */ 2242 *msg = xmlStrdup(BAD_CAST ""); 2243 } else { 2244 TODO 2245 return (NULL); 2246 } 2247 /* 2248 * VAL TODO: The output of the given schema component is currently 2249 * disabled. 2250 */ 2251#if 0 2252 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) { 2253 *msg = xmlStrcat(*msg, BAD_CAST " ["); 2254 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str, 2255 NULL, type, NULL, 0)); 2256 FREE_AND_NULL(str) 2257 *msg = xmlStrcat(*msg, BAD_CAST "]"); 2258 } 2259#endif 2260 return (*msg); 2261} 2262 2263static void 2264xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt, 2265 const char *funcName, 2266 const char *message, 2267 const xmlChar *str1, 2268 const xmlChar *str2) 2269{ 2270 xmlChar *msg = NULL; 2271 2272 if (actxt == NULL) 2273 return; 2274 msg = xmlStrdup(BAD_CAST "Internal error: "); 2275 msg = xmlStrcat(msg, BAD_CAST funcName); 2276 msg = xmlStrcat(msg, BAD_CAST ", "); 2277 msg = xmlStrcat(msg, BAD_CAST message); 2278 msg = xmlStrcat(msg, BAD_CAST ".\n"); 2279 2280 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) 2281 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL, 2282 (const char *) msg, str1, str2); 2283 2284 else if (actxt->type == XML_SCHEMA_CTXT_PARSER) 2285 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL, 2286 (const char *) msg, str1, str2); 2287 2288 FREE_AND_NULL(msg) 2289} 2290 2291static void 2292xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt, 2293 const char *funcName, 2294 const char *message) 2295{ 2296 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL); 2297} 2298 2299#if 0 2300static void 2301xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt, 2302 const char *funcName, 2303 const char *message, 2304 const xmlChar *str1, 2305 const xmlChar *str2) 2306{ 2307 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message, 2308 str1, str2); 2309} 2310#endif 2311 2312static void 2313xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt, 2314 xmlParserErrors error, 2315 xmlNodePtr node, 2316 xmlSchemaBasicItemPtr item, 2317 const char *message, 2318 const xmlChar *str1, const xmlChar *str2, 2319 const xmlChar *str3, const xmlChar *str4) 2320{ 2321 xmlChar *msg = NULL; 2322 2323 if ((node == NULL) && (item != NULL) && 2324 (actxt->type == XML_SCHEMA_CTXT_PARSER)) { 2325 node = WXS_ITEM_NODE(item); 2326 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL); 2327 msg = xmlStrcat(msg, BAD_CAST ": "); 2328 } else 2329 xmlSchemaFormatNodeForError(&msg, actxt, node); 2330 msg = xmlStrcat(msg, (const xmlChar *) message); 2331 msg = xmlStrcat(msg, BAD_CAST ".\n"); 2332 xmlSchemaErr4(actxt, error, node, 2333 (const char *) msg, str1, str2, str3, str4); 2334 FREE_AND_NULL(msg) 2335} 2336 2337static void 2338xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt, 2339 xmlParserErrors error, 2340 xmlNodePtr node, 2341 xmlSchemaBasicItemPtr item, 2342 const char *message, 2343 const xmlChar *str1, 2344 const xmlChar *str2) 2345{ 2346 xmlSchemaCustomErr4(actxt, error, node, item, 2347 message, str1, str2, NULL, NULL); 2348} 2349 2350 2351 2352static void 2353xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt, 2354 xmlParserErrors error, 2355 xmlNodePtr node, 2356 xmlSchemaTypePtr type ATTRIBUTE_UNUSED, 2357 const char *message, 2358 const xmlChar *str1, 2359 const xmlChar *str2, 2360 const xmlChar *str3) 2361{ 2362 xmlChar *msg = NULL; 2363 2364 xmlSchemaFormatNodeForError(&msg, actxt, node); 2365 msg = xmlStrcat(msg, (const xmlChar *) message); 2366 msg = xmlStrcat(msg, BAD_CAST ".\n"); 2367 2368 /* URGENT TODO: Set the error code to something sane. */ 2369 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0, 2370 (const char *) msg, str1, str2, str3, NULL); 2371 2372 FREE_AND_NULL(msg) 2373} 2374 2375 2376 2377static void 2378xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt, 2379 xmlParserErrors error, 2380 xmlSchemaPSVIIDCNodePtr idcNode, 2381 xmlSchemaTypePtr type ATTRIBUTE_UNUSED, 2382 const char *message, 2383 const xmlChar *str1, 2384 const xmlChar *str2) 2385{ 2386 xmlChar *msg = NULL, *qname = NULL; 2387 2388 msg = xmlStrdup(BAD_CAST "Element '%s': "); 2389 msg = xmlStrcat(msg, (const xmlChar *) message); 2390 msg = xmlStrcat(msg, BAD_CAST ".\n"); 2391 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR, 2392 error, NULL, idcNode->nodeLine, (const char *) msg, 2393 xmlSchemaFormatQName(&qname, 2394 vctxt->nodeQNames->items[idcNode->nodeQNameID +1], 2395 vctxt->nodeQNames->items[idcNode->nodeQNameID]), 2396 str1, str2, NULL); 2397 FREE_AND_NULL(qname); 2398 FREE_AND_NULL(msg); 2399} 2400 2401static int 2402xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt, 2403 xmlNodePtr node) 2404{ 2405 if (node != NULL) 2406 return (node->type); 2407 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) && 2408 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL)) 2409 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType); 2410 return (-1); 2411} 2412 2413static int 2414xmlSchemaIsGlobalItem(xmlSchemaTypePtr item) 2415{ 2416 switch (item->type) { 2417 case XML_SCHEMA_TYPE_COMPLEX: 2418 case XML_SCHEMA_TYPE_SIMPLE: 2419 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) 2420 return(1); 2421 break; 2422 case XML_SCHEMA_TYPE_GROUP: 2423 return (1); 2424 case XML_SCHEMA_TYPE_ELEMENT: 2425 if ( ((xmlSchemaElementPtr) item)->flags & 2426 XML_SCHEMAS_ELEM_GLOBAL) 2427 return(1); 2428 break; 2429 case XML_SCHEMA_TYPE_ATTRIBUTE: 2430 if ( ((xmlSchemaAttributePtr) item)->flags & 2431 XML_SCHEMAS_ATTR_GLOBAL) 2432 return(1); 2433 break; 2434 /* Note that attribute groups are always global. */ 2435 default: 2436 return(1); 2437 } 2438 return (0); 2439} 2440 2441static void 2442xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt, 2443 xmlParserErrors error, 2444 xmlNodePtr node, 2445 const xmlChar *value, 2446 xmlSchemaTypePtr type, 2447 int displayValue) 2448{ 2449 xmlChar *msg = NULL; 2450 2451 xmlSchemaFormatNodeForError(&msg, actxt, node); 2452 2453 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) == 2454 XML_ATTRIBUTE_NODE)) 2455 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of "); 2456 else 2457 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid " 2458 "value of "); 2459 2460 if (! xmlSchemaIsGlobalItem(type)) 2461 msg = xmlStrcat(msg, BAD_CAST "the local "); 2462 else 2463 msg = xmlStrcat(msg, BAD_CAST "the "); 2464 2465 if (WXS_IS_ATOMIC(type)) 2466 msg = xmlStrcat(msg, BAD_CAST "atomic type"); 2467 else if (WXS_IS_LIST(type)) 2468 msg = xmlStrcat(msg, BAD_CAST "list type"); 2469 else if (WXS_IS_UNION(type)) 2470 msg = xmlStrcat(msg, BAD_CAST "union type"); 2471 2472 if (xmlSchemaIsGlobalItem(type)) { 2473 xmlChar *str = NULL; 2474 msg = xmlStrcat(msg, BAD_CAST " '"); 2475 if (type->builtInType != 0) { 2476 msg = xmlStrcat(msg, BAD_CAST "xs:"); 2477 msg = xmlStrcat(msg, type->name); 2478 } else 2479 msg = xmlStrcat(msg, 2480 xmlSchemaFormatQName(&str, 2481 type->targetNamespace, type->name)); 2482 msg = xmlStrcat(msg, BAD_CAST "'"); 2483 FREE_AND_NULL(str); 2484 } 2485 msg = xmlStrcat(msg, BAD_CAST ".\n"); 2486 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) == 2487 XML_ATTRIBUTE_NODE)) 2488 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL); 2489 else 2490 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL); 2491 FREE_AND_NULL(msg) 2492} 2493 2494static const xmlChar * 2495xmlSchemaFormatErrorNodeQName(xmlChar ** str, 2496 xmlSchemaNodeInfoPtr ni, 2497 xmlNodePtr node) 2498{ 2499 if (node != NULL) { 2500 if (node->ns != NULL) 2501 return (xmlSchemaFormatQName(str, node->ns->href, node->name)); 2502 else 2503 return (xmlSchemaFormatQName(str, NULL, node->name)); 2504 } else if (ni != NULL) 2505 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName)); 2506 return (NULL); 2507} 2508 2509static void 2510xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt, 2511 xmlParserErrors error, 2512 xmlSchemaAttrInfoPtr ni, 2513 xmlNodePtr node) 2514{ 2515 xmlChar *msg = NULL, *str = NULL; 2516 2517 xmlSchemaFormatNodeForError(&msg, actxt, node); 2518 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n"); 2519 xmlSchemaErr(actxt, error, node, (const char *) msg, 2520 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node), 2521 NULL); 2522 FREE_AND_NULL(str) 2523 FREE_AND_NULL(msg) 2524} 2525 2526static void 2527xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt, 2528 xmlParserErrors error, 2529 xmlNodePtr node, 2530 xmlSchemaTypePtr type ATTRIBUTE_UNUSED, 2531 const char *message, 2532 int nbval, 2533 int nbneg, 2534 xmlChar **values) 2535{ 2536 xmlChar *str = NULL, *msg = NULL; 2537 xmlChar *localName, *nsName; 2538 const xmlChar *cur, *end; 2539 int i; 2540 2541 xmlSchemaFormatNodeForError(&msg, actxt, node); 2542 msg = xmlStrcat(msg, (const xmlChar *) message); 2543 msg = xmlStrcat(msg, BAD_CAST "."); 2544 /* 2545 * Note that is does not make sense to report that we have a 2546 * wildcard here, since the wildcard might be unfolded into 2547 * multiple transitions. 2548 */ 2549 if (nbval + nbneg > 0) { 2550 if (nbval + nbneg > 1) { 2551 str = xmlStrdup(BAD_CAST " Expected is one of ( "); 2552 } else 2553 str = xmlStrdup(BAD_CAST " Expected is ( "); 2554 nsName = NULL; 2555 2556 for (i = 0; i < nbval + nbneg; i++) { 2557 cur = values[i]; 2558 if (cur == NULL) 2559 continue; 2560 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') && 2561 (cur[3] == ' ')) { 2562 cur += 4; 2563 str = xmlStrcat(str, BAD_CAST "##other"); 2564 } 2565 /* 2566 * Get the local name. 2567 */ 2568 localName = NULL; 2569 2570 end = cur; 2571 if (*end == '*') { 2572 localName = xmlStrdup(BAD_CAST "*"); 2573 end++; 2574 } else { 2575 while ((*end != 0) && (*end != '|')) 2576 end++; 2577 localName = xmlStrncat(localName, BAD_CAST cur, end - cur); 2578 } 2579 if (*end != 0) { 2580 end++; 2581 /* 2582 * Skip "*|*" if they come with negated expressions, since 2583 * they represent the same negated wildcard. 2584 */ 2585 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) { 2586 /* 2587 * Get the namespace name. 2588 */ 2589 cur = end; 2590 if (*end == '*') { 2591 nsName = xmlStrdup(BAD_CAST "{*}"); 2592 } else { 2593 while (*end != 0) 2594 end++; 2595 2596 if (i >= nbval) 2597 nsName = xmlStrdup(BAD_CAST "{##other:"); 2598 else 2599 nsName = xmlStrdup(BAD_CAST "{"); 2600 2601 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur); 2602 nsName = xmlStrcat(nsName, BAD_CAST "}"); 2603 } 2604 str = xmlStrcat(str, BAD_CAST nsName); 2605 FREE_AND_NULL(nsName) 2606 } else { 2607 FREE_AND_NULL(localName); 2608 continue; 2609 } 2610 } 2611 str = xmlStrcat(str, BAD_CAST localName); 2612 FREE_AND_NULL(localName); 2613 2614 if (i < nbval + nbneg -1) 2615 str = xmlStrcat(str, BAD_CAST ", "); 2616 } 2617 str = xmlStrcat(str, BAD_CAST " ).\n"); 2618 msg = xmlStrcat(msg, BAD_CAST str); 2619 FREE_AND_NULL(str) 2620 } else 2621 msg = xmlStrcat(msg, BAD_CAST "\n"); 2622 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL); 2623 xmlFree(msg); 2624} 2625 2626static void 2627xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt, 2628 xmlParserErrors error, 2629 xmlNodePtr node, 2630 const xmlChar *value, 2631 unsigned long length, 2632 xmlSchemaTypePtr type, 2633 xmlSchemaFacetPtr facet, 2634 const char *message, 2635 const xmlChar *str1, 2636 const xmlChar *str2) 2637{ 2638 xmlChar *str = NULL, *msg = NULL; 2639 xmlSchemaTypeType facetType; 2640 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node); 2641 2642 xmlSchemaFormatNodeForError(&msg, actxt, node); 2643 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) { 2644 facetType = XML_SCHEMA_FACET_ENUMERATION; 2645 /* 2646 * If enumerations are validated, one must not expect the 2647 * facet to be given. 2648 */ 2649 } else 2650 facetType = facet->type; 2651 msg = xmlStrcat(msg, BAD_CAST "["); 2652 msg = xmlStrcat(msg, BAD_CAST "facet '"); 2653 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType)); 2654 msg = xmlStrcat(msg, BAD_CAST "'] "); 2655 if (message == NULL) { 2656 /* 2657 * Use a default message. 2658 */ 2659 if ((facetType == XML_SCHEMA_FACET_LENGTH) || 2660 (facetType == XML_SCHEMA_FACET_MINLENGTH) || 2661 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) { 2662 2663 char len[25], actLen[25]; 2664 2665 /* FIXME, TODO: What is the max expected string length of the 2666 * this value? 2667 */ 2668 if (nodeType == XML_ATTRIBUTE_NODE) 2669 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; "); 2670 else 2671 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; "); 2672 2673 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet)); 2674 snprintf(actLen, 24, "%lu", length); 2675 2676 if (facetType == XML_SCHEMA_FACET_LENGTH) 2677 msg = xmlStrcat(msg, 2678 BAD_CAST "this differs from the allowed length of '%s'.\n"); 2679 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH) 2680 msg = xmlStrcat(msg, 2681 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n"); 2682 else if (facetType == XML_SCHEMA_FACET_MINLENGTH) 2683 msg = xmlStrcat(msg, 2684 BAD_CAST "this underruns the allowed minimum length of '%s'.\n"); 2685 2686 if (nodeType == XML_ATTRIBUTE_NODE) 2687 xmlSchemaErr3(actxt, error, node, (const char *) msg, 2688 value, (const xmlChar *) actLen, (const xmlChar *) len); 2689 else 2690 xmlSchemaErr(actxt, error, node, (const char *) msg, 2691 (const xmlChar *) actLen, (const xmlChar *) len); 2692 2693 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) { 2694 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element " 2695 "of the set {%s}.\n"); 2696 xmlSchemaErr(actxt, error, node, (const char *) msg, value, 2697 xmlSchemaFormatFacetEnumSet(actxt, &str, type)); 2698 } else if (facetType == XML_SCHEMA_FACET_PATTERN) { 2699 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted " 2700 "by the pattern '%s'.\n"); 2701 xmlSchemaErr(actxt, error, node, (const char *) msg, value, 2702 facet->value); 2703 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) { 2704 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the " 2705 "minimum value allowed ('%s').\n"); 2706 xmlSchemaErr(actxt, error, node, (const char *) msg, value, 2707 facet->value); 2708 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) { 2709 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the " 2710 "maximum value allowed ('%s').\n"); 2711 xmlSchemaErr(actxt, error, node, (const char *) msg, value, 2712 facet->value); 2713 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) { 2714 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than " 2715 "'%s'.\n"); 2716 xmlSchemaErr(actxt, error, node, (const char *) msg, value, 2717 facet->value); 2718 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) { 2719 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than " 2720 "'%s'.\n"); 2721 xmlSchemaErr(actxt, error, node, (const char *) msg, value, 2722 facet->value); 2723 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) { 2724 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more " 2725 "digits than are allowed ('%s').\n"); 2726 xmlSchemaErr(actxt, error, node, (const char*) msg, value, 2727 facet->value); 2728 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) { 2729 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional " 2730 "digits than are allowed ('%s').\n"); 2731 xmlSchemaErr(actxt, error, node, (const char*) msg, value, 2732 facet->value); 2733 } else if (nodeType == XML_ATTRIBUTE_NODE) { 2734 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n"); 2735 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL); 2736 } else { 2737 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n"); 2738 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL); 2739 } 2740 } else { 2741 msg = xmlStrcat(msg, (const xmlChar *) message); 2742 msg = xmlStrcat(msg, BAD_CAST ".\n"); 2743 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2); 2744 } 2745 FREE_AND_NULL(str) 2746 xmlFree(msg); 2747} 2748 2749#define VERROR(err, type, msg) \ 2750 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL); 2751 2752#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg); 2753 2754#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg); 2755#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg); 2756 2757#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg); 2758 2759 2760/** 2761 * xmlSchemaPMissingAttrErr: 2762 * @ctxt: the schema validation context 2763 * @ownerDes: the designation of the owner 2764 * @ownerName: the name of the owner 2765 * @ownerItem: the owner as a schema object 2766 * @ownerElem: the owner as an element node 2767 * @node: the parent element node of the missing attribute node 2768 * @type: the corresponding type of the attribute node 2769 * 2770 * Reports an illegal attribute. 2771 */ 2772static void 2773xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt, 2774 xmlParserErrors error, 2775 xmlSchemaBasicItemPtr ownerItem, 2776 xmlNodePtr ownerElem, 2777 const char *name, 2778 const char *message) 2779{ 2780 xmlChar *des = NULL; 2781 2782 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem); 2783 2784 if (message != NULL) 2785 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message); 2786 else 2787 xmlSchemaPErr(ctxt, ownerElem, error, 2788 "%s: The attribute '%s' is required but missing.\n", 2789 BAD_CAST des, BAD_CAST name); 2790 FREE_AND_NULL(des); 2791} 2792 2793 2794/** 2795 * xmlSchemaPResCompAttrErr: 2796 * @ctxt: the schema validation context 2797 * @error: the error code 2798 * @ownerDes: the designation of the owner 2799 * @ownerItem: the owner as a schema object 2800 * @ownerElem: the owner as an element node 2801 * @name: the name of the attribute holding the QName 2802 * @refName: the referenced local name 2803 * @refURI: the referenced namespace URI 2804 * @message: optional message 2805 * 2806 * Used to report QName attribute values that failed to resolve 2807 * to schema components. 2808 */ 2809static void 2810xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt, 2811 xmlParserErrors error, 2812 xmlSchemaBasicItemPtr ownerItem, 2813 xmlNodePtr ownerElem, 2814 const char *name, 2815 const xmlChar *refName, 2816 const xmlChar *refURI, 2817 xmlSchemaTypeType refType, 2818 const char *refTypeStr) 2819{ 2820 xmlChar *des = NULL, *strA = NULL; 2821 2822 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem); 2823 if (refTypeStr == NULL) 2824 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType); 2825 xmlSchemaPErrExt(ctxt, ownerElem, error, 2826 NULL, NULL, NULL, 2827 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) " 2828 "%s.\n", BAD_CAST des, BAD_CAST name, 2829 xmlSchemaFormatQName(&strA, refURI, refName), 2830 BAD_CAST refTypeStr, NULL); 2831 FREE_AND_NULL(des) 2832 FREE_AND_NULL(strA) 2833} 2834 2835/** 2836 * xmlSchemaPCustomAttrErr: 2837 * @ctxt: the schema parser context 2838 * @error: the error code 2839 * @ownerDes: the designation of the owner 2840 * @ownerItem: the owner as a schema object 2841 * @attr: the illegal attribute node 2842 * 2843 * Reports an illegal attribute during the parse. 2844 */ 2845static void 2846xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt, 2847 xmlParserErrors error, 2848 xmlChar **ownerDes, 2849 xmlSchemaBasicItemPtr ownerItem, 2850 xmlAttrPtr attr, 2851 const char *msg) 2852{ 2853 xmlChar *des = NULL; 2854 2855 if (ownerDes == NULL) 2856 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent); 2857 else if (*ownerDes == NULL) { 2858 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent); 2859 des = *ownerDes; 2860 } else 2861 des = *ownerDes; 2862 if (attr == NULL) { 2863 xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL, 2864 "%s, attribute '%s': %s.\n", 2865 BAD_CAST des, (const xmlChar *) "Unknown", 2866 (const xmlChar *) msg, NULL, NULL); 2867 } else { 2868 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL, 2869 "%s, attribute '%s': %s.\n", 2870 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL); 2871 } 2872 if (ownerDes == NULL) 2873 FREE_AND_NULL(des); 2874} 2875 2876/** 2877 * xmlSchemaPIllegalAttrErr: 2878 * @ctxt: the schema parser context 2879 * @error: the error code 2880 * @ownerDes: the designation of the attribute's owner 2881 * @ownerItem: the attribute's owner item 2882 * @attr: the illegal attribute node 2883 * 2884 * Reports an illegal attribute during the parse. 2885 */ 2886static void 2887xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt, 2888 xmlParserErrors error, 2889 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED, 2890 xmlAttrPtr attr) 2891{ 2892 xmlChar *strA = NULL, *strB = NULL; 2893 2894 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent); 2895 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr, 2896 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA, 2897 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name), 2898 NULL, NULL); 2899 FREE_AND_NULL(strA); 2900 FREE_AND_NULL(strB); 2901} 2902 2903/** 2904 * xmlSchemaPCustomErr: 2905 * @ctxt: the schema parser context 2906 * @error: the error code 2907 * @itemDes: the designation of the schema item 2908 * @item: the schema item 2909 * @itemElem: the node of the schema item 2910 * @message: the error message 2911 * @str1: an optional param for the error message 2912 * @str2: an optional param for the error message 2913 * @str3: an optional param for the error message 2914 * 2915 * Reports an error during parsing. 2916 */ 2917static void 2918xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt, 2919 xmlParserErrors error, 2920 xmlSchemaBasicItemPtr item, 2921 xmlNodePtr itemElem, 2922 const char *message, 2923 const xmlChar *str1, 2924 const xmlChar *str2, 2925 const xmlChar *str3) 2926{ 2927 xmlChar *des = NULL, *msg = NULL; 2928 2929 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem); 2930 msg = xmlStrdup(BAD_CAST "%s: "); 2931 msg = xmlStrcat(msg, (const xmlChar *) message); 2932 msg = xmlStrcat(msg, BAD_CAST ".\n"); 2933 if ((itemElem == NULL) && (item != NULL)) 2934 itemElem = WXS_ITEM_NODE(item); 2935 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL, 2936 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL); 2937 FREE_AND_NULL(des); 2938 FREE_AND_NULL(msg); 2939} 2940 2941/** 2942 * xmlSchemaPCustomErr: 2943 * @ctxt: the schema parser context 2944 * @error: the error code 2945 * @itemDes: the designation of the schema item 2946 * @item: the schema item 2947 * @itemElem: the node of the schema item 2948 * @message: the error message 2949 * @str1: the optional param for the error message 2950 * 2951 * Reports an error during parsing. 2952 */ 2953static void 2954xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt, 2955 xmlParserErrors error, 2956 xmlSchemaBasicItemPtr item, 2957 xmlNodePtr itemElem, 2958 const char *message, 2959 const xmlChar *str1) 2960{ 2961 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message, 2962 str1, NULL, NULL); 2963} 2964 2965/** 2966 * xmlSchemaPAttrUseErr: 2967 * @ctxt: the schema parser context 2968 * @error: the error code 2969 * @itemDes: the designation of the schema type 2970 * @item: the schema type 2971 * @itemElem: the node of the schema type 2972 * @attr: the invalid schema attribute 2973 * @message: the error message 2974 * @str1: the optional param for the error message 2975 * 2976 * Reports an attribute use error during parsing. 2977 */ 2978static void 2979xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt, 2980 xmlParserErrors error, 2981 xmlNodePtr node, 2982 xmlSchemaBasicItemPtr ownerItem, 2983 const xmlSchemaAttributeUsePtr attruse, 2984 const char *message, 2985 const xmlChar *str1, const xmlChar *str2, 2986 const xmlChar *str3,const xmlChar *str4) 2987{ 2988 xmlChar *str = NULL, *msg = NULL; 2989 2990 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL); 2991 msg = xmlStrcat(msg, BAD_CAST ", "); 2992 msg = xmlStrcat(msg, 2993 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL, 2994 WXS_BASIC_CAST attruse, NULL)); 2995 FREE_AND_NULL(str); 2996 msg = xmlStrcat(msg, BAD_CAST ": "); 2997 msg = xmlStrcat(msg, (const xmlChar *) message); 2998 msg = xmlStrcat(msg, BAD_CAST ".\n"); 2999 xmlSchemaErr4(ACTXT_CAST ctxt, error, node, 3000 (const char *) msg, str1, str2, str3, str4); 3001 xmlFree(msg); 3002} 3003 3004/** 3005 * xmlSchemaPIllegalFacetAtomicErr: 3006 * @ctxt: the schema parser context 3007 * @error: the error code 3008 * @type: the schema type 3009 * @baseType: the base type of type 3010 * @facet: the illegal facet 3011 * 3012 * Reports an illegal facet for atomic simple types. 3013 */ 3014static void 3015xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt, 3016 xmlParserErrors error, 3017 xmlSchemaTypePtr type, 3018 xmlSchemaTypePtr baseType, 3019 xmlSchemaFacetPtr facet) 3020{ 3021 xmlChar *des = NULL, *strT = NULL; 3022 3023 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node); 3024 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL, 3025 "%s: The facet '%s' is not allowed on types derived from the " 3026 "type %s.\n", 3027 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type), 3028 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL), 3029 NULL, NULL); 3030 FREE_AND_NULL(des); 3031 FREE_AND_NULL(strT); 3032} 3033 3034/** 3035 * xmlSchemaPIllegalFacetListUnionErr: 3036 * @ctxt: the schema parser context 3037 * @error: the error code 3038 * @itemDes: the designation of the schema item involved 3039 * @item: the schema item involved 3040 * @facet: the illegal facet 3041 * 3042 * Reports an illegal facet for <list> and <union>. 3043 */ 3044static void 3045xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt, 3046 xmlParserErrors error, 3047 xmlSchemaTypePtr type, 3048 xmlSchemaFacetPtr facet) 3049{ 3050 xmlChar *des = NULL; 3051 3052 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, 3053 type->node); 3054 xmlSchemaPErr(ctxt, type->node, error, 3055 "%s: The facet '%s' is not allowed.\n", 3056 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type)); 3057 FREE_AND_NULL(des); 3058} 3059 3060/** 3061 * xmlSchemaPMutualExclAttrErr: 3062 * @ctxt: the schema validation context 3063 * @error: the error code 3064 * @elemDes: the designation of the parent element node 3065 * @attr: the bad attribute node 3066 * @type: the corresponding type of the attribute node 3067 * 3068 * Reports an illegal attribute. 3069 */ 3070static void 3071xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt, 3072 xmlParserErrors error, 3073 xmlSchemaBasicItemPtr ownerItem, 3074 xmlAttrPtr attr, 3075 const char *name1, 3076 const char *name2) 3077{ 3078 xmlChar *des = NULL; 3079 3080 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent); 3081 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL, 3082 "%s: The attributes '%s' and '%s' are mutually exclusive.\n", 3083 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL); 3084 FREE_AND_NULL(des); 3085} 3086 3087/** 3088 * xmlSchemaPSimpleTypeErr: 3089 * @ctxt: the schema validation context 3090 * @error: the error code 3091 * @type: the type specifier 3092 * @ownerDes: the designation of the owner 3093 * @ownerItem: the schema object if existent 3094 * @node: the validated node 3095 * @value: the validated value 3096 * 3097 * Reports a simple type validation error. 3098 * TODO: Should this report the value of an element as well? 3099 */ 3100static void 3101xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt, 3102 xmlParserErrors error, 3103 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED, 3104 xmlNodePtr node, 3105 xmlSchemaTypePtr type, 3106 const char *expected, 3107 const xmlChar *value, 3108 const char *message, 3109 const xmlChar *str1, 3110 const xmlChar *str2) 3111{ 3112 xmlChar *msg = NULL; 3113 3114 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node); 3115 if (message == NULL) { 3116 /* 3117 * Use default messages. 3118 */ 3119 if (type != NULL) { 3120 if (node->type == XML_ATTRIBUTE_NODE) 3121 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of "); 3122 else 3123 msg = xmlStrcat(msg, BAD_CAST "The character content is not a " 3124 "valid value of "); 3125 if (! xmlSchemaIsGlobalItem(type)) 3126 msg = xmlStrcat(msg, BAD_CAST "the local "); 3127 else 3128 msg = xmlStrcat(msg, BAD_CAST "the "); 3129 3130 if (WXS_IS_ATOMIC(type)) 3131 msg = xmlStrcat(msg, BAD_CAST "atomic type"); 3132 else if (WXS_IS_LIST(type)) 3133 msg = xmlStrcat(msg, BAD_CAST "list type"); 3134 else if (WXS_IS_UNION(type)) 3135 msg = xmlStrcat(msg, BAD_CAST "union type"); 3136 3137 if (xmlSchemaIsGlobalItem(type)) { 3138 xmlChar *str = NULL; 3139 msg = xmlStrcat(msg, BAD_CAST " '"); 3140 if (type->builtInType != 0) { 3141 msg = xmlStrcat(msg, BAD_CAST "xs:"); 3142 msg = xmlStrcat(msg, type->name); 3143 } else 3144 msg = xmlStrcat(msg, 3145 xmlSchemaFormatQName(&str, 3146 type->targetNamespace, type->name)); 3147 msg = xmlStrcat(msg, BAD_CAST "'."); 3148 FREE_AND_NULL(str); 3149 } 3150 } else { 3151 if (node->type == XML_ATTRIBUTE_NODE) 3152 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid."); 3153 else 3154 msg = xmlStrcat(msg, BAD_CAST "The character content is not " 3155 "valid."); 3156 } 3157 if (expected) { 3158 msg = xmlStrcat(msg, BAD_CAST " Expected is '"); 3159 msg = xmlStrcat(msg, BAD_CAST expected); 3160 msg = xmlStrcat(msg, BAD_CAST "'.\n"); 3161 } else 3162 msg = xmlStrcat(msg, BAD_CAST "\n"); 3163 if (node->type == XML_ATTRIBUTE_NODE) 3164 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL); 3165 else 3166 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL); 3167 } else { 3168 msg = xmlStrcat(msg, BAD_CAST message); 3169 msg = xmlStrcat(msg, BAD_CAST ".\n"); 3170 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL, 3171 (const char*) msg, str1, str2, NULL, NULL, NULL); 3172 } 3173 /* Cleanup. */ 3174 FREE_AND_NULL(msg) 3175} 3176 3177/** 3178 * xmlSchemaPContentErr: 3179 * @ctxt: the schema parser context 3180 * @error: the error code 3181 * @onwerDes: the designation of the holder of the content 3182 * @ownerItem: the owner item of the holder of the content 3183 * @ownerElem: the node of the holder of the content 3184 * @child: the invalid child node 3185 * @message: the optional error message 3186 * @content: the optional string describing the correct content 3187 * 3188 * Reports an error concerning the content of a schema element. 3189 */ 3190static void 3191xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt, 3192 xmlParserErrors error, 3193 xmlSchemaBasicItemPtr ownerItem, 3194 xmlNodePtr ownerElem, 3195 xmlNodePtr child, 3196 const char *message, 3197 const char *content) 3198{ 3199 xmlChar *des = NULL; 3200 3201 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem); 3202 if (message != NULL) 3203 xmlSchemaPErr2(ctxt, ownerElem, child, error, 3204 "%s: %s.\n", 3205 BAD_CAST des, BAD_CAST message); 3206 else { 3207 if (content != NULL) { 3208 xmlSchemaPErr2(ctxt, ownerElem, child, error, 3209 "%s: The content is not valid. Expected is %s.\n", 3210 BAD_CAST des, BAD_CAST content); 3211 } else { 3212 xmlSchemaPErr2(ctxt, ownerElem, child, error, 3213 "%s: The content is not valid.\n", 3214 BAD_CAST des, NULL); 3215 } 3216 } 3217 FREE_AND_NULL(des) 3218} 3219 3220/************************************************************************ 3221 * * 3222 * Streamable error functions * 3223 * * 3224 ************************************************************************/ 3225 3226 3227 3228 3229/************************************************************************ 3230 * * 3231 * Validation helper functions * 3232 * * 3233 ************************************************************************/ 3234 3235 3236/************************************************************************ 3237 * * 3238 * Allocation functions * 3239 * * 3240 ************************************************************************/ 3241 3242/** 3243 * xmlSchemaNewSchemaForParserCtxt: 3244 * @ctxt: a schema validation context 3245 * 3246 * Allocate a new Schema structure. 3247 * 3248 * Returns the newly allocated structure or NULL in case or error 3249 */ 3250static xmlSchemaPtr 3251xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt) 3252{ 3253 xmlSchemaPtr ret; 3254 3255 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema)); 3256 if (ret == NULL) { 3257 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL); 3258 return (NULL); 3259 } 3260 memset(ret, 0, sizeof(xmlSchema)); 3261 ret->dict = ctxt->dict; 3262 xmlDictReference(ret->dict); 3263 3264 return (ret); 3265} 3266 3267/** 3268 * xmlSchemaNewFacet: 3269 * 3270 * Allocate a new Facet structure. 3271 * 3272 * Returns the newly allocated structure or NULL in case or error 3273 */ 3274xmlSchemaFacetPtr 3275xmlSchemaNewFacet(void) 3276{ 3277 xmlSchemaFacetPtr ret; 3278 3279 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet)); 3280 if (ret == NULL) { 3281 return (NULL); 3282 } 3283 memset(ret, 0, sizeof(xmlSchemaFacet)); 3284 3285 return (ret); 3286} 3287 3288/** 3289 * xmlSchemaNewAnnot: 3290 * @ctxt: a schema validation context 3291 * @node: a node 3292 * 3293 * Allocate a new annotation structure. 3294 * 3295 * Returns the newly allocated structure or NULL in case or error 3296 */ 3297static xmlSchemaAnnotPtr 3298xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) 3299{ 3300 xmlSchemaAnnotPtr ret; 3301 3302 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot)); 3303 if (ret == NULL) { 3304 xmlSchemaPErrMemory(ctxt, "allocating annotation", node); 3305 return (NULL); 3306 } 3307 memset(ret, 0, sizeof(xmlSchemaAnnot)); 3308 ret->content = node; 3309 return (ret); 3310} 3311 3312static xmlSchemaItemListPtr 3313xmlSchemaItemListCreate(void) 3314{ 3315 xmlSchemaItemListPtr ret; 3316 3317 ret = xmlMalloc(sizeof(xmlSchemaItemList)); 3318 if (ret == NULL) { 3319 xmlSchemaPErrMemory(NULL, 3320 "allocating an item list structure", NULL); 3321 return (NULL); 3322 } 3323 memset(ret, 0, sizeof(xmlSchemaItemList)); 3324 return (ret); 3325} 3326 3327static void 3328xmlSchemaItemListClear(xmlSchemaItemListPtr list) 3329{ 3330 if (list->items != NULL) { 3331 xmlFree(list->items); 3332 list->items = NULL; 3333 } 3334 list->nbItems = 0; 3335 list->sizeItems = 0; 3336} 3337 3338static int 3339xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item) 3340{ 3341 if (list->items == NULL) { 3342 list->items = (void **) xmlMalloc( 3343 20 * sizeof(void *)); 3344 if (list->items == NULL) { 3345 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); 3346 return(-1); 3347 } 3348 list->sizeItems = 20; 3349 } else if (list->sizeItems <= list->nbItems) { 3350 list->sizeItems *= 2; 3351 list->items = (void **) xmlRealloc(list->items, 3352 list->sizeItems * sizeof(void *)); 3353 if (list->items == NULL) { 3354 xmlSchemaPErrMemory(NULL, "growing item list", NULL); 3355 list->sizeItems = 0; 3356 return(-1); 3357 } 3358 } 3359 list->items[list->nbItems++] = item; 3360 return(0); 3361} 3362 3363static int 3364xmlSchemaItemListAddSize(xmlSchemaItemListPtr list, 3365 int initialSize, 3366 void *item) 3367{ 3368 if (list->items == NULL) { 3369 if (initialSize <= 0) 3370 initialSize = 1; 3371 list->items = (void **) xmlMalloc( 3372 initialSize * sizeof(void *)); 3373 if (list->items == NULL) { 3374 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); 3375 return(-1); 3376 } 3377 list->sizeItems = initialSize; 3378 } else if (list->sizeItems <= list->nbItems) { 3379 list->sizeItems *= 2; 3380 list->items = (void **) xmlRealloc(list->items, 3381 list->sizeItems * sizeof(void *)); 3382 if (list->items == NULL) { 3383 xmlSchemaPErrMemory(NULL, "growing item list", NULL); 3384 list->sizeItems = 0; 3385 return(-1); 3386 } 3387 } 3388 list->items[list->nbItems++] = item; 3389 return(0); 3390} 3391 3392static int 3393xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx) 3394{ 3395 if (list->items == NULL) { 3396 list->items = (void **) xmlMalloc( 3397 20 * sizeof(void *)); 3398 if (list->items == NULL) { 3399 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); 3400 return(-1); 3401 } 3402 list->sizeItems = 20; 3403 } else if (list->sizeItems <= list->nbItems) { 3404 list->sizeItems *= 2; 3405 list->items = (void **) xmlRealloc(list->items, 3406 list->sizeItems * sizeof(void *)); 3407 if (list->items == NULL) { 3408 xmlSchemaPErrMemory(NULL, "growing item list", NULL); 3409 list->sizeItems = 0; 3410 return(-1); 3411 } 3412 } 3413 /* 3414 * Just append if the index is greater/equal than the item count. 3415 */ 3416 if (idx >= list->nbItems) { 3417 list->items[list->nbItems++] = item; 3418 } else { 3419 int i; 3420 for (i = list->nbItems; i > idx; i--) 3421 list->items[i] = list->items[i-1]; 3422 list->items[idx] = item; 3423 list->nbItems++; 3424 } 3425 return(0); 3426} 3427 3428#if 0 /* enable if ever needed */ 3429static int 3430xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list, 3431 int initialSize, 3432 void *item, 3433 int idx) 3434{ 3435 if (list->items == NULL) { 3436 if (initialSize <= 0) 3437 initialSize = 1; 3438 list->items = (void **) xmlMalloc( 3439 initialSize * sizeof(void *)); 3440 if (list->items == NULL) { 3441 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); 3442 return(-1); 3443 } 3444 list->sizeItems = initialSize; 3445 } else if (list->sizeItems <= list->nbItems) { 3446 list->sizeItems *= 2; 3447 list->items = (void **) xmlRealloc(list->items, 3448 list->sizeItems * sizeof(void *)); 3449 if (list->items == NULL) { 3450 xmlSchemaPErrMemory(NULL, "growing item list", NULL); 3451 list->sizeItems = 0; 3452 return(-1); 3453 } 3454 } 3455 /* 3456 * Just append if the index is greater/equal than the item count. 3457 */ 3458 if (idx >= list->nbItems) { 3459 list->items[list->nbItems++] = item; 3460 } else { 3461 int i; 3462 for (i = list->nbItems; i > idx; i--) 3463 list->items[i] = list->items[i-1]; 3464 list->items[idx] = item; 3465 list->nbItems++; 3466 } 3467 return(0); 3468} 3469#endif 3470 3471static int 3472xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx) 3473{ 3474 int i; 3475 if ((list->items == NULL) || (idx >= list->nbItems)) { 3476 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, " 3477 "index error.\n"); 3478 return(-1); 3479 } 3480 3481 if (list->nbItems == 1) { 3482 /* TODO: Really free the list? */ 3483 xmlFree(list->items); 3484 list->items = NULL; 3485 list->nbItems = 0; 3486 list->sizeItems = 0; 3487 } else if (list->nbItems -1 == idx) { 3488 list->nbItems--; 3489 } else { 3490 for (i = idx; i < list->nbItems -1; i++) 3491 list->items[i] = list->items[i+1]; 3492 list->nbItems--; 3493 } 3494 return(0); 3495} 3496 3497/** 3498 * xmlSchemaItemListFree: 3499 * @annot: a schema type structure 3500 * 3501 * Deallocate a annotation structure 3502 */ 3503static void 3504xmlSchemaItemListFree(xmlSchemaItemListPtr list) 3505{ 3506 if (list == NULL) 3507 return; 3508 if (list->items != NULL) 3509 xmlFree(list->items); 3510 xmlFree(list); 3511} 3512 3513static void 3514xmlSchemaBucketFree(xmlSchemaBucketPtr bucket) 3515{ 3516 if (bucket == NULL) 3517 return; 3518 if (bucket->globals != NULL) { 3519 xmlSchemaComponentListFree(bucket->globals); 3520 xmlSchemaItemListFree(bucket->globals); 3521 } 3522 if (bucket->locals != NULL) { 3523 xmlSchemaComponentListFree(bucket->locals); 3524 xmlSchemaItemListFree(bucket->locals); 3525 } 3526 if (bucket->relations != NULL) { 3527 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations; 3528 do { 3529 prev = cur; 3530 cur = cur->next; 3531 xmlFree(prev); 3532 } while (cur != NULL); 3533 } 3534 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) { 3535 xmlFreeDoc(bucket->doc); 3536 } 3537 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) { 3538 if (WXS_IMPBUCKET(bucket)->schema != NULL) 3539 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema); 3540 } 3541 xmlFree(bucket); 3542} 3543 3544static xmlSchemaBucketPtr 3545xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt, 3546 int type, const xmlChar *targetNamespace) 3547{ 3548 xmlSchemaBucketPtr ret; 3549 int size; 3550 xmlSchemaPtr mainSchema; 3551 3552 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) { 3553 PERROR_INT("xmlSchemaBucketCreate", 3554 "no main schema on constructor"); 3555 return(NULL); 3556 } 3557 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema; 3558 /* Create the schema bucket. */ 3559 if (WXS_IS_BUCKET_INCREDEF(type)) 3560 size = sizeof(xmlSchemaInclude); 3561 else 3562 size = sizeof(xmlSchemaImport); 3563 ret = (xmlSchemaBucketPtr) xmlMalloc(size); 3564 if (ret == NULL) { 3565 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL); 3566 return(NULL); 3567 } 3568 memset(ret, 0, size); 3569 ret->targetNamespace = targetNamespace; 3570 ret->type = type; 3571 ret->globals = xmlSchemaItemListCreate(); 3572 if (ret->globals == NULL) { 3573 xmlFree(ret); 3574 return(NULL); 3575 } 3576 ret->locals = xmlSchemaItemListCreate(); 3577 if (ret->locals == NULL) { 3578 xmlFree(ret); 3579 return(NULL); 3580 } 3581 /* 3582 * The following will assure that only the first bucket is marked as 3583 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema. 3584 * For each following import buckets an xmlSchema will be created. 3585 * An xmlSchema will be created for every distinct targetNamespace. 3586 * We assign the targetNamespace to the schemata here. 3587 */ 3588 if (! WXS_HAS_BUCKETS(pctxt)) { 3589 if (WXS_IS_BUCKET_INCREDEF(type)) { 3590 PERROR_INT("xmlSchemaBucketCreate", 3591 "first bucket but it's an include or redefine"); 3592 xmlSchemaBucketFree(ret); 3593 return(NULL); 3594 } 3595 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */ 3596 ret->type = XML_SCHEMA_SCHEMA_MAIN; 3597 /* Point to the *main* schema. */ 3598 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret; 3599 WXS_IMPBUCKET(ret)->schema = mainSchema; 3600 /* 3601 * Ensure that the main schema gets a targetNamespace. 3602 */ 3603 mainSchema->targetNamespace = targetNamespace; 3604 } else { 3605 if (type == XML_SCHEMA_SCHEMA_MAIN) { 3606 PERROR_INT("xmlSchemaBucketCreate", 3607 "main bucket but it's not the first one"); 3608 xmlSchemaBucketFree(ret); 3609 return(NULL); 3610 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) { 3611 /* 3612 * Create a schema for imports and assign the 3613 * targetNamespace. 3614 */ 3615 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt); 3616 if (WXS_IMPBUCKET(ret)->schema == NULL) { 3617 xmlSchemaBucketFree(ret); 3618 return(NULL); 3619 } 3620 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace; 3621 } 3622 } 3623 if (WXS_IS_BUCKET_IMPMAIN(type)) { 3624 int res; 3625 /* 3626 * Imports go into the "schemasImports" slot of the main *schema*. 3627 * Note that we create an import entry for the main schema as well; i.e., 3628 * even if there's only one schema, we'll get an import. 3629 */ 3630 if (mainSchema->schemasImports == NULL) { 3631 mainSchema->schemasImports = xmlHashCreateDict(5, 3632 WXS_CONSTRUCTOR(pctxt)->dict); 3633 if (mainSchema->schemasImports == NULL) { 3634 xmlSchemaBucketFree(ret); 3635 return(NULL); 3636 } 3637 } 3638 if (targetNamespace == NULL) 3639 res = xmlHashAddEntry(mainSchema->schemasImports, 3640 XML_SCHEMAS_NO_NAMESPACE, ret); 3641 else 3642 res = xmlHashAddEntry(mainSchema->schemasImports, 3643 targetNamespace, ret); 3644 if (res != 0) { 3645 PERROR_INT("xmlSchemaBucketCreate", 3646 "failed to add the schema bucket to the hash"); 3647 xmlSchemaBucketFree(ret); 3648 return(NULL); 3649 } 3650 } else { 3651 /* Set the @ownerImport of an include bucket. */ 3652 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type)) 3653 WXS_INCBUCKET(ret)->ownerImport = 3654 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket); 3655 else 3656 WXS_INCBUCKET(ret)->ownerImport = 3657 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport; 3658 3659 /* Includes got into the "includes" slot of the *main* schema. */ 3660 if (mainSchema->includes == NULL) { 3661 mainSchema->includes = xmlSchemaItemListCreate(); 3662 if (mainSchema->includes == NULL) { 3663 xmlSchemaBucketFree(ret); 3664 return(NULL); 3665 } 3666 } 3667 xmlSchemaItemListAdd(mainSchema->includes, ret); 3668 } 3669 /* 3670 * Add to list of all buckets; this is used for lookup 3671 * during schema construction time only. 3672 */ 3673 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1) 3674 return(NULL); 3675 return(ret); 3676} 3677 3678static int 3679xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item) 3680{ 3681 if (*list == NULL) { 3682 *list = xmlSchemaItemListCreate(); 3683 if (*list == NULL) 3684 return(-1); 3685 } 3686 xmlSchemaItemListAddSize(*list, initialSize, item); 3687 return(0); 3688} 3689 3690/** 3691 * xmlSchemaFreeAnnot: 3692 * @annot: a schema type structure 3693 * 3694 * Deallocate a annotation structure 3695 */ 3696static void 3697xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot) 3698{ 3699 if (annot == NULL) 3700 return; 3701 if (annot->next == NULL) { 3702 xmlFree(annot); 3703 } else { 3704 xmlSchemaAnnotPtr prev; 3705 3706 do { 3707 prev = annot; 3708 annot = annot->next; 3709 xmlFree(prev); 3710 } while (annot != NULL); 3711 } 3712} 3713 3714/** 3715 * xmlSchemaFreeNotation: 3716 * @schema: a schema notation structure 3717 * 3718 * Deallocate a Schema Notation structure. 3719 */ 3720static void 3721xmlSchemaFreeNotation(xmlSchemaNotationPtr nota) 3722{ 3723 if (nota == NULL) 3724 return; 3725 xmlFree(nota); 3726} 3727 3728/** 3729 * xmlSchemaFreeAttribute: 3730 * @attr: an attribute declaration 3731 * 3732 * Deallocates an attribute declaration structure. 3733 */ 3734static void 3735xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr) 3736{ 3737 if (attr == NULL) 3738 return; 3739 if (attr->annot != NULL) 3740 xmlSchemaFreeAnnot(attr->annot); 3741 if (attr->defVal != NULL) 3742 xmlSchemaFreeValue(attr->defVal); 3743 xmlFree(attr); 3744} 3745 3746/** 3747 * xmlSchemaFreeAttributeUse: 3748 * @use: an attribute use 3749 * 3750 * Deallocates an attribute use structure. 3751 */ 3752static void 3753xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use) 3754{ 3755 if (use == NULL) 3756 return; 3757 if (use->annot != NULL) 3758 xmlSchemaFreeAnnot(use->annot); 3759 if (use->defVal != NULL) 3760 xmlSchemaFreeValue(use->defVal); 3761 xmlFree(use); 3762} 3763 3764/** 3765 * xmlSchemaFreeAttributeUseProhib: 3766 * @prohib: an attribute use prohibition 3767 * 3768 * Deallocates an attribute use structure. 3769 */ 3770static void 3771xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib) 3772{ 3773 if (prohib == NULL) 3774 return; 3775 xmlFree(prohib); 3776} 3777 3778/** 3779 * xmlSchemaFreeWildcardNsSet: 3780 * set: a schema wildcard namespace 3781 * 3782 * Deallocates a list of wildcard constraint structures. 3783 */ 3784static void 3785xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set) 3786{ 3787 xmlSchemaWildcardNsPtr next; 3788 3789 while (set != NULL) { 3790 next = set->next; 3791 xmlFree(set); 3792 set = next; 3793 } 3794} 3795 3796/** 3797 * xmlSchemaFreeWildcard: 3798 * @wildcard: a wildcard structure 3799 * 3800 * Deallocates a wildcard structure. 3801 */ 3802void 3803xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard) 3804{ 3805 if (wildcard == NULL) 3806 return; 3807 if (wildcard->annot != NULL) 3808 xmlSchemaFreeAnnot(wildcard->annot); 3809 if (wildcard->nsSet != NULL) 3810 xmlSchemaFreeWildcardNsSet(wildcard->nsSet); 3811 if (wildcard->negNsSet != NULL) 3812 xmlFree(wildcard->negNsSet); 3813 xmlFree(wildcard); 3814} 3815 3816/** 3817 * xmlSchemaFreeAttributeGroup: 3818 * @schema: a schema attribute group structure 3819 * 3820 * Deallocate a Schema Attribute Group structure. 3821 */ 3822static void 3823xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr) 3824{ 3825 if (attrGr == NULL) 3826 return; 3827 if (attrGr->annot != NULL) 3828 xmlSchemaFreeAnnot(attrGr->annot); 3829 if (attrGr->attrUses != NULL) 3830 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses); 3831 xmlFree(attrGr); 3832} 3833 3834/** 3835 * xmlSchemaFreeQNameRef: 3836 * @item: a QName reference structure 3837 * 3838 * Deallocatea a QName reference structure. 3839 */ 3840static void 3841xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item) 3842{ 3843 xmlFree(item); 3844} 3845 3846/** 3847 * xmlSchemaFreeTypeLinkList: 3848 * @alink: a type link 3849 * 3850 * Deallocate a list of types. 3851 */ 3852static void 3853xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link) 3854{ 3855 xmlSchemaTypeLinkPtr next; 3856 3857 while (link != NULL) { 3858 next = link->next; 3859 xmlFree(link); 3860 link = next; 3861 } 3862} 3863 3864static void 3865xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto) 3866{ 3867 xmlSchemaIDCStateObjPtr next; 3868 while (sto != NULL) { 3869 next = sto->next; 3870 if (sto->history != NULL) 3871 xmlFree(sto->history); 3872 if (sto->xpathCtxt != NULL) 3873 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt); 3874 xmlFree(sto); 3875 sto = next; 3876 } 3877} 3878 3879/** 3880 * xmlSchemaFreeIDC: 3881 * @idc: a identity-constraint definition 3882 * 3883 * Deallocates an identity-constraint definition. 3884 */ 3885static void 3886xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef) 3887{ 3888 xmlSchemaIDCSelectPtr cur, prev; 3889 3890 if (idcDef == NULL) 3891 return; 3892 if (idcDef->annot != NULL) 3893 xmlSchemaFreeAnnot(idcDef->annot); 3894 /* Selector */ 3895 if (idcDef->selector != NULL) { 3896 if (idcDef->selector->xpathComp != NULL) 3897 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp); 3898 xmlFree(idcDef->selector); 3899 } 3900 /* Fields */ 3901 if (idcDef->fields != NULL) { 3902 cur = idcDef->fields; 3903 do { 3904 prev = cur; 3905 cur = cur->next; 3906 if (prev->xpathComp != NULL) 3907 xmlFreePattern((xmlPatternPtr) prev->xpathComp); 3908 xmlFree(prev); 3909 } while (cur != NULL); 3910 } 3911 xmlFree(idcDef); 3912} 3913 3914/** 3915 * xmlSchemaFreeElement: 3916 * @schema: a schema element structure 3917 * 3918 * Deallocate a Schema Element structure. 3919 */ 3920static void 3921xmlSchemaFreeElement(xmlSchemaElementPtr elem) 3922{ 3923 if (elem == NULL) 3924 return; 3925 if (elem->annot != NULL) 3926 xmlSchemaFreeAnnot(elem->annot); 3927 if (elem->contModel != NULL) 3928 xmlRegFreeRegexp(elem->contModel); 3929 if (elem->defVal != NULL) 3930 xmlSchemaFreeValue(elem->defVal); 3931 xmlFree(elem); 3932} 3933 3934/** 3935 * xmlSchemaFreeFacet: 3936 * @facet: a schema facet structure 3937 * 3938 * Deallocate a Schema Facet structure. 3939 */ 3940void 3941xmlSchemaFreeFacet(xmlSchemaFacetPtr facet) 3942{ 3943 if (facet == NULL) 3944 return; 3945 if (facet->val != NULL) 3946 xmlSchemaFreeValue(facet->val); 3947 if (facet->regexp != NULL) 3948 xmlRegFreeRegexp(facet->regexp); 3949 if (facet->annot != NULL) 3950 xmlSchemaFreeAnnot(facet->annot); 3951 xmlFree(facet); 3952} 3953 3954/** 3955 * xmlSchemaFreeType: 3956 * @type: a schema type structure 3957 * 3958 * Deallocate a Schema Type structure. 3959 */ 3960void 3961xmlSchemaFreeType(xmlSchemaTypePtr type) 3962{ 3963 if (type == NULL) 3964 return; 3965 if (type->annot != NULL) 3966 xmlSchemaFreeAnnot(type->annot); 3967 if (type->facets != NULL) { 3968 xmlSchemaFacetPtr facet, next; 3969 3970 facet = type->facets; 3971 while (facet != NULL) { 3972 next = facet->next; 3973 xmlSchemaFreeFacet(facet); 3974 facet = next; 3975 } 3976 } 3977 if (type->attrUses != NULL) 3978 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses); 3979 if (type->memberTypes != NULL) 3980 xmlSchemaFreeTypeLinkList(type->memberTypes); 3981 if (type->facetSet != NULL) { 3982 xmlSchemaFacetLinkPtr next, link; 3983 3984 link = type->facetSet; 3985 do { 3986 next = link->next; 3987 xmlFree(link); 3988 link = next; 3989 } while (link != NULL); 3990 } 3991 if (type->contModel != NULL) 3992 xmlRegFreeRegexp(type->contModel); 3993 xmlFree(type); 3994} 3995 3996/** 3997 * xmlSchemaFreeModelGroupDef: 3998 * @item: a schema model group definition 3999 * 4000 * Deallocates a schema model group definition. 4001 */ 4002static void 4003xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item) 4004{ 4005 if (item->annot != NULL) 4006 xmlSchemaFreeAnnot(item->annot); 4007 xmlFree(item); 4008} 4009 4010/** 4011 * xmlSchemaFreeModelGroup: 4012 * @item: a schema model group 4013 * 4014 * Deallocates a schema model group structure. 4015 */ 4016static void 4017xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item) 4018{ 4019 if (item->annot != NULL) 4020 xmlSchemaFreeAnnot(item->annot); 4021 xmlFree(item); 4022} 4023 4024static void 4025xmlSchemaComponentListFree(xmlSchemaItemListPtr list) 4026{ 4027 if ((list == NULL) || (list->nbItems == 0)) 4028 return; 4029 { 4030 xmlSchemaTreeItemPtr item; 4031 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items; 4032 int i; 4033 4034 for (i = 0; i < list->nbItems; i++) { 4035 item = items[i]; 4036 if (item == NULL) 4037 continue; 4038 switch (item->type) { 4039 case XML_SCHEMA_TYPE_SIMPLE: 4040 case XML_SCHEMA_TYPE_COMPLEX: 4041 xmlSchemaFreeType((xmlSchemaTypePtr) item); 4042 break; 4043 case XML_SCHEMA_TYPE_ATTRIBUTE: 4044 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item); 4045 break; 4046 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: 4047 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item); 4048 break; 4049 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB: 4050 xmlSchemaFreeAttributeUseProhib( 4051 (xmlSchemaAttributeUseProhibPtr) item); 4052 break; 4053 case XML_SCHEMA_TYPE_ELEMENT: 4054 xmlSchemaFreeElement((xmlSchemaElementPtr) item); 4055 break; 4056 case XML_SCHEMA_TYPE_PARTICLE: 4057 if (item->annot != NULL) 4058 xmlSchemaFreeAnnot(item->annot); 4059 xmlFree(item); 4060 break; 4061 case XML_SCHEMA_TYPE_SEQUENCE: 4062 case XML_SCHEMA_TYPE_CHOICE: 4063 case XML_SCHEMA_TYPE_ALL: 4064 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item); 4065 break; 4066 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: 4067 xmlSchemaFreeAttributeGroup( 4068 (xmlSchemaAttributeGroupPtr) item); 4069 break; 4070 case XML_SCHEMA_TYPE_GROUP: 4071 xmlSchemaFreeModelGroupDef( 4072 (xmlSchemaModelGroupDefPtr) item); 4073 break; 4074 case XML_SCHEMA_TYPE_ANY: 4075 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: 4076 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item); 4077 break; 4078 case XML_SCHEMA_TYPE_IDC_KEY: 4079 case XML_SCHEMA_TYPE_IDC_UNIQUE: 4080 case XML_SCHEMA_TYPE_IDC_KEYREF: 4081 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item); 4082 break; 4083 case XML_SCHEMA_TYPE_NOTATION: 4084 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item); 4085 break; 4086 case XML_SCHEMA_EXTRA_QNAMEREF: 4087 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item); 4088 break; 4089 default: { 4090 /* TODO: This should never be hit. */ 4091 xmlSchemaPSimpleInternalErr(NULL, 4092 "Internal error: xmlSchemaComponentListFree, " 4093 "unexpected component type '%s'\n", 4094 (const xmlChar *) WXS_ITEM_TYPE_NAME(item)); 4095 } 4096 break; 4097 } 4098 } 4099 list->nbItems = 0; 4100 } 4101} 4102 4103/** 4104 * xmlSchemaFree: 4105 * @schema: a schema structure 4106 * 4107 * Deallocate a Schema structure. 4108 */ 4109void 4110xmlSchemaFree(xmlSchemaPtr schema) 4111{ 4112 if (schema == NULL) 4113 return; 4114 /* @volatiles is not used anymore :-/ */ 4115 if (schema->volatiles != NULL) 4116 TODO 4117 /* 4118 * Note that those slots are not responsible for freeing 4119 * schema components anymore; this will now be done by 4120 * the schema buckets. 4121 */ 4122 if (schema->notaDecl != NULL) 4123 xmlHashFree(schema->notaDecl, NULL); 4124 if (schema->attrDecl != NULL) 4125 xmlHashFree(schema->attrDecl, NULL); 4126 if (schema->attrgrpDecl != NULL) 4127 xmlHashFree(schema->attrgrpDecl, NULL); 4128 if (schema->elemDecl != NULL) 4129 xmlHashFree(schema->elemDecl, NULL); 4130 if (schema->typeDecl != NULL) 4131 xmlHashFree(schema->typeDecl, NULL); 4132 if (schema->groupDecl != NULL) 4133 xmlHashFree(schema->groupDecl, NULL); 4134 if (schema->idcDef != NULL) 4135 xmlHashFree(schema->idcDef, NULL); 4136 4137 if (schema->schemasImports != NULL) 4138 xmlHashFree(schema->schemasImports, 4139 (xmlHashDeallocator) xmlSchemaBucketFree); 4140 if (schema->includes != NULL) { 4141 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes; 4142 int i; 4143 for (i = 0; i < list->nbItems; i++) { 4144 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]); 4145 } 4146 xmlSchemaItemListFree(list); 4147 } 4148 if (schema->annot != NULL) 4149 xmlSchemaFreeAnnot(schema->annot); 4150 /* Never free the doc here, since this will be done by the buckets. */ 4151 4152 xmlDictFree(schema->dict); 4153 xmlFree(schema); 4154} 4155 4156/************************************************************************ 4157 * * 4158 * Debug functions * 4159 * * 4160 ************************************************************************/ 4161 4162#ifdef LIBXML_OUTPUT_ENABLED 4163 4164static void 4165xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */ 4166 4167/** 4168 * xmlSchemaElementDump: 4169 * @elem: an element 4170 * @output: the file output 4171 * 4172 * Dump the element 4173 */ 4174static void 4175xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output, 4176 const xmlChar * name ATTRIBUTE_UNUSED, 4177 const xmlChar * namespace ATTRIBUTE_UNUSED, 4178 const xmlChar * context ATTRIBUTE_UNUSED) 4179{ 4180 if (elem == NULL) 4181 return; 4182 4183 4184 fprintf(output, "Element"); 4185 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL) 4186 fprintf(output, " (global)"); 4187 fprintf(output, ": '%s' ", elem->name); 4188 if (namespace != NULL) 4189 fprintf(output, "ns '%s'", namespace); 4190 fprintf(output, "\n"); 4191#if 0 4192 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) { 4193 fprintf(output, " min %d ", elem->minOccurs); 4194 if (elem->maxOccurs >= UNBOUNDED) 4195 fprintf(output, "max: unbounded\n"); 4196 else if (elem->maxOccurs != 1) 4197 fprintf(output, "max: %d\n", elem->maxOccurs); 4198 else 4199 fprintf(output, "\n"); 4200 } 4201#endif 4202 /* 4203 * Misc other properties. 4204 */ 4205 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) || 4206 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) || 4207 (elem->flags & XML_SCHEMAS_ELEM_FIXED) || 4208 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) { 4209 fprintf(output, " props: "); 4210 if (elem->flags & XML_SCHEMAS_ELEM_FIXED) 4211 fprintf(output, "[fixed] "); 4212 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) 4213 fprintf(output, "[default] "); 4214 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) 4215 fprintf(output, "[abstract] "); 4216 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE) 4217 fprintf(output, "[nillable] "); 4218 fprintf(output, "\n"); 4219 } 4220 /* 4221 * Default/fixed value. 4222 */ 4223 if (elem->value != NULL) 4224 fprintf(output, " value: '%s'\n", elem->value); 4225 /* 4226 * Type. 4227 */ 4228 if (elem->namedType != NULL) { 4229 fprintf(output, " type: '%s' ", elem->namedType); 4230 if (elem->namedTypeNs != NULL) 4231 fprintf(output, "ns '%s'\n", elem->namedTypeNs); 4232 else 4233 fprintf(output, "\n"); 4234 } else if (elem->subtypes != NULL) { 4235 /* 4236 * Dump local types. 4237 */ 4238 xmlSchemaTypeDump(elem->subtypes, output); 4239 } 4240 /* 4241 * Substitution group. 4242 */ 4243 if (elem->substGroup != NULL) { 4244 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup); 4245 if (elem->substGroupNs != NULL) 4246 fprintf(output, "ns '%s'\n", elem->substGroupNs); 4247 else 4248 fprintf(output, "\n"); 4249 } 4250} 4251 4252/** 4253 * xmlSchemaAnnotDump: 4254 * @output: the file output 4255 * @annot: a annotation 4256 * 4257 * Dump the annotation 4258 */ 4259static void 4260xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot) 4261{ 4262 xmlChar *content; 4263 4264 if (annot == NULL) 4265 return; 4266 4267 content = xmlNodeGetContent(annot->content); 4268 if (content != NULL) { 4269 fprintf(output, " Annot: %s\n", content); 4270 xmlFree(content); 4271 } else 4272 fprintf(output, " Annot: empty\n"); 4273} 4274 4275/** 4276 * xmlSchemaContentModelDump: 4277 * @particle: the schema particle 4278 * @output: the file output 4279 * @depth: the depth used for intentation 4280 * 4281 * Dump a SchemaType structure 4282 */ 4283static void 4284xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth) 4285{ 4286 xmlChar *str = NULL; 4287 xmlSchemaTreeItemPtr term; 4288 char shift[100]; 4289 int i; 4290 4291 if (particle == NULL) 4292 return; 4293 for (i = 0;((i < depth) && (i < 25));i++) 4294 shift[2 * i] = shift[2 * i + 1] = ' '; 4295 shift[2 * i] = shift[2 * i + 1] = 0; 4296 fprintf(output, "%s", shift); 4297 if (particle->children == NULL) { 4298 fprintf(output, "MISSING particle term\n"); 4299 return; 4300 } 4301 term = particle->children; 4302 if (term == NULL) { 4303 fprintf(output, "(NULL)"); 4304 } else { 4305 switch (term->type) { 4306 case XML_SCHEMA_TYPE_ELEMENT: 4307 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str, 4308 ((xmlSchemaElementPtr)term)->targetNamespace, 4309 ((xmlSchemaElementPtr)term)->name)); 4310 FREE_AND_NULL(str); 4311 break; 4312 case XML_SCHEMA_TYPE_SEQUENCE: 4313 fprintf(output, "SEQUENCE"); 4314 break; 4315 case XML_SCHEMA_TYPE_CHOICE: 4316 fprintf(output, "CHOICE"); 4317 break; 4318 case XML_SCHEMA_TYPE_ALL: 4319 fprintf(output, "ALL"); 4320 break; 4321 case XML_SCHEMA_TYPE_ANY: 4322 fprintf(output, "ANY"); 4323 break; 4324 default: 4325 fprintf(output, "UNKNOWN\n"); 4326 return; 4327 } 4328 } 4329 if (particle->minOccurs != 1) 4330 fprintf(output, " min: %d", particle->minOccurs); 4331 if (particle->maxOccurs >= UNBOUNDED) 4332 fprintf(output, " max: unbounded"); 4333 else if (particle->maxOccurs != 1) 4334 fprintf(output, " max: %d", particle->maxOccurs); 4335 fprintf(output, "\n"); 4336 if (term && 4337 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) || 4338 (term->type == XML_SCHEMA_TYPE_CHOICE) || 4339 (term->type == XML_SCHEMA_TYPE_ALL)) && 4340 (term->children != NULL)) { 4341 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children, 4342 output, depth +1); 4343 } 4344 if (particle->next != NULL) 4345 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next, 4346 output, depth); 4347} 4348 4349/** 4350 * xmlSchemaAttrUsesDump: 4351 * @uses: attribute uses list 4352 * @output: the file output 4353 * 4354 * Dumps a list of attribute use components. 4355 */ 4356static void 4357xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output) 4358{ 4359 xmlSchemaAttributeUsePtr use; 4360 xmlSchemaAttributeUseProhibPtr prohib; 4361 xmlSchemaQNameRefPtr ref; 4362 const xmlChar *name, *tns; 4363 xmlChar *str = NULL; 4364 int i; 4365 4366 if ((uses == NULL) || (uses->nbItems == 0)) 4367 return; 4368 4369 fprintf(output, " attributes:\n"); 4370 for (i = 0; i < uses->nbItems; i++) { 4371 use = uses->items[i]; 4372 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) { 4373 fprintf(output, " [prohibition] "); 4374 prohib = (xmlSchemaAttributeUseProhibPtr) use; 4375 name = prohib->name; 4376 tns = prohib->targetNamespace; 4377 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) { 4378 fprintf(output, " [reference] "); 4379 ref = (xmlSchemaQNameRefPtr) use; 4380 name = ref->name; 4381 tns = ref->targetNamespace; 4382 } else { 4383 fprintf(output, " [use] "); 4384 name = WXS_ATTRUSE_DECL_NAME(use); 4385 tns = WXS_ATTRUSE_DECL_TNS(use); 4386 } 4387 fprintf(output, "'%s'\n", 4388 (const char *) xmlSchemaFormatQName(&str, tns, name)); 4389 FREE_AND_NULL(str); 4390 } 4391} 4392 4393/** 4394 * xmlSchemaTypeDump: 4395 * @output: the file output 4396 * @type: a type structure 4397 * 4398 * Dump a SchemaType structure 4399 */ 4400static void 4401xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output) 4402{ 4403 if (type == NULL) { 4404 fprintf(output, "Type: NULL\n"); 4405 return; 4406 } 4407 fprintf(output, "Type: "); 4408 if (type->name != NULL) 4409 fprintf(output, "'%s' ", type->name); 4410 else 4411 fprintf(output, "(no name) "); 4412 if (type->targetNamespace != NULL) 4413 fprintf(output, "ns '%s' ", type->targetNamespace); 4414 switch (type->type) { 4415 case XML_SCHEMA_TYPE_BASIC: 4416 fprintf(output, "[basic] "); 4417 break; 4418 case XML_SCHEMA_TYPE_SIMPLE: 4419 fprintf(output, "[simple] "); 4420 break; 4421 case XML_SCHEMA_TYPE_COMPLEX: 4422 fprintf(output, "[complex] "); 4423 break; 4424 case XML_SCHEMA_TYPE_SEQUENCE: 4425 fprintf(output, "[sequence] "); 4426 break; 4427 case XML_SCHEMA_TYPE_CHOICE: 4428 fprintf(output, "[choice] "); 4429 break; 4430 case XML_SCHEMA_TYPE_ALL: 4431 fprintf(output, "[all] "); 4432 break; 4433 case XML_SCHEMA_TYPE_UR: 4434 fprintf(output, "[ur] "); 4435 break; 4436 case XML_SCHEMA_TYPE_RESTRICTION: 4437 fprintf(output, "[restriction] "); 4438 break; 4439 case XML_SCHEMA_TYPE_EXTENSION: 4440 fprintf(output, "[extension] "); 4441 break; 4442 default: 4443 fprintf(output, "[unknown type %d] ", type->type); 4444 break; 4445 } 4446 fprintf(output, "content: "); 4447 switch (type->contentType) { 4448 case XML_SCHEMA_CONTENT_UNKNOWN: 4449 fprintf(output, "[unknown] "); 4450 break; 4451 case XML_SCHEMA_CONTENT_EMPTY: 4452 fprintf(output, "[empty] "); 4453 break; 4454 case XML_SCHEMA_CONTENT_ELEMENTS: 4455 fprintf(output, "[element] "); 4456 break; 4457 case XML_SCHEMA_CONTENT_MIXED: 4458 fprintf(output, "[mixed] "); 4459 break; 4460 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS: 4461 /* not used. */ 4462 break; 4463 case XML_SCHEMA_CONTENT_BASIC: 4464 fprintf(output, "[basic] "); 4465 break; 4466 case XML_SCHEMA_CONTENT_SIMPLE: 4467 fprintf(output, "[simple] "); 4468 break; 4469 case XML_SCHEMA_CONTENT_ANY: 4470 fprintf(output, "[any] "); 4471 break; 4472 } 4473 fprintf(output, "\n"); 4474 if (type->base != NULL) { 4475 fprintf(output, " base type: '%s'", type->base); 4476 if (type->baseNs != NULL) 4477 fprintf(output, " ns '%s'\n", type->baseNs); 4478 else 4479 fprintf(output, "\n"); 4480 } 4481 if (type->attrUses != NULL) 4482 xmlSchemaAttrUsesDump(type->attrUses, output); 4483 if (type->annot != NULL) 4484 xmlSchemaAnnotDump(output, type->annot); 4485#ifdef DUMP_CONTENT_MODEL 4486 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) && 4487 (type->subtypes != NULL)) { 4488 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes, 4489 output, 1); 4490 } 4491#endif 4492} 4493 4494/** 4495 * xmlSchemaDump: 4496 * @output: the file output 4497 * @schema: a schema structure 4498 * 4499 * Dump a Schema structure. 4500 */ 4501void 4502xmlSchemaDump(FILE * output, xmlSchemaPtr schema) 4503{ 4504 if (output == NULL) 4505 return; 4506 if (schema == NULL) { 4507 fprintf(output, "Schemas: NULL\n"); 4508 return; 4509 } 4510 fprintf(output, "Schemas: "); 4511 if (schema->name != NULL) 4512 fprintf(output, "%s, ", schema->name); 4513 else 4514 fprintf(output, "no name, "); 4515 if (schema->targetNamespace != NULL) 4516 fprintf(output, "%s", (const char *) schema->targetNamespace); 4517 else 4518 fprintf(output, "no target namespace"); 4519 fprintf(output, "\n"); 4520 if (schema->annot != NULL) 4521 xmlSchemaAnnotDump(output, schema->annot); 4522 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump, 4523 output); 4524 xmlHashScanFull(schema->elemDecl, 4525 (xmlHashScannerFull) xmlSchemaElementDump, output); 4526} 4527 4528#ifdef DEBUG_IDC_NODE_TABLE 4529/** 4530 * xmlSchemaDebugDumpIDCTable: 4531 * @vctxt: the WXS validation context 4532 * 4533 * Displays the current IDC table for debug purposes. 4534 */ 4535static void 4536xmlSchemaDebugDumpIDCTable(FILE * output, 4537 const xmlChar *namespaceName, 4538 const xmlChar *localName, 4539 xmlSchemaPSVIIDCBindingPtr bind) 4540{ 4541 xmlChar *str = NULL; 4542 const xmlChar *value; 4543 xmlSchemaPSVIIDCNodePtr tab; 4544 xmlSchemaPSVIIDCKeyPtr key; 4545 int i, j, res; 4546 4547 fprintf(output, "IDC: TABLES on '%s'\n", 4548 xmlSchemaFormatQName(&str, namespaceName, localName)); 4549 FREE_AND_NULL(str) 4550 4551 if (bind == NULL) 4552 return; 4553 do { 4554 fprintf(output, "IDC: BINDING '%s' (%d)\n", 4555 xmlSchemaGetComponentQName(&str, 4556 bind->definition), bind->nbNodes); 4557 FREE_AND_NULL(str) 4558 for (i = 0; i < bind->nbNodes; i++) { 4559 tab = bind->nodeTable[i]; 4560 fprintf(output, " ( "); 4561 for (j = 0; j < bind->definition->nbFields; j++) { 4562 key = tab->keys[j]; 4563 if ((key != NULL) && (key->val != NULL)) { 4564 res = xmlSchemaGetCanonValue(key->val, &value); 4565 if (res >= 0) 4566 fprintf(output, "'%s' ", value); 4567 else 4568 fprintf(output, "CANON-VALUE-FAILED "); 4569 if (res == 0) 4570 FREE_AND_NULL(value) 4571 } else if (key != NULL) 4572 fprintf(output, "(no val), "); 4573 else 4574 fprintf(output, "(key missing), "); 4575 } 4576 fprintf(output, ")\n"); 4577 } 4578 if (bind->dupls && bind->dupls->nbItems) { 4579 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems); 4580 for (i = 0; i < bind->dupls->nbItems; i++) { 4581 tab = bind->dupls->items[i]; 4582 fprintf(output, " ( "); 4583 for (j = 0; j < bind->definition->nbFields; j++) { 4584 key = tab->keys[j]; 4585 if ((key != NULL) && (key->val != NULL)) { 4586 res = xmlSchemaGetCanonValue(key->val, &value); 4587 if (res >= 0) 4588 fprintf(output, "'%s' ", value); 4589 else 4590 fprintf(output, "CANON-VALUE-FAILED "); 4591 if (res == 0) 4592 FREE_AND_NULL(value) 4593 } else if (key != NULL) 4594 fprintf(output, "(no val), "); 4595 else 4596 fprintf(output, "(key missing), "); 4597 } 4598 fprintf(output, ")\n"); 4599 } 4600 } 4601 bind = bind->next; 4602 } while (bind != NULL); 4603} 4604#endif /* DEBUG_IDC */ 4605#endif /* LIBXML_OUTPUT_ENABLED */ 4606 4607/************************************************************************ 4608 * * 4609 * Utilities * 4610 * * 4611 ************************************************************************/ 4612 4613/** 4614 * xmlSchemaGetPropNode: 4615 * @node: the element node 4616 * @name: the name of the attribute 4617 * 4618 * Seeks an attribute with a name of @name in 4619 * no namespace. 4620 * 4621 * Returns the attribute or NULL if not present. 4622 */ 4623static xmlAttrPtr 4624xmlSchemaGetPropNode(xmlNodePtr node, const char *name) 4625{ 4626 xmlAttrPtr prop; 4627 4628 if ((node == NULL) || (name == NULL)) 4629 return(NULL); 4630 prop = node->properties; 4631 while (prop != NULL) { 4632 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name)) 4633 return(prop); 4634 prop = prop->next; 4635 } 4636 return (NULL); 4637} 4638 4639/** 4640 * xmlSchemaGetPropNodeNs: 4641 * @node: the element node 4642 * @uri: the uri 4643 * @name: the name of the attribute 4644 * 4645 * Seeks an attribute with a local name of @name and 4646 * a namespace URI of @uri. 4647 * 4648 * Returns the attribute or NULL if not present. 4649 */ 4650static xmlAttrPtr 4651xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name) 4652{ 4653 xmlAttrPtr prop; 4654 4655 if ((node == NULL) || (name == NULL)) 4656 return(NULL); 4657 prop = node->properties; 4658 while (prop != NULL) { 4659 if ((prop->ns != NULL) && 4660 xmlStrEqual(prop->name, BAD_CAST name) && 4661 xmlStrEqual(prop->ns->href, BAD_CAST uri)) 4662 return(prop); 4663 prop = prop->next; 4664 } 4665 return (NULL); 4666} 4667 4668static const xmlChar * 4669xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) 4670{ 4671 xmlChar *val; 4672 const xmlChar *ret; 4673 4674 val = xmlNodeGetContent(node); 4675 if (val == NULL) 4676 val = xmlStrdup((xmlChar *)""); 4677 ret = xmlDictLookup(ctxt->dict, val, -1); 4678 xmlFree(val); 4679 return(ret); 4680} 4681 4682static const xmlChar * 4683xmlSchemaGetNodeContentNoDict(xmlNodePtr node) 4684{ 4685 return((const xmlChar*) xmlNodeGetContent(node)); 4686} 4687 4688/** 4689 * xmlSchemaGetProp: 4690 * @ctxt: the parser context 4691 * @node: the node 4692 * @name: the property name 4693 * 4694 * Read a attribute value and internalize the string 4695 * 4696 * Returns the string or NULL if not present. 4697 */ 4698static const xmlChar * 4699xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, 4700 const char *name) 4701{ 4702 xmlChar *val; 4703 const xmlChar *ret; 4704 4705 val = xmlGetNoNsProp(node, BAD_CAST name); 4706 if (val == NULL) 4707 return(NULL); 4708 ret = xmlDictLookup(ctxt->dict, val, -1); 4709 xmlFree(val); 4710 return(ret); 4711} 4712 4713/************************************************************************ 4714 * * 4715 * Parsing functions * 4716 * * 4717 ************************************************************************/ 4718 4719#define WXS_FIND_GLOBAL_ITEM(slot) \ 4720 if (xmlStrEqual(nsName, schema->targetNamespace)) { \ 4721 ret = xmlHashLookup(schema->slot, name); \ 4722 if (ret != NULL) goto exit; \ 4723 } \ 4724 if (xmlHashSize(schema->schemasImports) > 1) { \ 4725 xmlSchemaImportPtr import; \ 4726 if (nsName == NULL) \ 4727 import = xmlHashLookup(schema->schemasImports, \ 4728 XML_SCHEMAS_NO_NAMESPACE); \ 4729 else \ 4730 import = xmlHashLookup(schema->schemasImports, nsName); \ 4731 if (import == NULL) \ 4732 goto exit; \ 4733 ret = xmlHashLookup(import->schema->slot, name); \ 4734 } 4735 4736/** 4737 * xmlSchemaGetElem: 4738 * @schema: the schema context 4739 * @name: the element name 4740 * @ns: the element namespace 4741 * 4742 * Lookup a global element declaration in the schema. 4743 * 4744 * Returns the element declaration or NULL if not found. 4745 */ 4746static xmlSchemaElementPtr 4747xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name, 4748 const xmlChar * nsName) 4749{ 4750 xmlSchemaElementPtr ret = NULL; 4751 4752 if ((name == NULL) || (schema == NULL)) 4753 return(NULL); 4754 if (schema != NULL) { 4755 WXS_FIND_GLOBAL_ITEM(elemDecl) 4756 } 4757exit: 4758#ifdef DEBUG 4759 if (ret == NULL) { 4760 if (nsName == NULL) 4761 fprintf(stderr, "Unable to lookup element decl. %s", name); 4762 else 4763 fprintf(stderr, "Unable to lookup element decl. %s:%s", name, 4764 nsName); 4765 } 4766#endif 4767 return (ret); 4768} 4769 4770/** 4771 * xmlSchemaGetType: 4772 * @schema: the main schema 4773 * @name: the type's name 4774 * nsName: the type's namespace 4775 * 4776 * Lookup a type in the schemas or the predefined types 4777 * 4778 * Returns the group definition or NULL if not found. 4779 */ 4780static xmlSchemaTypePtr 4781xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name, 4782 const xmlChar * nsName) 4783{ 4784 xmlSchemaTypePtr ret = NULL; 4785 4786 if (name == NULL) 4787 return (NULL); 4788 /* First try the built-in types. */ 4789 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) { 4790 ret = xmlSchemaGetPredefinedType(name, nsName); 4791 if (ret != NULL) 4792 goto exit; 4793 /* 4794 * Note that we try the parsed schemas as well here 4795 * since one might have parsed the S4S, which contain more 4796 * than the built-in types. 4797 * TODO: Can we optimize this? 4798 */ 4799 } 4800 if (schema != NULL) { 4801 WXS_FIND_GLOBAL_ITEM(typeDecl) 4802 } 4803exit: 4804 4805#ifdef DEBUG 4806 if (ret == NULL) { 4807 if (nsName == NULL) 4808 fprintf(stderr, "Unable to lookup type %s", name); 4809 else 4810 fprintf(stderr, "Unable to lookup type %s:%s", name, 4811 nsName); 4812 } 4813#endif 4814 return (ret); 4815} 4816 4817/** 4818 * xmlSchemaGetAttributeDecl: 4819 * @schema: the context of the schema 4820 * @name: the name of the attribute 4821 * @ns: the target namespace of the attribute 4822 * 4823 * Lookup a an attribute in the schema or imported schemas 4824 * 4825 * Returns the attribute declaration or NULL if not found. 4826 */ 4827static xmlSchemaAttributePtr 4828xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name, 4829 const xmlChar * nsName) 4830{ 4831 xmlSchemaAttributePtr ret = NULL; 4832 4833 if ((name == NULL) || (schema == NULL)) 4834 return (NULL); 4835 if (schema != NULL) { 4836 WXS_FIND_GLOBAL_ITEM(attrDecl) 4837 } 4838exit: 4839#ifdef DEBUG 4840 if (ret == NULL) { 4841 if (nsName == NULL) 4842 fprintf(stderr, "Unable to lookup attribute %s", name); 4843 else 4844 fprintf(stderr, "Unable to lookup attribute %s:%s", name, 4845 nsName); 4846 } 4847#endif 4848 return (ret); 4849} 4850 4851/** 4852 * xmlSchemaGetAttributeGroup: 4853 * @schema: the context of the schema 4854 * @name: the name of the attribute group 4855 * @ns: the target namespace of the attribute group 4856 * 4857 * Lookup a an attribute group in the schema or imported schemas 4858 * 4859 * Returns the attribute group definition or NULL if not found. 4860 */ 4861static xmlSchemaAttributeGroupPtr 4862xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name, 4863 const xmlChar * nsName) 4864{ 4865 xmlSchemaAttributeGroupPtr ret = NULL; 4866 4867 if ((name == NULL) || (schema == NULL)) 4868 return (NULL); 4869 if (schema != NULL) { 4870 WXS_FIND_GLOBAL_ITEM(attrgrpDecl) 4871 } 4872exit: 4873 /* TODO: 4874 if ((ret != NULL) && (ret->redef != NULL)) { 4875 * Return the last redefinition. * 4876 ret = ret->redef; 4877 } 4878 */ 4879#ifdef DEBUG 4880 if (ret == NULL) { 4881 if (nsName == NULL) 4882 fprintf(stderr, "Unable to lookup attribute group %s", name); 4883 else 4884 fprintf(stderr, "Unable to lookup attribute group %s:%s", name, 4885 nsName); 4886 } 4887#endif 4888 return (ret); 4889} 4890 4891/** 4892 * xmlSchemaGetGroup: 4893 * @schema: the context of the schema 4894 * @name: the name of the group 4895 * @ns: the target namespace of the group 4896 * 4897 * Lookup a group in the schema or imported schemas 4898 * 4899 * Returns the group definition or NULL if not found. 4900 */ 4901static xmlSchemaModelGroupDefPtr 4902xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name, 4903 const xmlChar * nsName) 4904{ 4905 xmlSchemaModelGroupDefPtr ret = NULL; 4906 4907 if ((name == NULL) || (schema == NULL)) 4908 return (NULL); 4909 if (schema != NULL) { 4910 WXS_FIND_GLOBAL_ITEM(groupDecl) 4911 } 4912exit: 4913 4914#ifdef DEBUG 4915 if (ret == NULL) { 4916 if (nsName == NULL) 4917 fprintf(stderr, "Unable to lookup group %s", name); 4918 else 4919 fprintf(stderr, "Unable to lookup group %s:%s", name, 4920 nsName); 4921 } 4922#endif 4923 return (ret); 4924} 4925 4926static xmlSchemaNotationPtr 4927xmlSchemaGetNotation(xmlSchemaPtr schema, 4928 const xmlChar *name, 4929 const xmlChar *nsName) 4930{ 4931 xmlSchemaNotationPtr ret = NULL; 4932 4933 if ((name == NULL) || (schema == NULL)) 4934 return (NULL); 4935 if (schema != NULL) { 4936 WXS_FIND_GLOBAL_ITEM(notaDecl) 4937 } 4938exit: 4939 return (ret); 4940} 4941 4942static xmlSchemaIDCPtr 4943xmlSchemaGetIDC(xmlSchemaPtr schema, 4944 const xmlChar *name, 4945 const xmlChar *nsName) 4946{ 4947 xmlSchemaIDCPtr ret = NULL; 4948 4949 if ((name == NULL) || (schema == NULL)) 4950 return (NULL); 4951 if (schema != NULL) { 4952 WXS_FIND_GLOBAL_ITEM(idcDef) 4953 } 4954exit: 4955 return (ret); 4956} 4957 4958/** 4959 * xmlSchemaGetNamedComponent: 4960 * @schema: the schema 4961 * @name: the name of the group 4962 * @ns: the target namespace of the group 4963 * 4964 * Lookup a group in the schema or imported schemas 4965 * 4966 * Returns the group definition or NULL if not found. 4967 */ 4968static xmlSchemaBasicItemPtr 4969xmlSchemaGetNamedComponent(xmlSchemaPtr schema, 4970 xmlSchemaTypeType itemType, 4971 const xmlChar *name, 4972 const xmlChar *targetNs) 4973{ 4974 switch (itemType) { 4975 case XML_SCHEMA_TYPE_GROUP: 4976 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema, 4977 name, targetNs)); 4978 case XML_SCHEMA_TYPE_ELEMENT: 4979 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema, 4980 name, targetNs)); 4981 default: 4982 TODO 4983 return (NULL); 4984 } 4985} 4986 4987/************************************************************************ 4988 * * 4989 * Parsing functions * 4990 * * 4991 ************************************************************************/ 4992 4993#define IS_BLANK_NODE(n) \ 4994 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1))) 4995 4996/** 4997 * xmlSchemaIsBlank: 4998 * @str: a string 4999 * @len: the length of the string or -1 5000 * 5001 * Check if a string is ignorable 5002 * 5003 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise 5004 */ 5005static int 5006xmlSchemaIsBlank(xmlChar * str, int len) 5007{ 5008 if (str == NULL) 5009 return (1); 5010 if (len < 0) { 5011 while (*str != 0) { 5012 if (!(IS_BLANK_CH(*str))) 5013 return (0); 5014 str++; 5015 } 5016 } else while ((*str != 0) && (len != 0)) { 5017 if (!(IS_BLANK_CH(*str))) 5018 return (0); 5019 str++; 5020 len--; 5021 } 5022 5023 return (1); 5024} 5025 5026#define WXS_COMP_NAME(c, t) ((t) (c))->name 5027#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace 5028/* 5029* xmlSchemaFindRedefCompInGraph: 5030* ATTENTION TODO: This uses pointer comp. for strings. 5031*/ 5032static xmlSchemaBasicItemPtr 5033xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket, 5034 xmlSchemaTypeType type, 5035 const xmlChar *name, 5036 const xmlChar *nsName) 5037{ 5038 xmlSchemaBasicItemPtr ret; 5039 int i; 5040 5041 if ((bucket == NULL) || (name == NULL)) 5042 return(NULL); 5043 if ((bucket->globals == NULL) || 5044 (bucket->globals->nbItems == 0)) 5045 goto subschemas; 5046 /* 5047 * Search in global components. 5048 */ 5049 for (i = 0; i < bucket->globals->nbItems; i++) { 5050 ret = bucket->globals->items[i]; 5051 if (ret->type == type) { 5052 switch (type) { 5053 case XML_SCHEMA_TYPE_COMPLEX: 5054 case XML_SCHEMA_TYPE_SIMPLE: 5055 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) && 5056 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) == 5057 nsName)) 5058 { 5059 return(ret); 5060 } 5061 break; 5062 case XML_SCHEMA_TYPE_GROUP: 5063 if ((WXS_COMP_NAME(ret, 5064 xmlSchemaModelGroupDefPtr) == name) && 5065 (WXS_COMP_TNS(ret, 5066 xmlSchemaModelGroupDefPtr) == nsName)) 5067 { 5068 return(ret); 5069 } 5070 break; 5071 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: 5072 if ((WXS_COMP_NAME(ret, 5073 xmlSchemaAttributeGroupPtr) == name) && 5074 (WXS_COMP_TNS(ret, 5075 xmlSchemaAttributeGroupPtr) == nsName)) 5076 { 5077 return(ret); 5078 } 5079 break; 5080 default: 5081 /* Should not be hit. */ 5082 return(NULL); 5083 } 5084 } 5085 } 5086subschemas: 5087 /* 5088 * Process imported/included schemas. 5089 */ 5090 if (bucket->relations != NULL) { 5091 xmlSchemaSchemaRelationPtr rel = bucket->relations; 5092 5093 /* 5094 * TODO: Marking the bucket will not avoid multiple searches 5095 * in the same schema, but avoids at least circularity. 5096 */ 5097 bucket->flags |= XML_SCHEMA_BUCKET_MARKED; 5098 do { 5099 if ((rel->bucket != NULL) && 5100 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) { 5101 ret = xmlSchemaFindRedefCompInGraph(rel->bucket, 5102 type, name, nsName); 5103 if (ret != NULL) 5104 return(ret); 5105 } 5106 rel = rel->next; 5107 } while (rel != NULL); 5108 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED; 5109 } 5110 return(NULL); 5111} 5112 5113/** 5114 * xmlSchemaAddNotation: 5115 * @ctxt: a schema parser context 5116 * @schema: the schema being built 5117 * @name: the item name 5118 * 5119 * Add an XML schema annotation declaration 5120 * *WARNING* this interface is highly subject to change 5121 * 5122 * Returns the new struture or NULL in case of error 5123 */ 5124static xmlSchemaNotationPtr 5125xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 5126 const xmlChar *name, const xmlChar *nsName, 5127 xmlNodePtr node ATTRIBUTE_UNUSED) 5128{ 5129 xmlSchemaNotationPtr ret = NULL; 5130 5131 if ((ctxt == NULL) || (schema == NULL) || (name == NULL)) 5132 return (NULL); 5133 5134 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation)); 5135 if (ret == NULL) { 5136 xmlSchemaPErrMemory(ctxt, "add annotation", NULL); 5137 return (NULL); 5138 } 5139 memset(ret, 0, sizeof(xmlSchemaNotation)); 5140 ret->type = XML_SCHEMA_TYPE_NOTATION; 5141 ret->name = name; 5142 ret->targetNamespace = nsName; 5143 /* TODO: do we need the node to be set? 5144 * ret->node = node;*/ 5145 WXS_ADD_GLOBAL(ctxt, ret); 5146 return (ret); 5147} 5148 5149/** 5150 * xmlSchemaAddAttribute: 5151 * @ctxt: a schema parser context 5152 * @schema: the schema being built 5153 * @name: the item name 5154 * @namespace: the namespace 5155 * 5156 * Add an XML schema Attrribute declaration 5157 * *WARNING* this interface is highly subject to change 5158 * 5159 * Returns the new struture or NULL in case of error 5160 */ 5161static xmlSchemaAttributePtr 5162xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 5163 const xmlChar * name, const xmlChar * nsName, 5164 xmlNodePtr node, int topLevel) 5165{ 5166 xmlSchemaAttributePtr ret = NULL; 5167 5168 if ((ctxt == NULL) || (schema == NULL)) 5169 return (NULL); 5170 5171 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute)); 5172 if (ret == NULL) { 5173 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL); 5174 return (NULL); 5175 } 5176 memset(ret, 0, sizeof(xmlSchemaAttribute)); 5177 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE; 5178 ret->node = node; 5179 ret->name = name; 5180 ret->targetNamespace = nsName; 5181 5182 if (topLevel) 5183 WXS_ADD_GLOBAL(ctxt, ret); 5184 else 5185 WXS_ADD_LOCAL(ctxt, ret); 5186 WXS_ADD_PENDING(ctxt, ret); 5187 return (ret); 5188} 5189 5190/** 5191 * xmlSchemaAddAttributeUse: 5192 * @ctxt: a schema parser context 5193 * @schema: the schema being built 5194 * @name: the item name 5195 * @namespace: the namespace 5196 * 5197 * Add an XML schema Attrribute declaration 5198 * *WARNING* this interface is highly subject to change 5199 * 5200 * Returns the new struture or NULL in case of error 5201 */ 5202static xmlSchemaAttributeUsePtr 5203xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt, 5204 xmlNodePtr node) 5205{ 5206 xmlSchemaAttributeUsePtr ret = NULL; 5207 5208 if (pctxt == NULL) 5209 return (NULL); 5210 5211 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse)); 5212 if (ret == NULL) { 5213 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL); 5214 return (NULL); 5215 } 5216 memset(ret, 0, sizeof(xmlSchemaAttributeUse)); 5217 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE; 5218 ret->node = node; 5219 5220 WXS_ADD_LOCAL(pctxt, ret); 5221 return (ret); 5222} 5223 5224/* 5225* xmlSchemaAddRedef: 5226* 5227* Adds a redefinition information. This is used at a later stage to: 5228* resolve references to the redefined components and to check constraints. 5229*/ 5230static xmlSchemaRedefPtr 5231xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt, 5232 xmlSchemaBucketPtr targetBucket, 5233 void *item, 5234 const xmlChar *refName, 5235 const xmlChar *refTargetNs) 5236{ 5237 xmlSchemaRedefPtr ret; 5238 5239 ret = (xmlSchemaRedefPtr) 5240 xmlMalloc(sizeof(xmlSchemaRedef)); 5241 if (ret == NULL) { 5242 xmlSchemaPErrMemory(pctxt, 5243 "allocating redefinition info", NULL); 5244 return (NULL); 5245 } 5246 memset(ret, 0, sizeof(xmlSchemaRedef)); 5247 ret->item = item; 5248 ret->targetBucket = targetBucket; 5249 ret->refName = refName; 5250 ret->refTargetNs = refTargetNs; 5251 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL) 5252 WXS_CONSTRUCTOR(pctxt)->redefs = ret; 5253 else 5254 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret; 5255 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret; 5256 5257 return (ret); 5258} 5259 5260/** 5261 * xmlSchemaAddAttributeGroupDefinition: 5262 * @ctxt: a schema parser context 5263 * @schema: the schema being built 5264 * @name: the item name 5265 * @nsName: the target namespace 5266 * @node: the corresponding node 5267 * 5268 * Add an XML schema Attrribute Group definition. 5269 * 5270 * Returns the new struture or NULL in case of error 5271 */ 5272static xmlSchemaAttributeGroupPtr 5273xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt, 5274 xmlSchemaPtr schema ATTRIBUTE_UNUSED, 5275 const xmlChar *name, 5276 const xmlChar *nsName, 5277 xmlNodePtr node) 5278{ 5279 xmlSchemaAttributeGroupPtr ret = NULL; 5280 5281 if ((pctxt == NULL) || (name == NULL)) 5282 return (NULL); 5283 5284 ret = (xmlSchemaAttributeGroupPtr) 5285 xmlMalloc(sizeof(xmlSchemaAttributeGroup)); 5286 if (ret == NULL) { 5287 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL); 5288 return (NULL); 5289 } 5290 memset(ret, 0, sizeof(xmlSchemaAttributeGroup)); 5291 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP; 5292 ret->name = name; 5293 ret->targetNamespace = nsName; 5294 ret->node = node; 5295 5296 /* TODO: Remove the flag. */ 5297 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL; 5298 if (pctxt->isRedefine) { 5299 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined, 5300 ret, name, nsName); 5301 if (pctxt->redef == NULL) { 5302 xmlFree(ret); 5303 return(NULL); 5304 } 5305 pctxt->redefCounter = 0; 5306 } 5307 WXS_ADD_GLOBAL(pctxt, ret); 5308 WXS_ADD_PENDING(pctxt, ret); 5309 return (ret); 5310} 5311 5312/** 5313 * xmlSchemaAddElement: 5314 * @ctxt: a schema parser context 5315 * @schema: the schema being built 5316 * @name: the type name 5317 * @namespace: the type namespace 5318 * 5319 * Add an XML schema Element declaration 5320 * *WARNING* this interface is highly subject to change 5321 * 5322 * Returns the new struture or NULL in case of error 5323 */ 5324static xmlSchemaElementPtr 5325xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, 5326 const xmlChar * name, const xmlChar * nsName, 5327 xmlNodePtr node, int topLevel) 5328{ 5329 xmlSchemaElementPtr ret = NULL; 5330 5331 if ((ctxt == NULL) || (name == NULL)) 5332 return (NULL); 5333 5334 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement)); 5335 if (ret == NULL) { 5336 xmlSchemaPErrMemory(ctxt, "allocating element", NULL); 5337 return (NULL); 5338 } 5339 memset(ret, 0, sizeof(xmlSchemaElement)); 5340 ret->type = XML_SCHEMA_TYPE_ELEMENT; 5341 ret->name = name; 5342 ret->targetNamespace = nsName; 5343 ret->node = node; 5344 5345 if (topLevel) 5346 WXS_ADD_GLOBAL(ctxt, ret); 5347 else 5348 WXS_ADD_LOCAL(ctxt, ret); 5349 WXS_ADD_PENDING(ctxt, ret); 5350 return (ret); 5351} 5352 5353/** 5354 * xmlSchemaAddType: 5355 * @ctxt: a schema parser context 5356 * @schema: the schema being built 5357 * @name: the item name 5358 * @namespace: the namespace 5359 * 5360 * Add an XML schema item 5361 * *WARNING* this interface is highly subject to change 5362 * 5363 * Returns the new struture or NULL in case of error 5364 */ 5365static xmlSchemaTypePtr 5366xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 5367 xmlSchemaTypeType type, 5368 const xmlChar * name, const xmlChar * nsName, 5369 xmlNodePtr node, int topLevel) 5370{ 5371 xmlSchemaTypePtr ret = NULL; 5372 5373 if ((ctxt == NULL) || (schema == NULL)) 5374 return (NULL); 5375 5376 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType)); 5377 if (ret == NULL) { 5378 xmlSchemaPErrMemory(ctxt, "allocating type", NULL); 5379 return (NULL); 5380 } 5381 memset(ret, 0, sizeof(xmlSchemaType)); 5382 ret->type = type; 5383 ret->name = name; 5384 ret->targetNamespace = nsName; 5385 ret->node = node; 5386 if (topLevel) { 5387 if (ctxt->isRedefine) { 5388 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined, 5389 ret, name, nsName); 5390 if (ctxt->redef == NULL) { 5391 xmlFree(ret); 5392 return(NULL); 5393 } 5394 ctxt->redefCounter = 0; 5395 } 5396 WXS_ADD_GLOBAL(ctxt, ret); 5397 } else 5398 WXS_ADD_LOCAL(ctxt, ret); 5399 WXS_ADD_PENDING(ctxt, ret); 5400 return (ret); 5401} 5402 5403static xmlSchemaQNameRefPtr 5404xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt, 5405 xmlSchemaTypeType refType, 5406 const xmlChar *refName, 5407 const xmlChar *refNs) 5408{ 5409 xmlSchemaQNameRefPtr ret; 5410 5411 ret = (xmlSchemaQNameRefPtr) 5412 xmlMalloc(sizeof(xmlSchemaQNameRef)); 5413 if (ret == NULL) { 5414 xmlSchemaPErrMemory(pctxt, 5415 "allocating QName reference item", NULL); 5416 return (NULL); 5417 } 5418 ret->node = NULL; 5419 ret->type = XML_SCHEMA_EXTRA_QNAMEREF; 5420 ret->name = refName; 5421 ret->targetNamespace = refNs; 5422 ret->item = NULL; 5423 ret->itemType = refType; 5424 /* 5425 * Store the reference item in the schema. 5426 */ 5427 WXS_ADD_LOCAL(pctxt, ret); 5428 return (ret); 5429} 5430 5431static xmlSchemaAttributeUseProhibPtr 5432xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt) 5433{ 5434 xmlSchemaAttributeUseProhibPtr ret; 5435 5436 ret = (xmlSchemaAttributeUseProhibPtr) 5437 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib)); 5438 if (ret == NULL) { 5439 xmlSchemaPErrMemory(pctxt, 5440 "allocating attribute use prohibition", NULL); 5441 return (NULL); 5442 } 5443 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib)); 5444 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB; 5445 WXS_ADD_LOCAL(pctxt, ret); 5446 return (ret); 5447} 5448 5449 5450/** 5451 * xmlSchemaAddModelGroup: 5452 * @ctxt: a schema parser context 5453 * @schema: the schema being built 5454 * @type: the "compositor" type of the model group 5455 * @node: the node in the schema doc 5456 * 5457 * Adds a schema model group 5458 * *WARNING* this interface is highly subject to change 5459 * 5460 * Returns the new struture or NULL in case of error 5461 */ 5462static xmlSchemaModelGroupPtr 5463xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, 5464 xmlSchemaPtr schema, 5465 xmlSchemaTypeType type, 5466 xmlNodePtr node) 5467{ 5468 xmlSchemaModelGroupPtr ret = NULL; 5469 5470 if ((ctxt == NULL) || (schema == NULL)) 5471 return (NULL); 5472 5473 ret = (xmlSchemaModelGroupPtr) 5474 xmlMalloc(sizeof(xmlSchemaModelGroup)); 5475 if (ret == NULL) { 5476 xmlSchemaPErrMemory(ctxt, "allocating model group component", 5477 NULL); 5478 return (NULL); 5479 } 5480 memset(ret, 0, sizeof(xmlSchemaModelGroup)); 5481 ret->type = type; 5482 ret->node = node; 5483 WXS_ADD_LOCAL(ctxt, ret); 5484 if ((type == XML_SCHEMA_TYPE_SEQUENCE) || 5485 (type == XML_SCHEMA_TYPE_CHOICE)) 5486 WXS_ADD_PENDING(ctxt, ret); 5487 return (ret); 5488} 5489 5490 5491/** 5492 * xmlSchemaAddParticle: 5493 * @ctxt: a schema parser context 5494 * @schema: the schema being built 5495 * @node: the corresponding node in the schema doc 5496 * @min: the minOccurs 5497 * @max: the maxOccurs 5498 * 5499 * Adds an XML schema particle component. 5500 * *WARNING* this interface is highly subject to change 5501 * 5502 * Returns the new struture or NULL in case of error 5503 */ 5504static xmlSchemaParticlePtr 5505xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, 5506 xmlNodePtr node, int min, int max) 5507{ 5508 xmlSchemaParticlePtr ret = NULL; 5509 if (ctxt == NULL) 5510 return (NULL); 5511 5512#ifdef DEBUG 5513 fprintf(stderr, "Adding particle component\n"); 5514#endif 5515 ret = (xmlSchemaParticlePtr) 5516 xmlMalloc(sizeof(xmlSchemaParticle)); 5517 if (ret == NULL) { 5518 xmlSchemaPErrMemory(ctxt, "allocating particle component", 5519 NULL); 5520 return (NULL); 5521 } 5522 ret->type = XML_SCHEMA_TYPE_PARTICLE; 5523 ret->annot = NULL; 5524 ret->node = node; 5525 ret->minOccurs = min; 5526 ret->maxOccurs = max; 5527 ret->next = NULL; 5528 ret->children = NULL; 5529 5530 WXS_ADD_LOCAL(ctxt, ret); 5531 /* 5532 * Note that addition to pending components will be done locally 5533 * to the specific parsing function, since the most particles 5534 * need not to be fixed up (i.e. the reference to be resolved). 5535 * REMOVED: WXS_ADD_PENDING(ctxt, ret); 5536 */ 5537 return (ret); 5538} 5539 5540/** 5541 * xmlSchemaAddModelGroupDefinition: 5542 * @ctxt: a schema validation context 5543 * @schema: the schema being built 5544 * @name: the group name 5545 * 5546 * Add an XML schema Group definition 5547 * 5548 * Returns the new struture or NULL in case of error 5549 */ 5550static xmlSchemaModelGroupDefPtr 5551xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt, 5552 xmlSchemaPtr schema, 5553 const xmlChar *name, 5554 const xmlChar *nsName, 5555 xmlNodePtr node) 5556{ 5557 xmlSchemaModelGroupDefPtr ret = NULL; 5558 5559 if ((ctxt == NULL) || (schema == NULL) || (name == NULL)) 5560 return (NULL); 5561 5562 ret = (xmlSchemaModelGroupDefPtr) 5563 xmlMalloc(sizeof(xmlSchemaModelGroupDef)); 5564 if (ret == NULL) { 5565 xmlSchemaPErrMemory(ctxt, "adding group", NULL); 5566 return (NULL); 5567 } 5568 memset(ret, 0, sizeof(xmlSchemaModelGroupDef)); 5569 ret->name = name; 5570 ret->type = XML_SCHEMA_TYPE_GROUP; 5571 ret->node = node; 5572 ret->targetNamespace = nsName; 5573 5574 if (ctxt->isRedefine) { 5575 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined, 5576 ret, name, nsName); 5577 if (ctxt->redef == NULL) { 5578 xmlFree(ret); 5579 return(NULL); 5580 } 5581 ctxt->redefCounter = 0; 5582 } 5583 WXS_ADD_GLOBAL(ctxt, ret); 5584 WXS_ADD_PENDING(ctxt, ret); 5585 return (ret); 5586} 5587 5588/** 5589 * xmlSchemaNewWildcardNs: 5590 * @ctxt: a schema validation context 5591 * 5592 * Creates a new wildcard namespace constraint. 5593 * 5594 * Returns the new struture or NULL in case of error 5595 */ 5596static xmlSchemaWildcardNsPtr 5597xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt) 5598{ 5599 xmlSchemaWildcardNsPtr ret; 5600 5601 ret = (xmlSchemaWildcardNsPtr) 5602 xmlMalloc(sizeof(xmlSchemaWildcardNs)); 5603 if (ret == NULL) { 5604 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL); 5605 return (NULL); 5606 } 5607 ret->value = NULL; 5608 ret->next = NULL; 5609 return (ret); 5610} 5611 5612static xmlSchemaIDCPtr 5613xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 5614 const xmlChar *name, const xmlChar *nsName, 5615 int category, xmlNodePtr node) 5616{ 5617 xmlSchemaIDCPtr ret = NULL; 5618 5619 if ((ctxt == NULL) || (schema == NULL) || (name == NULL)) 5620 return (NULL); 5621 5622 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC)); 5623 if (ret == NULL) { 5624 xmlSchemaPErrMemory(ctxt, 5625 "allocating an identity-constraint definition", NULL); 5626 return (NULL); 5627 } 5628 memset(ret, 0, sizeof(xmlSchemaIDC)); 5629 /* The target namespace of the parent element declaration. */ 5630 ret->targetNamespace = nsName; 5631 ret->name = name; 5632 ret->type = category; 5633 ret->node = node; 5634 5635 WXS_ADD_GLOBAL(ctxt, ret); 5636 /* 5637 * Only keyrefs need to be fixup up. 5638 */ 5639 if (category == XML_SCHEMA_TYPE_IDC_KEYREF) 5640 WXS_ADD_PENDING(ctxt, ret); 5641 return (ret); 5642} 5643 5644/** 5645 * xmlSchemaAddWildcard: 5646 * @ctxt: a schema validation context 5647 * @schema: a schema 5648 * 5649 * Adds a wildcard. 5650 * It corresponds to a xsd:anyAttribute and xsd:any. 5651 * 5652 * Returns the new struture or NULL in case of error 5653 */ 5654static xmlSchemaWildcardPtr 5655xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 5656 xmlSchemaTypeType type, xmlNodePtr node) 5657{ 5658 xmlSchemaWildcardPtr ret = NULL; 5659 5660 if ((ctxt == NULL) || (schema == NULL)) 5661 return (NULL); 5662 5663 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard)); 5664 if (ret == NULL) { 5665 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL); 5666 return (NULL); 5667 } 5668 memset(ret, 0, sizeof(xmlSchemaWildcard)); 5669 ret->type = type; 5670 ret->node = node; 5671 WXS_ADD_LOCAL(ctxt, ret); 5672 return (ret); 5673} 5674 5675static void 5676xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group) 5677{ 5678 if (group == NULL) 5679 return; 5680 if (group->members != NULL) 5681 xmlSchemaItemListFree(group->members); 5682 xmlFree(group); 5683} 5684 5685static xmlSchemaSubstGroupPtr 5686xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt, 5687 xmlSchemaElementPtr head) 5688{ 5689 xmlSchemaSubstGroupPtr ret; 5690 5691 /* Init subst group hash. */ 5692 if (WXS_SUBST_GROUPS(pctxt) == NULL) { 5693 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict); 5694 if (WXS_SUBST_GROUPS(pctxt) == NULL) 5695 return(NULL); 5696 } 5697 /* Create a new substitution group. */ 5698 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup)); 5699 if (ret == NULL) { 5700 xmlSchemaPErrMemory(NULL, 5701 "allocating a substitution group container", NULL); 5702 return(NULL); 5703 } 5704 memset(ret, 0, sizeof(xmlSchemaSubstGroup)); 5705 ret->head = head; 5706 /* Create list of members. */ 5707 ret->members = xmlSchemaItemListCreate(); 5708 if (ret->members == NULL) { 5709 xmlSchemaSubstGroupFree(ret); 5710 return(NULL); 5711 } 5712 /* Add subst group to hash. */ 5713 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt), 5714 head->name, head->targetNamespace, ret) != 0) { 5715 PERROR_INT("xmlSchemaSubstGroupAdd", 5716 "failed to add a new substitution container"); 5717 xmlSchemaSubstGroupFree(ret); 5718 return(NULL); 5719 } 5720 return(ret); 5721} 5722 5723static xmlSchemaSubstGroupPtr 5724xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt, 5725 xmlSchemaElementPtr head) 5726{ 5727 if (WXS_SUBST_GROUPS(pctxt) == NULL) 5728 return(NULL); 5729 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt), 5730 head->name, head->targetNamespace)); 5731 5732} 5733 5734/** 5735 * xmlSchemaAddElementSubstitutionMember: 5736 * @pctxt: a schema parser context 5737 * @head: the head of the substitution group 5738 * @member: the new member of the substitution group 5739 * 5740 * Allocate a new annotation structure. 5741 * 5742 * Returns the newly allocated structure or NULL in case or error 5743 */ 5744static int 5745xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt, 5746 xmlSchemaElementPtr head, 5747 xmlSchemaElementPtr member) 5748{ 5749 xmlSchemaSubstGroupPtr substGroup = NULL; 5750 5751 if ((pctxt == NULL) || (head == NULL) || (member == NULL)) 5752 return (-1); 5753 5754 substGroup = xmlSchemaSubstGroupGet(pctxt, head); 5755 if (substGroup == NULL) 5756 substGroup = xmlSchemaSubstGroupAdd(pctxt, head); 5757 if (substGroup == NULL) 5758 return(-1); 5759 if (xmlSchemaItemListAdd(substGroup->members, member) == -1) 5760 return(-1); 5761 return(0); 5762} 5763 5764/************************************************************************ 5765 * * 5766 * Utilities for parsing * 5767 * * 5768 ************************************************************************/ 5769 5770/** 5771 * xmlSchemaPValAttrNodeQNameValue: 5772 * @ctxt: a schema parser context 5773 * @schema: the schema context 5774 * @ownerDes: the designation of the parent element 5775 * @ownerItem: the parent as a schema object 5776 * @value: the QName value 5777 * @local: the resulting local part if found, the attribute value otherwise 5778 * @uri: the resulting namespace URI if found 5779 * 5780 * Extracts the local name and the URI of a QName value and validates it. 5781 * This one is intended to be used on attribute values that 5782 * should resolve to schema components. 5783 * 5784 * Returns 0, in case the QName is valid, a positive error code 5785 * if not valid and -1 if an internal error occurs. 5786 */ 5787static int 5788xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt, 5789 xmlSchemaPtr schema, 5790 xmlSchemaBasicItemPtr ownerItem, 5791 xmlAttrPtr attr, 5792 const xmlChar *value, 5793 const xmlChar **uri, 5794 const xmlChar **local) 5795{ 5796 const xmlChar *pref; 5797 xmlNsPtr ns; 5798 int len, ret; 5799 5800 *uri = NULL; 5801 *local = NULL; 5802 ret = xmlValidateQName(value, 1); 5803 if (ret > 0) { 5804 xmlSchemaPSimpleTypeErr(ctxt, 5805 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 5806 ownerItem, (xmlNodePtr) attr, 5807 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 5808 NULL, value, NULL, NULL, NULL); 5809 *local = value; 5810 return (ctxt->err); 5811 } else if (ret < 0) 5812 return (-1); 5813 5814 if (!strchr((char *) value, ':')) { 5815 ns = xmlSearchNs(attr->doc, attr->parent, NULL); 5816 if (ns) 5817 *uri = xmlDictLookup(ctxt->dict, ns->href, -1); 5818 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) { 5819 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the 5820 * parser context. */ 5821 /* 5822 * This one takes care of included schemas with no 5823 * target namespace. 5824 */ 5825 *uri = ctxt->targetNamespace; 5826 } 5827 *local = xmlDictLookup(ctxt->dict, value, -1); 5828 return (0); 5829 } 5830 /* 5831 * At this point xmlSplitQName3 has to return a local name. 5832 */ 5833 *local = xmlSplitQName3(value, &len); 5834 *local = xmlDictLookup(ctxt->dict, *local, -1); 5835 pref = xmlDictLookup(ctxt->dict, value, len); 5836 ns = xmlSearchNs(attr->doc, attr->parent, pref); 5837 if (ns == NULL) { 5838 xmlSchemaPSimpleTypeErr(ctxt, 5839 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 5840 ownerItem, (xmlNodePtr) attr, 5841 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value, 5842 "The value '%s' of simple type 'xs:QName' has no " 5843 "corresponding namespace declaration in scope", value, NULL); 5844 return (ctxt->err); 5845 } else { 5846 *uri = xmlDictLookup(ctxt->dict, ns->href, -1); 5847 } 5848 return (0); 5849} 5850 5851/** 5852 * xmlSchemaPValAttrNodeQName: 5853 * @ctxt: a schema parser context 5854 * @schema: the schema context 5855 * @ownerDes: the designation of the owner element 5856 * @ownerItem: the owner as a schema object 5857 * @attr: the attribute node 5858 * @local: the resulting local part if found, the attribute value otherwise 5859 * @uri: the resulting namespace URI if found 5860 * 5861 * Extracts and validates the QName of an attribute value. 5862 * This one is intended to be used on attribute values that 5863 * should resolve to schema components. 5864 * 5865 * Returns 0, in case the QName is valid, a positive error code 5866 * if not valid and -1 if an internal error occurs. 5867 */ 5868static int 5869xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt, 5870 xmlSchemaPtr schema, 5871 xmlSchemaBasicItemPtr ownerItem, 5872 xmlAttrPtr attr, 5873 const xmlChar **uri, 5874 const xmlChar **local) 5875{ 5876 const xmlChar *value; 5877 5878 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 5879 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, 5880 ownerItem, attr, value, uri, local)); 5881} 5882 5883/** 5884 * xmlSchemaPValAttrQName: 5885 * @ctxt: a schema parser context 5886 * @schema: the schema context 5887 * @ownerDes: the designation of the parent element 5888 * @ownerItem: the owner as a schema object 5889 * @ownerElem: the parent node of the attribute 5890 * @name: the name of the attribute 5891 * @local: the resulting local part if found, the attribute value otherwise 5892 * @uri: the resulting namespace URI if found 5893 * 5894 * Extracts and validates the QName of an attribute value. 5895 * 5896 * Returns 0, in case the QName is valid, a positive error code 5897 * if not valid and -1 if an internal error occurs. 5898 */ 5899static int 5900xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt, 5901 xmlSchemaPtr schema, 5902 xmlSchemaBasicItemPtr ownerItem, 5903 xmlNodePtr ownerElem, 5904 const char *name, 5905 const xmlChar **uri, 5906 const xmlChar **local) 5907{ 5908 xmlAttrPtr attr; 5909 5910 attr = xmlSchemaGetPropNode(ownerElem, name); 5911 if (attr == NULL) { 5912 *local = NULL; 5913 *uri = NULL; 5914 return (0); 5915 } 5916 return (xmlSchemaPValAttrNodeQName(ctxt, schema, 5917 ownerItem, attr, uri, local)); 5918} 5919 5920/** 5921 * xmlSchemaPValAttrID: 5922 * @ctxt: a schema parser context 5923 * @schema: the schema context 5924 * @ownerDes: the designation of the parent element 5925 * @ownerItem: the owner as a schema object 5926 * @ownerElem: the parent node of the attribute 5927 * @name: the name of the attribute 5928 * 5929 * Extracts and validates the ID of an attribute value. 5930 * 5931 * Returns 0, in case the ID is valid, a positive error code 5932 * if not valid and -1 if an internal error occurs. 5933 */ 5934static int 5935xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr) 5936{ 5937 int ret; 5938 const xmlChar *value; 5939 5940 if (attr == NULL) 5941 return(0); 5942 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr); 5943 ret = xmlValidateNCName(value, 1); 5944 if (ret == 0) { 5945 /* 5946 * NOTE: the IDness might have already be declared in the DTD 5947 */ 5948 if (attr->atype != XML_ATTRIBUTE_ID) { 5949 xmlIDPtr res; 5950 xmlChar *strip; 5951 5952 /* 5953 * TODO: Use xmlSchemaStrip here; it's not exported at this 5954 * moment. 5955 */ 5956 strip = xmlSchemaCollapseString(value); 5957 if (strip != NULL) { 5958 xmlFree((xmlChar *) value); 5959 value = strip; 5960 } 5961 res = xmlAddID(NULL, attr->doc, value, attr); 5962 if (res == NULL) { 5963 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; 5964 xmlSchemaPSimpleTypeErr(ctxt, 5965 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 5966 NULL, (xmlNodePtr) attr, 5967 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID), 5968 NULL, NULL, "Duplicate value '%s' of simple " 5969 "type 'xs:ID'", value, NULL); 5970 } else 5971 attr->atype = XML_ATTRIBUTE_ID; 5972 } 5973 } else if (ret > 0) { 5974 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; 5975 xmlSchemaPSimpleTypeErr(ctxt, 5976 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 5977 NULL, (xmlNodePtr) attr, 5978 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID), 5979 NULL, NULL, "The value '%s' of simple type 'xs:ID' is " 5980 "not a valid 'xs:NCName'", 5981 value, NULL); 5982 } 5983 if (value != NULL) 5984 xmlFree((xmlChar *)value); 5985 5986 return (ret); 5987} 5988 5989static int 5990xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt, 5991 xmlNodePtr ownerElem, 5992 const xmlChar *name) 5993{ 5994 xmlAttrPtr attr; 5995 5996 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name); 5997 if (attr == NULL) 5998 return(0); 5999 return(xmlSchemaPValAttrNodeID(ctxt, attr)); 6000 6001} 6002 6003/** 6004 * xmlGetMaxOccurs: 6005 * @ctxt: a schema validation context 6006 * @node: a subtree containing XML Schema informations 6007 * 6008 * Get the maxOccurs property 6009 * 6010 * Returns the default if not found, or the value 6011 */ 6012static int 6013xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, 6014 int min, int max, int def, const char *expected) 6015{ 6016 const xmlChar *val, *cur; 6017 int ret = 0; 6018 xmlAttrPtr attr; 6019 6020 attr = xmlSchemaGetPropNode(node, "maxOccurs"); 6021 if (attr == NULL) 6022 return (def); 6023 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 6024 6025 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) { 6026 if (max != UNBOUNDED) { 6027 xmlSchemaPSimpleTypeErr(ctxt, 6028 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 6029 /* XML_SCHEMAP_INVALID_MINOCCURS, */ 6030 NULL, (xmlNodePtr) attr, NULL, expected, 6031 val, NULL, NULL, NULL); 6032 return (def); 6033 } else 6034 return (UNBOUNDED); /* encoding it with -1 might be another option */ 6035 } 6036 6037 cur = val; 6038 while (IS_BLANK_CH(*cur)) 6039 cur++; 6040 if (*cur == 0) { 6041 xmlSchemaPSimpleTypeErr(ctxt, 6042 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 6043 /* XML_SCHEMAP_INVALID_MINOCCURS, */ 6044 NULL, (xmlNodePtr) attr, NULL, expected, 6045 val, NULL, NULL, NULL); 6046 return (def); 6047 } 6048 while ((*cur >= '0') && (*cur <= '9')) { 6049 ret = ret * 10 + (*cur - '0'); 6050 cur++; 6051 } 6052 while (IS_BLANK_CH(*cur)) 6053 cur++; 6054 /* 6055 * TODO: Restrict the maximal value to Integer. 6056 */ 6057 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) { 6058 xmlSchemaPSimpleTypeErr(ctxt, 6059 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 6060 /* XML_SCHEMAP_INVALID_MINOCCURS, */ 6061 NULL, (xmlNodePtr) attr, NULL, expected, 6062 val, NULL, NULL, NULL); 6063 return (def); 6064 } 6065 return (ret); 6066} 6067 6068/** 6069 * xmlGetMinOccurs: 6070 * @ctxt: a schema validation context 6071 * @node: a subtree containing XML Schema informations 6072 * 6073 * Get the minOccurs property 6074 * 6075 * Returns the default if not found, or the value 6076 */ 6077static int 6078xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, 6079 int min, int max, int def, const char *expected) 6080{ 6081 const xmlChar *val, *cur; 6082 int ret = 0; 6083 xmlAttrPtr attr; 6084 6085 attr = xmlSchemaGetPropNode(node, "minOccurs"); 6086 if (attr == NULL) 6087 return (def); 6088 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 6089 cur = val; 6090 while (IS_BLANK_CH(*cur)) 6091 cur++; 6092 if (*cur == 0) { 6093 xmlSchemaPSimpleTypeErr(ctxt, 6094 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 6095 /* XML_SCHEMAP_INVALID_MINOCCURS, */ 6096 NULL, (xmlNodePtr) attr, NULL, expected, 6097 val, NULL, NULL, NULL); 6098 return (def); 6099 } 6100 while ((*cur >= '0') && (*cur <= '9')) { 6101 ret = ret * 10 + (*cur - '0'); 6102 cur++; 6103 } 6104 while (IS_BLANK_CH(*cur)) 6105 cur++; 6106 /* 6107 * TODO: Restrict the maximal value to Integer. 6108 */ 6109 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) { 6110 xmlSchemaPSimpleTypeErr(ctxt, 6111 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 6112 /* XML_SCHEMAP_INVALID_MINOCCURS, */ 6113 NULL, (xmlNodePtr) attr, NULL, expected, 6114 val, NULL, NULL, NULL); 6115 return (def); 6116 } 6117 return (ret); 6118} 6119 6120/** 6121 * xmlSchemaPGetBoolNodeValue: 6122 * @ctxt: a schema validation context 6123 * @ownerDes: owner designation 6124 * @ownerItem: the owner as a schema item 6125 * @node: the node holding the value 6126 * 6127 * Converts a boolean string value into 1 or 0. 6128 * 6129 * Returns 0 or 1. 6130 */ 6131static int 6132xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt, 6133 xmlSchemaBasicItemPtr ownerItem, 6134 xmlNodePtr node) 6135{ 6136 xmlChar *value = NULL; 6137 int res = 0; 6138 6139 value = xmlNodeGetContent(node); 6140 /* 6141 * 3.2.2.1 Lexical representation 6142 * An instance of a datatype that is defined as �boolean� 6143 * can have the following legal literals {true, false, 1, 0}. 6144 */ 6145 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true")) 6146 res = 1; 6147 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false")) 6148 res = 0; 6149 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1")) 6150 res = 1; 6151 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0")) 6152 res = 0; 6153 else { 6154 xmlSchemaPSimpleTypeErr(ctxt, 6155 XML_SCHEMAP_INVALID_BOOLEAN, 6156 ownerItem, node, 6157 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN), 6158 NULL, BAD_CAST value, 6159 NULL, NULL, NULL); 6160 } 6161 if (value != NULL) 6162 xmlFree(value); 6163 return (res); 6164} 6165 6166/** 6167 * xmlGetBooleanProp: 6168 * @ctxt: a schema validation context 6169 * @node: a subtree containing XML Schema informations 6170 * @name: the attribute name 6171 * @def: the default value 6172 * 6173 * Evaluate if a boolean property is set 6174 * 6175 * Returns the default if not found, 0 if found to be false, 6176 * 1 if found to be true 6177 */ 6178static int 6179xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, 6180 xmlNodePtr node, 6181 const char *name, int def) 6182{ 6183 const xmlChar *val; 6184 6185 val = xmlSchemaGetProp(ctxt, node, name); 6186 if (val == NULL) 6187 return (def); 6188 /* 6189 * 3.2.2.1 Lexical representation 6190 * An instance of a datatype that is defined as �boolean� 6191 * can have the following legal literals {true, false, 1, 0}. 6192 */ 6193 if (xmlStrEqual(val, BAD_CAST "true")) 6194 def = 1; 6195 else if (xmlStrEqual(val, BAD_CAST "false")) 6196 def = 0; 6197 else if (xmlStrEqual(val, BAD_CAST "1")) 6198 def = 1; 6199 else if (xmlStrEqual(val, BAD_CAST "0")) 6200 def = 0; 6201 else { 6202 xmlSchemaPSimpleTypeErr(ctxt, 6203 XML_SCHEMAP_INVALID_BOOLEAN, 6204 NULL, 6205 (xmlNodePtr) xmlSchemaGetPropNode(node, name), 6206 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN), 6207 NULL, val, NULL, NULL, NULL); 6208 } 6209 return (def); 6210} 6211 6212/************************************************************************ 6213 * * 6214 * Shema extraction from an Infoset * 6215 * * 6216 ************************************************************************/ 6217static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr 6218 ctxt, xmlSchemaPtr schema, 6219 xmlNodePtr node, 6220 int topLevel); 6221static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr 6222 ctxt, 6223 xmlSchemaPtr schema, 6224 xmlNodePtr node, 6225 int topLevel); 6226static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr 6227 ctxt, 6228 xmlSchemaPtr schema, 6229 xmlNodePtr node, 6230 xmlSchemaTypeType parentType); 6231static xmlSchemaBasicItemPtr 6232xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt, 6233 xmlSchemaPtr schema, 6234 xmlNodePtr node, 6235 xmlSchemaItemListPtr uses, 6236 int parentType); 6237static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, 6238 xmlSchemaPtr schema, 6239 xmlNodePtr node); 6240static xmlSchemaWildcardPtr 6241xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, 6242 xmlSchemaPtr schema, xmlNodePtr node); 6243 6244/** 6245 * xmlSchemaPValAttrNodeValue: 6246 * 6247 * @ctxt: a schema parser context 6248 * @ownerDes: the designation of the parent element 6249 * @ownerItem: the schema object owner if existent 6250 * @attr: the schema attribute node being validated 6251 * @value: the value 6252 * @type: the built-in type to be validated against 6253 * 6254 * Validates a value against the given built-in type. 6255 * This one is intended to be used internally for validation 6256 * of schema attribute values during parsing of the schema. 6257 * 6258 * Returns 0 if the value is valid, a positive error code 6259 * number otherwise and -1 in case of an internal or API error. 6260 */ 6261static int 6262xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt, 6263 xmlSchemaBasicItemPtr ownerItem, 6264 xmlAttrPtr attr, 6265 const xmlChar *value, 6266 xmlSchemaTypePtr type) 6267{ 6268 6269 int ret = 0; 6270 6271 /* 6272 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this 6273 * one is really meant to be used internally, so better not. 6274 */ 6275 if ((pctxt == NULL) || (type == NULL) || (attr == NULL)) 6276 return (-1); 6277 if (type->type != XML_SCHEMA_TYPE_BASIC) { 6278 PERROR_INT("xmlSchemaPValAttrNodeValue", 6279 "the given type is not a built-in type"); 6280 return (-1); 6281 } 6282 switch (type->builtInType) { 6283 case XML_SCHEMAS_NCNAME: 6284 case XML_SCHEMAS_QNAME: 6285 case XML_SCHEMAS_ANYURI: 6286 case XML_SCHEMAS_TOKEN: 6287 case XML_SCHEMAS_LANGUAGE: 6288 ret = xmlSchemaValPredefTypeNode(type, value, NULL, 6289 (xmlNodePtr) attr); 6290 break; 6291 default: { 6292 PERROR_INT("xmlSchemaPValAttrNodeValue", 6293 "validation using the given type is not supported while " 6294 "parsing a schema"); 6295 return (-1); 6296 } 6297 } 6298 /* 6299 * TODO: Should we use the S4S error codes instead? 6300 */ 6301 if (ret < 0) { 6302 PERROR_INT("xmlSchemaPValAttrNodeValue", 6303 "failed to validate a schema attribute value"); 6304 return (-1); 6305 } else if (ret > 0) { 6306 if (WXS_IS_LIST(type)) 6307 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; 6308 else 6309 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; 6310 xmlSchemaPSimpleTypeErr(pctxt, 6311 ret, ownerItem, (xmlNodePtr) attr, 6312 type, NULL, value, NULL, NULL, NULL); 6313 } 6314 return (ret); 6315} 6316 6317/** 6318 * xmlSchemaPValAttrNode: 6319 * 6320 * @ctxt: a schema parser context 6321 * @ownerDes: the designation of the parent element 6322 * @ownerItem: the schema object owner if existent 6323 * @attr: the schema attribute node being validated 6324 * @type: the built-in type to be validated against 6325 * @value: the resulting value if any 6326 * 6327 * Extracts and validates a value against the given built-in type. 6328 * This one is intended to be used internally for validation 6329 * of schema attribute values during parsing of the schema. 6330 * 6331 * Returns 0 if the value is valid, a positive error code 6332 * number otherwise and -1 in case of an internal or API error. 6333 */ 6334static int 6335xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt, 6336 xmlSchemaBasicItemPtr ownerItem, 6337 xmlAttrPtr attr, 6338 xmlSchemaTypePtr type, 6339 const xmlChar **value) 6340{ 6341 const xmlChar *val; 6342 6343 if ((ctxt == NULL) || (type == NULL) || (attr == NULL)) 6344 return (-1); 6345 6346 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 6347 if (value != NULL) 6348 *value = val; 6349 6350 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr, 6351 val, type)); 6352} 6353 6354/** 6355 * xmlSchemaPValAttr: 6356 * 6357 * @ctxt: a schema parser context 6358 * @node: the element node of the attribute 6359 * @ownerDes: the designation of the parent element 6360 * @ownerItem: the schema object owner if existent 6361 * @ownerElem: the owner element node 6362 * @name: the name of the schema attribute node 6363 * @type: the built-in type to be validated against 6364 * @value: the resulting value if any 6365 * 6366 * Extracts and validates a value against the given built-in type. 6367 * This one is intended to be used internally for validation 6368 * of schema attribute values during parsing of the schema. 6369 * 6370 * Returns 0 if the value is valid, a positive error code 6371 * number otherwise and -1 in case of an internal or API error. 6372 */ 6373static int 6374xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt, 6375 xmlSchemaBasicItemPtr ownerItem, 6376 xmlNodePtr ownerElem, 6377 const char *name, 6378 xmlSchemaTypePtr type, 6379 const xmlChar **value) 6380{ 6381 xmlAttrPtr attr; 6382 6383 if ((ctxt == NULL) || (type == NULL)) { 6384 if (value != NULL) 6385 *value = NULL; 6386 return (-1); 6387 } 6388 if (type->type != XML_SCHEMA_TYPE_BASIC) { 6389 if (value != NULL) 6390 *value = NULL; 6391 xmlSchemaPErr(ctxt, ownerElem, 6392 XML_SCHEMAP_INTERNAL, 6393 "Internal error: xmlSchemaPValAttr, the given " 6394 "type '%s' is not a built-in type.\n", 6395 type->name, NULL); 6396 return (-1); 6397 } 6398 attr = xmlSchemaGetPropNode(ownerElem, name); 6399 if (attr == NULL) { 6400 if (value != NULL) 6401 *value = NULL; 6402 return (0); 6403 } 6404 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr, 6405 type, value)); 6406} 6407 6408static int 6409xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt, 6410 xmlSchemaPtr schema ATTRIBUTE_UNUSED, 6411 xmlNodePtr node, 6412 xmlAttrPtr attr, 6413 const xmlChar *namespaceName) 6414{ 6415 /* TODO: Pointer comparison instead? */ 6416 if (xmlStrEqual(pctxt->targetNamespace, namespaceName)) 6417 return (0); 6418 if (xmlStrEqual(xmlSchemaNs, namespaceName)) 6419 return (0); 6420 /* 6421 * Check if the referenced namespace was <import>ed. 6422 */ 6423 if (WXS_BUCKET(pctxt)->relations != NULL) { 6424 xmlSchemaSchemaRelationPtr rel; 6425 6426 rel = WXS_BUCKET(pctxt)->relations; 6427 do { 6428 if (WXS_IS_BUCKET_IMPMAIN(rel->type) && 6429 xmlStrEqual(namespaceName, rel->importNamespace)) 6430 return (0); 6431 rel = rel->next; 6432 } while (rel != NULL); 6433 } 6434 /* 6435 * No matching <import>ed namespace found. 6436 */ 6437 { 6438 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node; 6439 6440 if (namespaceName == NULL) 6441 xmlSchemaCustomErr(ACTXT_CAST pctxt, 6442 XML_SCHEMAP_SRC_RESOLVE, n, NULL, 6443 "References from this schema to components in no " 6444 "namespace are not allowed, since not indicated by an " 6445 "import statement", NULL, NULL); 6446 else 6447 xmlSchemaCustomErr(ACTXT_CAST pctxt, 6448 XML_SCHEMAP_SRC_RESOLVE, n, NULL, 6449 "References from this schema to components in the " 6450 "namespace '%s' are not allowed, since not indicated by an " 6451 "import statement", namespaceName, NULL); 6452 } 6453 return (XML_SCHEMAP_SRC_RESOLVE); 6454} 6455 6456/** 6457 * xmlSchemaParseLocalAttributes: 6458 * @ctxt: a schema validation context 6459 * @schema: the schema being built 6460 * @node: a subtree containing XML Schema informations 6461 * @type: the hosting type where the attributes will be anchored 6462 * 6463 * Parses attribute uses and attribute declarations and 6464 * attribute group references. 6465 */ 6466static int 6467xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 6468 xmlNodePtr *child, xmlSchemaItemListPtr *list, 6469 int parentType, int *hasRefs) 6470{ 6471 void *item; 6472 6473 while ((IS_SCHEMA((*child), "attribute")) || 6474 (IS_SCHEMA((*child), "attributeGroup"))) { 6475 if (IS_SCHEMA((*child), "attribute")) { 6476 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child, 6477 *list, parentType); 6478 } else { 6479 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child); 6480 if ((item != NULL) && (hasRefs != NULL)) 6481 *hasRefs = 1; 6482 } 6483 if (item != NULL) { 6484 if (*list == NULL) { 6485 /* TODO: Customize grow factor. */ 6486 *list = xmlSchemaItemListCreate(); 6487 if (*list == NULL) 6488 return(-1); 6489 } 6490 if (xmlSchemaItemListAddSize(*list, 2, item) == -1) 6491 return(-1); 6492 } 6493 *child = (*child)->next; 6494 } 6495 return (0); 6496} 6497 6498/** 6499 * xmlSchemaParseAnnotation: 6500 * @ctxt: a schema validation context 6501 * @schema: the schema being built 6502 * @node: a subtree containing XML Schema informations 6503 * 6504 * parse a XML schema Attrribute declaration 6505 * *WARNING* this interface is highly subject to change 6506 * 6507 * Returns -1 in case of error, 0 if the declaration is improper and 6508 * 1 in case of success. 6509 */ 6510static xmlSchemaAnnotPtr 6511xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed) 6512{ 6513 xmlSchemaAnnotPtr ret; 6514 xmlNodePtr child = NULL; 6515 xmlAttrPtr attr; 6516 int barked = 0; 6517 6518 /* 6519 * INFO: S4S completed. 6520 */ 6521 /* 6522 * id = ID 6523 * {any attributes with non-schema namespace . . .}> 6524 * Content: (appinfo | documentation)* 6525 */ 6526 if ((ctxt == NULL) || (node == NULL)) 6527 return (NULL); 6528 if (needed) 6529 ret = xmlSchemaNewAnnot(ctxt, node); 6530 else 6531 ret = NULL; 6532 attr = node->properties; 6533 while (attr != NULL) { 6534 if (((attr->ns == NULL) && 6535 (!xmlStrEqual(attr->name, BAD_CAST "id"))) || 6536 ((attr->ns != NULL) && 6537 xmlStrEqual(attr->ns->href, xmlSchemaNs))) { 6538 6539 xmlSchemaPIllegalAttrErr(ctxt, 6540 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 6541 } 6542 attr = attr->next; 6543 } 6544 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 6545 /* 6546 * And now for the children... 6547 */ 6548 child = node->children; 6549 while (child != NULL) { 6550 if (IS_SCHEMA(child, "appinfo")) { 6551 /* TODO: make available the content of "appinfo". */ 6552 /* 6553 * source = anyURI 6554 * {any attributes with non-schema namespace . . .}> 6555 * Content: ({any})* 6556 */ 6557 attr = child->properties; 6558 while (attr != NULL) { 6559 if (((attr->ns == NULL) && 6560 (!xmlStrEqual(attr->name, BAD_CAST "source"))) || 6561 ((attr->ns != NULL) && 6562 xmlStrEqual(attr->ns->href, xmlSchemaNs))) { 6563 6564 xmlSchemaPIllegalAttrErr(ctxt, 6565 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 6566 } 6567 attr = attr->next; 6568 } 6569 xmlSchemaPValAttr(ctxt, NULL, child, "source", 6570 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL); 6571 child = child->next; 6572 } else if (IS_SCHEMA(child, "documentation")) { 6573 /* TODO: make available the content of "documentation". */ 6574 /* 6575 * source = anyURI 6576 * {any attributes with non-schema namespace . . .}> 6577 * Content: ({any})* 6578 */ 6579 attr = child->properties; 6580 while (attr != NULL) { 6581 if (attr->ns == NULL) { 6582 if (!xmlStrEqual(attr->name, BAD_CAST "source")) { 6583 xmlSchemaPIllegalAttrErr(ctxt, 6584 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 6585 } 6586 } else { 6587 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) || 6588 (xmlStrEqual(attr->name, BAD_CAST "lang") && 6589 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) { 6590 6591 xmlSchemaPIllegalAttrErr(ctxt, 6592 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 6593 } 6594 } 6595 attr = attr->next; 6596 } 6597 /* 6598 * Attribute "xml:lang". 6599 */ 6600 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang"); 6601 if (attr != NULL) 6602 xmlSchemaPValAttrNode(ctxt, NULL, attr, 6603 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL); 6604 child = child->next; 6605 } else { 6606 if (!barked) 6607 xmlSchemaPContentErr(ctxt, 6608 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 6609 NULL, node, child, NULL, "(appinfo | documentation)*"); 6610 barked = 1; 6611 child = child->next; 6612 } 6613 } 6614 6615 return (ret); 6616} 6617 6618/** 6619 * xmlSchemaParseFacet: 6620 * @ctxt: a schema validation context 6621 * @schema: the schema being built 6622 * @node: a subtree containing XML Schema informations 6623 * 6624 * parse a XML schema Facet declaration 6625 * *WARNING* this interface is highly subject to change 6626 * 6627 * Returns the new type structure or NULL in case of error 6628 */ 6629static xmlSchemaFacetPtr 6630xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 6631 xmlNodePtr node) 6632{ 6633 xmlSchemaFacetPtr facet; 6634 xmlNodePtr child = NULL; 6635 const xmlChar *value; 6636 6637 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 6638 return (NULL); 6639 6640 facet = xmlSchemaNewFacet(); 6641 if (facet == NULL) { 6642 xmlSchemaPErrMemory(ctxt, "allocating facet", node); 6643 return (NULL); 6644 } 6645 facet->node = node; 6646 value = xmlSchemaGetProp(ctxt, node, "value"); 6647 if (value == NULL) { 6648 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE, 6649 "Facet %s has no value\n", node->name, NULL); 6650 xmlSchemaFreeFacet(facet); 6651 return (NULL); 6652 } 6653 if (IS_SCHEMA(node, "minInclusive")) { 6654 facet->type = XML_SCHEMA_FACET_MININCLUSIVE; 6655 } else if (IS_SCHEMA(node, "minExclusive")) { 6656 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE; 6657 } else if (IS_SCHEMA(node, "maxInclusive")) { 6658 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE; 6659 } else if (IS_SCHEMA(node, "maxExclusive")) { 6660 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE; 6661 } else if (IS_SCHEMA(node, "totalDigits")) { 6662 facet->type = XML_SCHEMA_FACET_TOTALDIGITS; 6663 } else if (IS_SCHEMA(node, "fractionDigits")) { 6664 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS; 6665 } else if (IS_SCHEMA(node, "pattern")) { 6666 facet->type = XML_SCHEMA_FACET_PATTERN; 6667 } else if (IS_SCHEMA(node, "enumeration")) { 6668 facet->type = XML_SCHEMA_FACET_ENUMERATION; 6669 } else if (IS_SCHEMA(node, "whiteSpace")) { 6670 facet->type = XML_SCHEMA_FACET_WHITESPACE; 6671 } else if (IS_SCHEMA(node, "length")) { 6672 facet->type = XML_SCHEMA_FACET_LENGTH; 6673 } else if (IS_SCHEMA(node, "maxLength")) { 6674 facet->type = XML_SCHEMA_FACET_MAXLENGTH; 6675 } else if (IS_SCHEMA(node, "minLength")) { 6676 facet->type = XML_SCHEMA_FACET_MINLENGTH; 6677 } else { 6678 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE, 6679 "Unknown facet type %s\n", node->name, NULL); 6680 xmlSchemaFreeFacet(facet); 6681 return (NULL); 6682 } 6683 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 6684 facet->value = value; 6685 if ((facet->type != XML_SCHEMA_FACET_PATTERN) && 6686 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) { 6687 const xmlChar *fixed; 6688 6689 fixed = xmlSchemaGetProp(ctxt, node, "fixed"); 6690 if (fixed != NULL) { 6691 if (xmlStrEqual(fixed, BAD_CAST "true")) 6692 facet->fixed = 1; 6693 } 6694 } 6695 child = node->children; 6696 6697 if (IS_SCHEMA(child, "annotation")) { 6698 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1); 6699 child = child->next; 6700 } 6701 if (child != NULL) { 6702 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD, 6703 "Facet %s has unexpected child content\n", 6704 node->name, NULL); 6705 } 6706 return (facet); 6707} 6708 6709/** 6710 * xmlSchemaParseWildcardNs: 6711 * @ctxt: a schema parser context 6712 * @wildc: the wildcard, already created 6713 * @node: a subtree containing XML Schema informations 6714 * 6715 * Parses the attribute "processContents" and "namespace" 6716 * of a xsd:anyAttribute and xsd:any. 6717 * *WARNING* this interface is highly subject to change 6718 * 6719 * Returns 0 if everything goes fine, a positive error code 6720 * if something is not valid and -1 if an internal error occurs. 6721 */ 6722static int 6723xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt, 6724 xmlSchemaPtr schema ATTRIBUTE_UNUSED, 6725 xmlSchemaWildcardPtr wildc, 6726 xmlNodePtr node) 6727{ 6728 const xmlChar *pc, *ns, *dictnsItem; 6729 int ret = 0; 6730 xmlChar *nsItem; 6731 xmlSchemaWildcardNsPtr tmp, lastNs = NULL; 6732 xmlAttrPtr attr; 6733 6734 pc = xmlSchemaGetProp(ctxt, node, "processContents"); 6735 if ((pc == NULL) 6736 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) { 6737 wildc->processContents = XML_SCHEMAS_ANY_STRICT; 6738 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) { 6739 wildc->processContents = XML_SCHEMAS_ANY_SKIP; 6740 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) { 6741 wildc->processContents = XML_SCHEMAS_ANY_LAX; 6742 } else { 6743 xmlSchemaPSimpleTypeErr(ctxt, 6744 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 6745 NULL, node, 6746 NULL, "(strict | skip | lax)", pc, 6747 NULL, NULL, NULL); 6748 wildc->processContents = XML_SCHEMAS_ANY_STRICT; 6749 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; 6750 } 6751 /* 6752 * Build the namespace constraints. 6753 */ 6754 attr = xmlSchemaGetPropNode(node, "namespace"); 6755 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 6756 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any"))) 6757 wildc->any = 1; 6758 else if (xmlStrEqual(ns, BAD_CAST "##other")) { 6759 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); 6760 if (wildc->negNsSet == NULL) { 6761 return (-1); 6762 } 6763 wildc->negNsSet->value = ctxt->targetNamespace; 6764 } else { 6765 const xmlChar *end, *cur; 6766 6767 cur = ns; 6768 do { 6769 while (IS_BLANK_CH(*cur)) 6770 cur++; 6771 end = cur; 6772 while ((*end != 0) && (!(IS_BLANK_CH(*end)))) 6773 end++; 6774 if (end == cur) 6775 break; 6776 nsItem = xmlStrndup(cur, end - cur); 6777 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) || 6778 (xmlStrEqual(nsItem, BAD_CAST "##any"))) { 6779 xmlSchemaPSimpleTypeErr(ctxt, 6780 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER, 6781 NULL, (xmlNodePtr) attr, 6782 NULL, 6783 "((##any | ##other) | List of (xs:anyURI | " 6784 "(##targetNamespace | ##local)))", 6785 nsItem, NULL, NULL, NULL); 6786 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER; 6787 } else { 6788 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) { 6789 dictnsItem = ctxt->targetNamespace; 6790 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) { 6791 dictnsItem = NULL; 6792 } else { 6793 /* 6794 * Validate the item (anyURI). 6795 */ 6796 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr, 6797 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI)); 6798 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1); 6799 } 6800 /* 6801 * Avoid dublicate namespaces. 6802 */ 6803 tmp = wildc->nsSet; 6804 while (tmp != NULL) { 6805 if (dictnsItem == tmp->value) 6806 break; 6807 tmp = tmp->next; 6808 } 6809 if (tmp == NULL) { 6810 tmp = xmlSchemaNewWildcardNsConstraint(ctxt); 6811 if (tmp == NULL) { 6812 xmlFree(nsItem); 6813 return (-1); 6814 } 6815 tmp->value = dictnsItem; 6816 tmp->next = NULL; 6817 if (wildc->nsSet == NULL) 6818 wildc->nsSet = tmp; 6819 else if (lastNs != NULL) 6820 lastNs->next = tmp; 6821 lastNs = tmp; 6822 } 6823 6824 } 6825 xmlFree(nsItem); 6826 cur = end; 6827 } while (*cur != 0); 6828 } 6829 return (ret); 6830} 6831 6832static int 6833xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt, 6834 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED, 6835 xmlNodePtr node, 6836 int minOccurs, 6837 int maxOccurs) { 6838 6839 if ((maxOccurs == 0) && ( minOccurs == 0)) 6840 return (0); 6841 if (maxOccurs != UNBOUNDED) { 6842 /* 6843 * TODO: Maybe we should better not create the particle, 6844 * if min/max is invalid, since it could confuse the build of the 6845 * content model. 6846 */ 6847 /* 6848 * 3.9.6 Schema Component Constraint: Particle Correct 6849 * 6850 */ 6851 if (maxOccurs < 1) { 6852 /* 6853 * 2.2 {max occurs} must be greater than or equal to 1. 6854 */ 6855 xmlSchemaPCustomAttrErr(ctxt, 6856 XML_SCHEMAP_P_PROPS_CORRECT_2_2, 6857 NULL, NULL, 6858 xmlSchemaGetPropNode(node, "maxOccurs"), 6859 "The value must be greater than or equal to 1"); 6860 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2); 6861 } else if (minOccurs > maxOccurs) { 6862 /* 6863 * 2.1 {min occurs} must not be greater than {max occurs}. 6864 */ 6865 xmlSchemaPCustomAttrErr(ctxt, 6866 XML_SCHEMAP_P_PROPS_CORRECT_2_1, 6867 NULL, NULL, 6868 xmlSchemaGetPropNode(node, "minOccurs"), 6869 "The value must not be greater than the value of 'maxOccurs'"); 6870 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1); 6871 } 6872 } 6873 return (0); 6874} 6875 6876/** 6877 * xmlSchemaParseAny: 6878 * @ctxt: a schema validation context 6879 * @schema: the schema being built 6880 * @node: a subtree containing XML Schema informations 6881 * 6882 * Parsea a XML schema <any> element. A particle and wildcard 6883 * will be created (except if minOccurs==maxOccurs==0, in this case 6884 * nothing will be created). 6885 * *WARNING* this interface is highly subject to change 6886 * 6887 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0 6888 */ 6889static xmlSchemaParticlePtr 6890xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 6891 xmlNodePtr node) 6892{ 6893 xmlSchemaParticlePtr particle; 6894 xmlNodePtr child = NULL; 6895 xmlSchemaWildcardPtr wild; 6896 int min, max; 6897 xmlAttrPtr attr; 6898 xmlSchemaAnnotPtr annot = NULL; 6899 6900 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 6901 return (NULL); 6902 /* 6903 * Check for illegal attributes. 6904 */ 6905 attr = node->properties; 6906 while (attr != NULL) { 6907 if (attr->ns == NULL) { 6908 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 6909 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) && 6910 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) && 6911 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) && 6912 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) { 6913 xmlSchemaPIllegalAttrErr(ctxt, 6914 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 6915 } 6916 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 6917 xmlSchemaPIllegalAttrErr(ctxt, 6918 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 6919 } 6920 attr = attr->next; 6921 } 6922 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 6923 /* 6924 * minOccurs/maxOccurs. 6925 */ 6926 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, 6927 "(xs:nonNegativeInteger | unbounded)"); 6928 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, 6929 "xs:nonNegativeInteger"); 6930 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max); 6931 /* 6932 * Create & parse the wildcard. 6933 */ 6934 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node); 6935 if (wild == NULL) 6936 return (NULL); 6937 xmlSchemaParseWildcardNs(ctxt, schema, wild, node); 6938 /* 6939 * And now for the children... 6940 */ 6941 child = node->children; 6942 if (IS_SCHEMA(child, "annotation")) { 6943 annot = xmlSchemaParseAnnotation(ctxt, child, 1); 6944 child = child->next; 6945 } 6946 if (child != NULL) { 6947 xmlSchemaPContentErr(ctxt, 6948 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 6949 NULL, node, child, 6950 NULL, "(annotation?)"); 6951 } 6952 /* 6953 * No component if minOccurs==maxOccurs==0. 6954 */ 6955 if ((min == 0) && (max == 0)) { 6956 /* Don't free the wildcard, since it's already on the list. */ 6957 return (NULL); 6958 } 6959 /* 6960 * Create the particle. 6961 */ 6962 particle = xmlSchemaAddParticle(ctxt, node, min, max); 6963 if (particle == NULL) 6964 return (NULL); 6965 particle->annot = annot; 6966 particle->children = (xmlSchemaTreeItemPtr) wild; 6967 6968 return (particle); 6969} 6970 6971/** 6972 * xmlSchemaParseNotation: 6973 * @ctxt: a schema validation context 6974 * @schema: the schema being built 6975 * @node: a subtree containing XML Schema informations 6976 * 6977 * parse a XML schema Notation declaration 6978 * 6979 * Returns the new structure or NULL in case of error 6980 */ 6981static xmlSchemaNotationPtr 6982xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 6983 xmlNodePtr node) 6984{ 6985 const xmlChar *name; 6986 xmlSchemaNotationPtr ret; 6987 xmlNodePtr child = NULL; 6988 6989 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 6990 return (NULL); 6991 name = xmlSchemaGetProp(ctxt, node, "name"); 6992 if (name == NULL) { 6993 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME, 6994 "Notation has no name\n", NULL, NULL); 6995 return (NULL); 6996 } 6997 ret = xmlSchemaAddNotation(ctxt, schema, name, 6998 ctxt->targetNamespace, node); 6999 if (ret == NULL) 7000 return (NULL); 7001 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 7002 7003 child = node->children; 7004 if (IS_SCHEMA(child, "annotation")) { 7005 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1); 7006 child = child->next; 7007 } 7008 if (child != NULL) { 7009 xmlSchemaPContentErr(ctxt, 7010 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 7011 NULL, node, child, 7012 NULL, "(annotation?)"); 7013 } 7014 7015 return (ret); 7016} 7017 7018/** 7019 * xmlSchemaParseAnyAttribute: 7020 * @ctxt: a schema validation context 7021 * @schema: the schema being built 7022 * @node: a subtree containing XML Schema informations 7023 * 7024 * parse a XML schema AnyAttrribute declaration 7025 * *WARNING* this interface is highly subject to change 7026 * 7027 * Returns a wildcard or NULL. 7028 */ 7029static xmlSchemaWildcardPtr 7030xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, 7031 xmlSchemaPtr schema, xmlNodePtr node) 7032{ 7033 xmlSchemaWildcardPtr ret; 7034 xmlNodePtr child = NULL; 7035 xmlAttrPtr attr; 7036 7037 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 7038 return (NULL); 7039 7040 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE, 7041 node); 7042 if (ret == NULL) { 7043 return (NULL); 7044 } 7045 /* 7046 * Check for illegal attributes. 7047 */ 7048 attr = node->properties; 7049 while (attr != NULL) { 7050 if (attr->ns == NULL) { 7051 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 7052 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) && 7053 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) { 7054 xmlSchemaPIllegalAttrErr(ctxt, 7055 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 7056 } 7057 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 7058 xmlSchemaPIllegalAttrErr(ctxt, 7059 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 7060 } 7061 attr = attr->next; 7062 } 7063 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 7064 /* 7065 * Parse the namespace list. 7066 */ 7067 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) 7068 return (NULL); 7069 /* 7070 * And now for the children... 7071 */ 7072 child = node->children; 7073 if (IS_SCHEMA(child, "annotation")) { 7074 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1); 7075 child = child->next; 7076 } 7077 if (child != NULL) { 7078 xmlSchemaPContentErr(ctxt, 7079 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 7080 NULL, node, child, 7081 NULL, "(annotation?)"); 7082 } 7083 7084 return (ret); 7085} 7086 7087 7088/** 7089 * xmlSchemaParseAttribute: 7090 * @ctxt: a schema validation context 7091 * @schema: the schema being built 7092 * @node: a subtree containing XML Schema informations 7093 * 7094 * parse a XML schema Attrribute declaration 7095 * *WARNING* this interface is highly subject to change 7096 * 7097 * Returns the attribute declaration. 7098 */ 7099static xmlSchemaBasicItemPtr 7100xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt, 7101 xmlSchemaPtr schema, 7102 xmlNodePtr node, 7103 xmlSchemaItemListPtr uses, 7104 int parentType) 7105{ 7106 const xmlChar *attrValue, *name = NULL, *ns = NULL; 7107 xmlSchemaAttributeUsePtr use = NULL; 7108 xmlNodePtr child = NULL; 7109 xmlAttrPtr attr; 7110 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL; 7111 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL; 7112 int nberrors, hasForm = 0, defValueType = 0; 7113 7114#define WXS_ATTR_DEF_VAL_DEFAULT 1 7115#define WXS_ATTR_DEF_VAL_FIXED 2 7116 7117 /* 7118 * 3.2.3 Constraints on XML Representations of Attribute Declarations 7119 */ 7120 7121 if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) 7122 return (NULL); 7123 attr = xmlSchemaGetPropNode(node, "ref"); 7124 if (attr != NULL) { 7125 if (xmlSchemaPValAttrNodeQName(pctxt, schema, 7126 NULL, attr, &tmpNs, &tmpName) != 0) { 7127 return (NULL); 7128 } 7129 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0) 7130 return(NULL); 7131 isRef = 1; 7132 } 7133 nberrors = pctxt->nberrors; 7134 /* 7135 * Check for illegal attributes. 7136 */ 7137 attr = node->properties; 7138 while (attr != NULL) { 7139 if (attr->ns == NULL) { 7140 if (isRef) { 7141 if (xmlStrEqual(attr->name, BAD_CAST "id")) { 7142 xmlSchemaPValAttrNodeID(pctxt, attr); 7143 goto attr_next; 7144 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) { 7145 goto attr_next; 7146 } 7147 } else { 7148 if (xmlStrEqual(attr->name, BAD_CAST "name")) { 7149 goto attr_next; 7150 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) { 7151 xmlSchemaPValAttrNodeID(pctxt, attr); 7152 goto attr_next; 7153 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) { 7154 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL, 7155 attr, &tmpNs, &tmpName); 7156 goto attr_next; 7157 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) { 7158 /* 7159 * Evaluate the target namespace 7160 */ 7161 hasForm = 1; 7162 attrValue = xmlSchemaGetNodeContent(pctxt, 7163 (xmlNodePtr) attr); 7164 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) { 7165 ns = pctxt->targetNamespace; 7166 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) 7167 { 7168 xmlSchemaPSimpleTypeErr(pctxt, 7169 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 7170 NULL, (xmlNodePtr) attr, 7171 NULL, "(qualified | unqualified)", 7172 attrValue, NULL, NULL, NULL); 7173 } 7174 goto attr_next; 7175 } 7176 } 7177 if (xmlStrEqual(attr->name, BAD_CAST "use")) { 7178 7179 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); 7180 /* TODO: Maybe we need to normalize the value beforehand. */ 7181 if (xmlStrEqual(attrValue, BAD_CAST "optional")) 7182 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL; 7183 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited")) 7184 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED; 7185 else if (xmlStrEqual(attrValue, BAD_CAST "required")) 7186 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED; 7187 else { 7188 xmlSchemaPSimpleTypeErr(pctxt, 7189 XML_SCHEMAP_INVALID_ATTR_USE, 7190 NULL, (xmlNodePtr) attr, 7191 NULL, "(optional | prohibited | required)", 7192 attrValue, NULL, NULL, NULL); 7193 } 7194 goto attr_next; 7195 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) { 7196 /* 7197 * 3.2.3 : 1 7198 * default and fixed must not both be present. 7199 */ 7200 if (defValue) { 7201 xmlSchemaPMutualExclAttrErr(pctxt, 7202 XML_SCHEMAP_SRC_ATTRIBUTE_1, 7203 NULL, attr, "default", "fixed"); 7204 } else { 7205 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); 7206 defValueType = WXS_ATTR_DEF_VAL_DEFAULT; 7207 } 7208 goto attr_next; 7209 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) { 7210 /* 7211 * 3.2.3 : 1 7212 * default and fixed must not both be present. 7213 */ 7214 if (defValue) { 7215 xmlSchemaPMutualExclAttrErr(pctxt, 7216 XML_SCHEMAP_SRC_ATTRIBUTE_1, 7217 NULL, attr, "default", "fixed"); 7218 } else { 7219 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); 7220 defValueType = WXS_ATTR_DEF_VAL_FIXED; 7221 } 7222 goto attr_next; 7223 } 7224 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs)) 7225 goto attr_next; 7226 7227 xmlSchemaPIllegalAttrErr(pctxt, 7228 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 7229 7230attr_next: 7231 attr = attr->next; 7232 } 7233 /* 7234 * 3.2.3 : 2 7235 * If default and use are both present, use must have 7236 * the actual value optional. 7237 */ 7238 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) && 7239 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) { 7240 xmlSchemaPSimpleTypeErr(pctxt, 7241 XML_SCHEMAP_SRC_ATTRIBUTE_2, 7242 NULL, node, NULL, 7243 "(optional | prohibited | required)", NULL, 7244 "The value of the attribute 'use' must be 'optional' " 7245 "if the attribute 'default' is present", 7246 NULL, NULL); 7247 } 7248 /* 7249 * We want correct attributes. 7250 */ 7251 if (nberrors != pctxt->nberrors) 7252 return(NULL); 7253 if (! isRef) { 7254 xmlSchemaAttributePtr attrDecl; 7255 7256 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */ 7257 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR)) 7258 ns = pctxt->targetNamespace; 7259 /* 7260 * 3.2.6 Schema Component Constraint: xsi: Not Allowed 7261 * TODO: Move this to the component layer. 7262 */ 7263 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) { 7264 xmlSchemaCustomErr(ACTXT_CAST pctxt, 7265 XML_SCHEMAP_NO_XSI, 7266 node, NULL, 7267 "The target namespace must not match '%s'", 7268 xmlSchemaInstanceNs, NULL); 7269 } 7270 attr = xmlSchemaGetPropNode(node, "name"); 7271 if (attr == NULL) { 7272 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING, 7273 NULL, node, "name", NULL); 7274 return (NULL); 7275 } 7276 if (xmlSchemaPValAttrNode(pctxt, NULL, attr, 7277 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { 7278 return (NULL); 7279 } 7280 /* 7281 * 3.2.6 Schema Component Constraint: xmlns Not Allowed 7282 * TODO: Move this to the component layer. 7283 */ 7284 if (xmlStrEqual(name, BAD_CAST "xmlns")) { 7285 xmlSchemaPSimpleTypeErr(pctxt, 7286 XML_SCHEMAP_NO_XMLNS, 7287 NULL, (xmlNodePtr) attr, 7288 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL, 7289 "The value of the attribute must not match 'xmlns'", 7290 NULL, NULL); 7291 return (NULL); 7292 } 7293 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) 7294 goto check_children; 7295 /* 7296 * Create the attribute use component. 7297 */ 7298 use = xmlSchemaAddAttributeUse(pctxt, node); 7299 if (use == NULL) 7300 return(NULL); 7301 use->occurs = occurs; 7302 /* 7303 * Create the attribute declaration. 7304 */ 7305 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0); 7306 if (attrDecl == NULL) 7307 return (NULL); 7308 if (tmpName != NULL) { 7309 attrDecl->typeName = tmpName; 7310 attrDecl->typeNs = tmpNs; 7311 } 7312 use->attrDecl = attrDecl; 7313 /* 7314 * Value constraint. 7315 */ 7316 if (defValue != NULL) { 7317 attrDecl->defValue = defValue; 7318 if (defValueType == WXS_ATTR_DEF_VAL_FIXED) 7319 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED; 7320 } 7321 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) { 7322 xmlSchemaQNameRefPtr ref; 7323 7324 /* 7325 * Create the attribute use component. 7326 */ 7327 use = xmlSchemaAddAttributeUse(pctxt, node); 7328 if (use == NULL) 7329 return(NULL); 7330 /* 7331 * We need to resolve the reference at later stage. 7332 */ 7333 WXS_ADD_PENDING(pctxt, use); 7334 use->occurs = occurs; 7335 /* 7336 * Create a QName reference to the attribute declaration. 7337 */ 7338 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE, 7339 tmpName, tmpNs); 7340 if (ref == NULL) 7341 return(NULL); 7342 /* 7343 * Assign the reference. This will be substituted for the 7344 * referenced attribute declaration when the QName is resolved. 7345 */ 7346 use->attrDecl = WXS_ATTR_CAST ref; 7347 /* 7348 * Value constraint. 7349 */ 7350 if (defValue != NULL) 7351 use->defValue = defValue; 7352 if (defValueType == WXS_ATTR_DEF_VAL_FIXED) 7353 use->flags |= XML_SCHEMA_ATTR_USE_FIXED; 7354 } 7355 7356check_children: 7357 /* 7358 * And now for the children... 7359 */ 7360 child = node->children; 7361 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) { 7362 xmlSchemaAttributeUseProhibPtr prohib; 7363 7364 if (IS_SCHEMA(child, "annotation")) { 7365 xmlSchemaParseAnnotation(pctxt, child, 0); 7366 child = child->next; 7367 } 7368 if (child != NULL) { 7369 xmlSchemaPContentErr(pctxt, 7370 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 7371 NULL, node, child, NULL, 7372 "(annotation?)"); 7373 } 7374 /* 7375 * Check for pointlessness of attribute prohibitions. 7376 */ 7377 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) { 7378 xmlSchemaCustomWarning(ACTXT_CAST pctxt, 7379 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, 7380 node, NULL, 7381 "Skipping attribute use prohibition, since it is " 7382 "pointless inside an <attributeGroup>", 7383 NULL, NULL, NULL); 7384 return(NULL); 7385 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) { 7386 xmlSchemaCustomWarning(ACTXT_CAST pctxt, 7387 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, 7388 node, NULL, 7389 "Skipping attribute use prohibition, since it is " 7390 "pointless when extending a type", 7391 NULL, NULL, NULL); 7392 return(NULL); 7393 } 7394 if (! isRef) { 7395 tmpName = name; 7396 tmpNs = ns; 7397 } 7398 /* 7399 * Check for duplicate attribute prohibitions. 7400 */ 7401 if (uses) { 7402 int i; 7403 7404 for (i = 0; i < uses->nbItems; i++) { 7405 use = uses->items[i]; 7406 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) && 7407 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) && 7408 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace)) 7409 { 7410 xmlChar *str = NULL; 7411 7412 xmlSchemaCustomWarning(ACTXT_CAST pctxt, 7413 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, 7414 node, NULL, 7415 "Skipping duplicate attribute use prohibition '%s'", 7416 xmlSchemaFormatQName(&str, tmpNs, tmpName), 7417 NULL, NULL); 7418 FREE_AND_NULL(str) 7419 return(NULL); 7420 } 7421 } 7422 } 7423 /* 7424 * Create the attribute prohibition helper component. 7425 */ 7426 prohib = xmlSchemaAddAttributeUseProhib(pctxt); 7427 if (prohib == NULL) 7428 return(NULL); 7429 prohib->node = node; 7430 prohib->name = tmpName; 7431 prohib->targetNamespace = tmpNs; 7432 if (isRef) { 7433 /* 7434 * We need at least to resolve to the attribute declaration. 7435 */ 7436 WXS_ADD_PENDING(pctxt, prohib); 7437 } 7438 return(WXS_BASIC_CAST prohib); 7439 } else { 7440 if (IS_SCHEMA(child, "annotation")) { 7441 /* 7442 * TODO: Should this go into the attr decl? 7443 */ 7444 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1); 7445 child = child->next; 7446 } 7447 if (isRef) { 7448 if (child != NULL) { 7449 if (IS_SCHEMA(child, "simpleType")) 7450 /* 7451 * 3.2.3 : 3.2 7452 * If ref is present, then all of <simpleType>, 7453 * form and type must be absent. 7454 */ 7455 xmlSchemaPContentErr(pctxt, 7456 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, 7457 NULL, node, child, NULL, 7458 "(annotation?)"); 7459 else 7460 xmlSchemaPContentErr(pctxt, 7461 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 7462 NULL, node, child, NULL, 7463 "(annotation?)"); 7464 } 7465 } else { 7466 if (IS_SCHEMA(child, "simpleType")) { 7467 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) { 7468 /* 7469 * 3.2.3 : 4 7470 * type and <simpleType> must not both be present. 7471 */ 7472 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4, 7473 NULL, node, child, 7474 "The attribute 'type' and the <simpleType> child " 7475 "are mutually exclusive", NULL); 7476 } else 7477 WXS_ATTRUSE_TYPEDEF(use) = 7478 xmlSchemaParseSimpleType(pctxt, schema, child, 0); 7479 child = child->next; 7480 } 7481 if (child != NULL) 7482 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 7483 NULL, node, child, NULL, 7484 "(annotation?, simpleType?)"); 7485 } 7486 } 7487 return (WXS_BASIC_CAST use); 7488} 7489 7490 7491static xmlSchemaAttributePtr 7492xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt, 7493 xmlSchemaPtr schema, 7494 xmlNodePtr node) 7495{ 7496 const xmlChar *attrValue; 7497 xmlSchemaAttributePtr ret; 7498 xmlNodePtr child = NULL; 7499 xmlAttrPtr attr; 7500 7501 /* 7502 * Note that the w3c spec assumes the schema to be validated with schema 7503 * for schemas beforehand. 7504 * 7505 * 3.2.3 Constraints on XML Representations of Attribute Declarations 7506 */ 7507 if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) 7508 return (NULL); 7509 /* 7510 * 3.2.3 : 3.1 7511 * One of ref or name must be present, but not both 7512 */ 7513 attr = xmlSchemaGetPropNode(node, "name"); 7514 if (attr == NULL) { 7515 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING, 7516 NULL, node, "name", NULL); 7517 return (NULL); 7518 } 7519 if (xmlSchemaPValAttrNode(pctxt, NULL, attr, 7520 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) { 7521 return (NULL); 7522 } 7523 /* 7524 * 3.2.6 Schema Component Constraint: xmlns Not Allowed 7525 * TODO: Move this to the component layer. 7526 */ 7527 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) { 7528 xmlSchemaPSimpleTypeErr(pctxt, 7529 XML_SCHEMAP_NO_XMLNS, 7530 NULL, (xmlNodePtr) attr, 7531 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL, 7532 "The value of the attribute must not match 'xmlns'", 7533 NULL, NULL); 7534 return (NULL); 7535 } 7536 /* 7537 * 3.2.6 Schema Component Constraint: xsi: Not Allowed 7538 * TODO: Move this to the component layer. 7539 * Or better leave it here and add it to the component layer 7540 * if we have a schema construction API. 7541 */ 7542 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) { 7543 xmlSchemaCustomErr(ACTXT_CAST pctxt, 7544 XML_SCHEMAP_NO_XSI, node, NULL, 7545 "The target namespace must not match '%s'", 7546 xmlSchemaInstanceNs, NULL); 7547 } 7548 7549 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue, 7550 pctxt->targetNamespace, node, 1); 7551 if (ret == NULL) 7552 return (NULL); 7553 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL; 7554 7555 /* 7556 * Check for illegal attributes. 7557 */ 7558 attr = node->properties; 7559 while (attr != NULL) { 7560 if (attr->ns == NULL) { 7561 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 7562 (!xmlStrEqual(attr->name, BAD_CAST "default")) && 7563 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) && 7564 (!xmlStrEqual(attr->name, BAD_CAST "name")) && 7565 (!xmlStrEqual(attr->name, BAD_CAST "type"))) 7566 { 7567 xmlSchemaPIllegalAttrErr(pctxt, 7568 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 7569 } 7570 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 7571 xmlSchemaPIllegalAttrErr(pctxt, 7572 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 7573 } 7574 attr = attr->next; 7575 } 7576 xmlSchemaPValAttrQName(pctxt, schema, NULL, 7577 node, "type", &ret->typeNs, &ret->typeName); 7578 7579 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); 7580 /* 7581 * Attribute "fixed". 7582 */ 7583 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed"); 7584 if (ret->defValue != NULL) 7585 ret->flags |= XML_SCHEMAS_ATTR_FIXED; 7586 /* 7587 * Attribute "default". 7588 */ 7589 attr = xmlSchemaGetPropNode(node, "default"); 7590 if (attr != NULL) { 7591 /* 7592 * 3.2.3 : 1 7593 * default and fixed must not both be present. 7594 */ 7595 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) { 7596 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1, 7597 WXS_BASIC_CAST ret, attr, "default", "fixed"); 7598 } else 7599 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); 7600 } 7601 /* 7602 * And now for the children... 7603 */ 7604 child = node->children; 7605 if (IS_SCHEMA(child, "annotation")) { 7606 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1); 7607 child = child->next; 7608 } 7609 if (IS_SCHEMA(child, "simpleType")) { 7610 if (ret->typeName != NULL) { 7611 /* 7612 * 3.2.3 : 4 7613 * type and <simpleType> must not both be present. 7614 */ 7615 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4, 7616 NULL, node, child, 7617 "The attribute 'type' and the <simpleType> child " 7618 "are mutually exclusive", NULL); 7619 } else 7620 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0); 7621 child = child->next; 7622 } 7623 if (child != NULL) 7624 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 7625 NULL, node, child, NULL, 7626 "(annotation?, simpleType?)"); 7627 7628 return (ret); 7629} 7630 7631/** 7632 * xmlSchemaParseAttributeGroupRef: 7633 * @ctxt: a schema validation context 7634 * @schema: the schema being built 7635 * @node: a subtree containing XML Schema informations 7636 * 7637 * Parse an attribute group definition reference. 7638 * Note that a reference to an attribute group does not 7639 * correspond to any component at all. 7640 * *WARNING* this interface is highly subject to change 7641 * 7642 * Returns the attribute group or NULL in case of error. 7643 */ 7644static xmlSchemaQNameRefPtr 7645xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt, 7646 xmlSchemaPtr schema, 7647 xmlNodePtr node) 7648{ 7649 xmlSchemaQNameRefPtr ret; 7650 xmlNodePtr child = NULL; 7651 xmlAttrPtr attr; 7652 const xmlChar *refNs = NULL, *ref = NULL; 7653 7654 if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) 7655 return (NULL); 7656 7657 attr = xmlSchemaGetPropNode(node, "ref"); 7658 if (attr == NULL) { 7659 xmlSchemaPMissingAttrErr(pctxt, 7660 XML_SCHEMAP_S4S_ATTR_MISSING, 7661 NULL, node, "ref", NULL); 7662 return (NULL); 7663 } 7664 xmlSchemaPValAttrNodeQName(pctxt, schema, 7665 NULL, attr, &refNs, &ref); 7666 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0) 7667 return(NULL); 7668 7669 /* 7670 * Check for illegal attributes. 7671 */ 7672 attr = node->properties; 7673 while (attr != NULL) { 7674 if (attr->ns == NULL) { 7675 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) && 7676 (!xmlStrEqual(attr->name, BAD_CAST "id"))) 7677 { 7678 xmlSchemaPIllegalAttrErr(pctxt, 7679 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 7680 } 7681 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 7682 xmlSchemaPIllegalAttrErr(pctxt, 7683 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 7684 } 7685 attr = attr->next; 7686 } 7687 /* Attribute ID */ 7688 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); 7689 7690 /* 7691 * And now for the children... 7692 */ 7693 child = node->children; 7694 if (IS_SCHEMA(child, "annotation")) { 7695 /* 7696 * TODO: We do not have a place to store the annotation, do we? 7697 */ 7698 xmlSchemaParseAnnotation(pctxt, child, 0); 7699 child = child->next; 7700 } 7701 if (child != NULL) { 7702 xmlSchemaPContentErr(pctxt, 7703 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 7704 NULL, node, child, NULL, 7705 "(annotation?)"); 7706 } 7707 7708 /* 7709 * Handle attribute group redefinitions. 7710 */ 7711 if (pctxt->isRedefine && pctxt->redef && 7712 (pctxt->redef->item->type == 7713 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) && 7714 (ref == pctxt->redef->refName) && 7715 (refNs == pctxt->redef->refTargetNs)) 7716 { 7717 /* 7718 * SPEC src-redefine: 7719 * (7.1) "If it has an <attributeGroup> among its contents 7720 * the �actual value� of whose ref [attribute] is the same 7721 * as the �actual value� of its own name attribute plus 7722 * target namespace, then it must have exactly one such group." 7723 */ 7724 if (pctxt->redefCounter != 0) { 7725 xmlChar *str = NULL; 7726 7727 xmlSchemaCustomErr(ACTXT_CAST pctxt, 7728 XML_SCHEMAP_SRC_REDEFINE, node, NULL, 7729 "The redefining attribute group definition " 7730 "'%s' must not contain more than one " 7731 "reference to the redefined definition", 7732 xmlSchemaFormatQName(&str, refNs, ref), NULL); 7733 FREE_AND_NULL(str); 7734 return(NULL); 7735 } 7736 pctxt->redefCounter++; 7737 /* 7738 * URGENT TODO: How to ensure that the reference will not be 7739 * handled by the normal component resolution mechanism? 7740 */ 7741 ret = xmlSchemaNewQNameRef(pctxt, 7742 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs); 7743 if (ret == NULL) 7744 return(NULL); 7745 ret->node = node; 7746 pctxt->redef->reference = WXS_BASIC_CAST ret; 7747 } else { 7748 /* 7749 * Create a QName-reference helper component. We will substitute this 7750 * component for the attribute uses of the referenced attribute group 7751 * definition. 7752 */ 7753 ret = xmlSchemaNewQNameRef(pctxt, 7754 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs); 7755 if (ret == NULL) 7756 return(NULL); 7757 ret->node = node; 7758 /* Add to pending items, to be able to resolve the reference. */ 7759 WXS_ADD_PENDING(pctxt, ret); 7760 } 7761 return (ret); 7762} 7763 7764/** 7765 * xmlSchemaParseAttributeGroupDefinition: 7766 * @pctxt: a schema validation context 7767 * @schema: the schema being built 7768 * @node: a subtree containing XML Schema informations 7769 * 7770 * parse a XML schema Attribute Group declaration 7771 * *WARNING* this interface is highly subject to change 7772 * 7773 * Returns the attribute group definition or NULL in case of error. 7774 */ 7775static xmlSchemaAttributeGroupPtr 7776xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt, 7777 xmlSchemaPtr schema, 7778 xmlNodePtr node) 7779{ 7780 const xmlChar *name; 7781 xmlSchemaAttributeGroupPtr ret; 7782 xmlNodePtr child = NULL; 7783 xmlAttrPtr attr; 7784 int hasRefs = 0; 7785 7786 if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) 7787 return (NULL); 7788 7789 attr = xmlSchemaGetPropNode(node, "name"); 7790 if (attr == NULL) { 7791 xmlSchemaPMissingAttrErr(pctxt, 7792 XML_SCHEMAP_S4S_ATTR_MISSING, 7793 NULL, node, "name", NULL); 7794 return (NULL); 7795 } 7796 /* 7797 * The name is crucial, exit if invalid. 7798 */ 7799 if (xmlSchemaPValAttrNode(pctxt, 7800 NULL, attr, 7801 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { 7802 return (NULL); 7803 } 7804 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema, 7805 name, pctxt->targetNamespace, node); 7806 if (ret == NULL) 7807 return (NULL); 7808 /* 7809 * Check for illegal attributes. 7810 */ 7811 attr = node->properties; 7812 while (attr != NULL) { 7813 if (attr->ns == NULL) { 7814 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) && 7815 (!xmlStrEqual(attr->name, BAD_CAST "id"))) 7816 { 7817 xmlSchemaPIllegalAttrErr(pctxt, 7818 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 7819 } 7820 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 7821 xmlSchemaPIllegalAttrErr(pctxt, 7822 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 7823 } 7824 attr = attr->next; 7825 } 7826 /* Attribute ID */ 7827 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); 7828 /* 7829 * And now for the children... 7830 */ 7831 child = node->children; 7832 if (IS_SCHEMA(child, "annotation")) { 7833 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1); 7834 child = child->next; 7835 } 7836 /* 7837 * Parse contained attribute decls/refs. 7838 */ 7839 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child, 7840 (xmlSchemaItemListPtr *) &(ret->attrUses), 7841 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1) 7842 return(NULL); 7843 if (hasRefs) 7844 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS; 7845 /* 7846 * Parse the attribute wildcard. 7847 */ 7848 if (IS_SCHEMA(child, "anyAttribute")) { 7849 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt, 7850 schema, child); 7851 child = child->next; 7852 } 7853 if (child != NULL) { 7854 xmlSchemaPContentErr(pctxt, 7855 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 7856 NULL, node, child, NULL, 7857 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))"); 7858 } 7859 return (ret); 7860} 7861 7862/** 7863 * xmlSchemaPValAttrFormDefault: 7864 * @value: the value 7865 * @flags: the flags to be modified 7866 * @flagQualified: the specific flag for "qualified" 7867 * 7868 * Returns 0 if the value is valid, 1 otherwise. 7869 */ 7870static int 7871xmlSchemaPValAttrFormDefault(const xmlChar *value, 7872 int *flags, 7873 int flagQualified) 7874{ 7875 if (xmlStrEqual(value, BAD_CAST "qualified")) { 7876 if ((*flags & flagQualified) == 0) 7877 *flags |= flagQualified; 7878 } else if (!xmlStrEqual(value, BAD_CAST "unqualified")) 7879 return (1); 7880 7881 return (0); 7882} 7883 7884/** 7885 * xmlSchemaPValAttrBlockFinal: 7886 * @value: the value 7887 * @flags: the flags to be modified 7888 * @flagAll: the specific flag for "#all" 7889 * @flagExtension: the specific flag for "extension" 7890 * @flagRestriction: the specific flag for "restriction" 7891 * @flagSubstitution: the specific flag for "substitution" 7892 * @flagList: the specific flag for "list" 7893 * @flagUnion: the specific flag for "union" 7894 * 7895 * Validates the value of the attribute "final" and "block". The value 7896 * is converted into the specified flag values and returned in @flags. 7897 * 7898 * Returns 0 if the value is valid, 1 otherwise. 7899 */ 7900 7901static int 7902xmlSchemaPValAttrBlockFinal(const xmlChar *value, 7903 int *flags, 7904 int flagAll, 7905 int flagExtension, 7906 int flagRestriction, 7907 int flagSubstitution, 7908 int flagList, 7909 int flagUnion) 7910{ 7911 int ret = 0; 7912 7913 /* 7914 * TODO: This does not check for dublicate entries. 7915 */ 7916 if ((flags == NULL) || (value == NULL)) 7917 return (-1); 7918 if (value[0] == 0) 7919 return (0); 7920 if (xmlStrEqual(value, BAD_CAST "#all")) { 7921 if (flagAll != -1) 7922 *flags |= flagAll; 7923 else { 7924 if (flagExtension != -1) 7925 *flags |= flagExtension; 7926 if (flagRestriction != -1) 7927 *flags |= flagRestriction; 7928 if (flagSubstitution != -1) 7929 *flags |= flagSubstitution; 7930 if (flagList != -1) 7931 *flags |= flagList; 7932 if (flagUnion != -1) 7933 *flags |= flagUnion; 7934 } 7935 } else { 7936 const xmlChar *end, *cur = value; 7937 xmlChar *item; 7938 7939 do { 7940 while (IS_BLANK_CH(*cur)) 7941 cur++; 7942 end = cur; 7943 while ((*end != 0) && (!(IS_BLANK_CH(*end)))) 7944 end++; 7945 if (end == cur) 7946 break; 7947 item = xmlStrndup(cur, end - cur); 7948 if (xmlStrEqual(item, BAD_CAST "extension")) { 7949 if (flagExtension != -1) { 7950 if ((*flags & flagExtension) == 0) 7951 *flags |= flagExtension; 7952 } else 7953 ret = 1; 7954 } else if (xmlStrEqual(item, BAD_CAST "restriction")) { 7955 if (flagRestriction != -1) { 7956 if ((*flags & flagRestriction) == 0) 7957 *flags |= flagRestriction; 7958 } else 7959 ret = 1; 7960 } else if (xmlStrEqual(item, BAD_CAST "substitution")) { 7961 if (flagSubstitution != -1) { 7962 if ((*flags & flagSubstitution) == 0) 7963 *flags |= flagSubstitution; 7964 } else 7965 ret = 1; 7966 } else if (xmlStrEqual(item, BAD_CAST "list")) { 7967 if (flagList != -1) { 7968 if ((*flags & flagList) == 0) 7969 *flags |= flagList; 7970 } else 7971 ret = 1; 7972 } else if (xmlStrEqual(item, BAD_CAST "union")) { 7973 if (flagUnion != -1) { 7974 if ((*flags & flagUnion) == 0) 7975 *flags |= flagUnion; 7976 } else 7977 ret = 1; 7978 } else 7979 ret = 1; 7980 if (item != NULL) 7981 xmlFree(item); 7982 cur = end; 7983 } while ((ret == 0) && (*cur != 0)); 7984 } 7985 7986 return (ret); 7987} 7988 7989static int 7990xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt, 7991 xmlSchemaIDCPtr idc, 7992 xmlSchemaIDCSelectPtr selector, 7993 xmlAttrPtr attr, 7994 int isField) 7995{ 7996 xmlNodePtr node; 7997 7998 /* 7999 * c-selector-xpath: 8000 * Schema Component Constraint: Selector Value OK 8001 * 8002 * TODO: 1 The {selector} must be a valid XPath expression, as defined 8003 * in [XPath]. 8004 */ 8005 if (selector == NULL) { 8006 xmlSchemaPErr(ctxt, idc->node, 8007 XML_SCHEMAP_INTERNAL, 8008 "Internal error: xmlSchemaCheckCSelectorXPath, " 8009 "the selector is not specified.\n", NULL, NULL); 8010 return (-1); 8011 } 8012 if (attr == NULL) 8013 node = idc->node; 8014 else 8015 node = (xmlNodePtr) attr; 8016 if (selector->xpath == NULL) { 8017 xmlSchemaPCustomErr(ctxt, 8018 /* TODO: Adjust error code. */ 8019 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 8020 NULL, node, 8021 "The XPath expression of the selector is not valid", NULL); 8022 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE); 8023 } else { 8024 const xmlChar **nsArray = NULL; 8025 xmlNsPtr *nsList = NULL; 8026 /* 8027 * Compile the XPath expression. 8028 */ 8029 /* 8030 * TODO: We need the array of in-scope namespaces for compilation. 8031 * TODO: Call xmlPatterncompile with different options for selector/ 8032 * field. 8033 */ 8034 if (attr == NULL) 8035 nsList = NULL; 8036 else 8037 nsList = xmlGetNsList(attr->doc, attr->parent); 8038 /* 8039 * Build an array of prefixes and namespaces. 8040 */ 8041 if (nsList != NULL) { 8042 int i, count = 0; 8043 8044 for (i = 0; nsList[i] != NULL; i++) 8045 count++; 8046 8047 nsArray = (const xmlChar **) xmlMalloc( 8048 (count * 2 + 1) * sizeof(const xmlChar *)); 8049 if (nsArray == NULL) { 8050 xmlSchemaPErrMemory(ctxt, "allocating a namespace array", 8051 NULL); 8052 xmlFree(nsList); 8053 return (-1); 8054 } 8055 for (i = 0; i < count; i++) { 8056 nsArray[2 * i] = nsList[i]->href; 8057 nsArray[2 * i + 1] = nsList[i]->prefix; 8058 } 8059 nsArray[count * 2] = NULL; 8060 xmlFree(nsList); 8061 } 8062 /* 8063 * TODO: Differentiate between "selector" and "field". 8064 */ 8065 if (isField) 8066 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath, 8067 NULL, XML_PATTERN_XSFIELD, nsArray); 8068 else 8069 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath, 8070 NULL, XML_PATTERN_XSSEL, nsArray); 8071 if (nsArray != NULL) 8072 xmlFree((xmlChar **) nsArray); 8073 8074 if (selector->xpathComp == NULL) { 8075 xmlSchemaPCustomErr(ctxt, 8076 /* TODO: Adjust error code? */ 8077 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 8078 NULL, node, 8079 "The XPath expression '%s' could not be " 8080 "compiled", selector->xpath); 8081 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE); 8082 } 8083 } 8084 return (0); 8085} 8086 8087#define ADD_ANNOTATION(annot) \ 8088 xmlSchemaAnnotPtr cur = item->annot; \ 8089 if (item->annot == NULL) { \ 8090 item->annot = annot; \ 8091 return (annot); \ 8092 } \ 8093 cur = item->annot; \ 8094 if (cur->next != NULL) { \ 8095 cur = cur->next; \ 8096 } \ 8097 cur->next = annot; 8098 8099/** 8100 * xmlSchemaAssignAnnotation: 8101 * @item: the schema component 8102 * @annot: the annotation 8103 * 8104 * Adds the annotation to the given schema component. 8105 * 8106 * Returns the given annotaion. 8107 */ 8108static xmlSchemaAnnotPtr 8109xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem, 8110 xmlSchemaAnnotPtr annot) 8111{ 8112 if ((annItem == NULL) || (annot == NULL)) 8113 return (NULL); 8114 switch (annItem->type) { 8115 case XML_SCHEMA_TYPE_ELEMENT: { 8116 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem; 8117 ADD_ANNOTATION(annot) 8118 } 8119 break; 8120 case XML_SCHEMA_TYPE_ATTRIBUTE: { 8121 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem; 8122 ADD_ANNOTATION(annot) 8123 } 8124 break; 8125 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: 8126 case XML_SCHEMA_TYPE_ANY: { 8127 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem; 8128 ADD_ANNOTATION(annot) 8129 } 8130 break; 8131 case XML_SCHEMA_TYPE_PARTICLE: 8132 case XML_SCHEMA_TYPE_IDC_KEY: 8133 case XML_SCHEMA_TYPE_IDC_KEYREF: 8134 case XML_SCHEMA_TYPE_IDC_UNIQUE: { 8135 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem; 8136 ADD_ANNOTATION(annot) 8137 } 8138 break; 8139 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: { 8140 xmlSchemaAttributeGroupPtr item = 8141 (xmlSchemaAttributeGroupPtr) annItem; 8142 ADD_ANNOTATION(annot) 8143 } 8144 break; 8145 case XML_SCHEMA_TYPE_NOTATION: { 8146 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem; 8147 ADD_ANNOTATION(annot) 8148 } 8149 break; 8150 case XML_SCHEMA_FACET_MININCLUSIVE: 8151 case XML_SCHEMA_FACET_MINEXCLUSIVE: 8152 case XML_SCHEMA_FACET_MAXINCLUSIVE: 8153 case XML_SCHEMA_FACET_MAXEXCLUSIVE: 8154 case XML_SCHEMA_FACET_TOTALDIGITS: 8155 case XML_SCHEMA_FACET_FRACTIONDIGITS: 8156 case XML_SCHEMA_FACET_PATTERN: 8157 case XML_SCHEMA_FACET_ENUMERATION: 8158 case XML_SCHEMA_FACET_WHITESPACE: 8159 case XML_SCHEMA_FACET_LENGTH: 8160 case XML_SCHEMA_FACET_MAXLENGTH: 8161 case XML_SCHEMA_FACET_MINLENGTH: { 8162 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem; 8163 ADD_ANNOTATION(annot) 8164 } 8165 break; 8166 case XML_SCHEMA_TYPE_SIMPLE: 8167 case XML_SCHEMA_TYPE_COMPLEX: { 8168 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem; 8169 ADD_ANNOTATION(annot) 8170 } 8171 break; 8172 case XML_SCHEMA_TYPE_GROUP: { 8173 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem; 8174 ADD_ANNOTATION(annot) 8175 } 8176 break; 8177 case XML_SCHEMA_TYPE_SEQUENCE: 8178 case XML_SCHEMA_TYPE_CHOICE: 8179 case XML_SCHEMA_TYPE_ALL: { 8180 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem; 8181 ADD_ANNOTATION(annot) 8182 } 8183 break; 8184 default: 8185 xmlSchemaPCustomErr(NULL, 8186 XML_SCHEMAP_INTERNAL, 8187 NULL, NULL, 8188 "Internal error: xmlSchemaAddAnnotation, " 8189 "The item is not a annotated schema component", NULL); 8190 break; 8191 } 8192 return (annot); 8193} 8194 8195/** 8196 * xmlSchemaParseIDCSelectorAndField: 8197 * @ctxt: a schema validation context 8198 * @schema: the schema being built 8199 * @node: a subtree containing XML Schema informations 8200 * 8201 * Parses a XML Schema identity-contraint definition's 8202 * <selector> and <field> elements. 8203 * 8204 * Returns the parsed identity-constraint definition. 8205 */ 8206static xmlSchemaIDCSelectPtr 8207xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt, 8208 xmlSchemaIDCPtr idc, 8209 xmlNodePtr node, 8210 int isField) 8211{ 8212 xmlSchemaIDCSelectPtr item; 8213 xmlNodePtr child = NULL; 8214 xmlAttrPtr attr; 8215 8216 /* 8217 * Check for illegal attributes. 8218 */ 8219 attr = node->properties; 8220 while (attr != NULL) { 8221 if (attr->ns == NULL) { 8222 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 8223 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) { 8224 xmlSchemaPIllegalAttrErr(ctxt, 8225 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 8226 } 8227 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 8228 xmlSchemaPIllegalAttrErr(ctxt, 8229 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 8230 } 8231 attr = attr->next; 8232 } 8233 /* 8234 * Create the item. 8235 */ 8236 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect)); 8237 if (item == NULL) { 8238 xmlSchemaPErrMemory(ctxt, 8239 "allocating a 'selector' of an identity-constraint definition", 8240 NULL); 8241 return (NULL); 8242 } 8243 memset(item, 0, sizeof(xmlSchemaIDCSelect)); 8244 /* 8245 * Attribute "xpath" (mandatory). 8246 */ 8247 attr = xmlSchemaGetPropNode(node, "xpath"); 8248 if (attr == NULL) { 8249 xmlSchemaPMissingAttrErr(ctxt, 8250 XML_SCHEMAP_S4S_ATTR_MISSING, 8251 NULL, node, 8252 "name", NULL); 8253 } else { 8254 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 8255 /* 8256 * URGENT TODO: "field"s have an other syntax than "selector"s. 8257 */ 8258 8259 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr, 8260 isField) == -1) { 8261 xmlSchemaPErr(ctxt, 8262 (xmlNodePtr) attr, 8263 XML_SCHEMAP_INTERNAL, 8264 "Internal error: xmlSchemaParseIDCSelectorAndField, " 8265 "validating the XPath expression of a IDC selector.\n", 8266 NULL, NULL); 8267 } 8268 8269 } 8270 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 8271 /* 8272 * And now for the children... 8273 */ 8274 child = node->children; 8275 if (IS_SCHEMA(child, "annotation")) { 8276 /* 8277 * Add the annotation to the parent IDC. 8278 */ 8279 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc, 8280 xmlSchemaParseAnnotation(ctxt, child, 1)); 8281 child = child->next; 8282 } 8283 if (child != NULL) { 8284 xmlSchemaPContentErr(ctxt, 8285 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 8286 NULL, node, child, 8287 NULL, "(annotation?)"); 8288 } 8289 8290 return (item); 8291} 8292 8293/** 8294 * xmlSchemaParseIDC: 8295 * @ctxt: a schema validation context 8296 * @schema: the schema being built 8297 * @node: a subtree containing XML Schema informations 8298 * 8299 * Parses a XML Schema identity-contraint definition. 8300 * 8301 * Returns the parsed identity-constraint definition. 8302 */ 8303static xmlSchemaIDCPtr 8304xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt, 8305 xmlSchemaPtr schema, 8306 xmlNodePtr node, 8307 xmlSchemaTypeType idcCategory, 8308 const xmlChar *targetNamespace) 8309{ 8310 xmlSchemaIDCPtr item = NULL; 8311 xmlNodePtr child = NULL; 8312 xmlAttrPtr attr; 8313 const xmlChar *name = NULL; 8314 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL; 8315 8316 /* 8317 * Check for illegal attributes. 8318 */ 8319 attr = node->properties; 8320 while (attr != NULL) { 8321 if (attr->ns == NULL) { 8322 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 8323 (!xmlStrEqual(attr->name, BAD_CAST "name")) && 8324 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) || 8325 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) { 8326 xmlSchemaPIllegalAttrErr(ctxt, 8327 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 8328 } 8329 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 8330 xmlSchemaPIllegalAttrErr(ctxt, 8331 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 8332 } 8333 attr = attr->next; 8334 } 8335 /* 8336 * Attribute "name" (mandatory). 8337 */ 8338 attr = xmlSchemaGetPropNode(node, "name"); 8339 if (attr == NULL) { 8340 xmlSchemaPMissingAttrErr(ctxt, 8341 XML_SCHEMAP_S4S_ATTR_MISSING, 8342 NULL, node, 8343 "name", NULL); 8344 return (NULL); 8345 } else if (xmlSchemaPValAttrNode(ctxt, 8346 NULL, attr, 8347 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { 8348 return (NULL); 8349 } 8350 /* Create the component. */ 8351 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace, 8352 idcCategory, node); 8353 if (item == NULL) 8354 return(NULL); 8355 8356 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 8357 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) { 8358 /* 8359 * Attribute "refer" (mandatory). 8360 */ 8361 attr = xmlSchemaGetPropNode(node, "refer"); 8362 if (attr == NULL) { 8363 xmlSchemaPMissingAttrErr(ctxt, 8364 XML_SCHEMAP_S4S_ATTR_MISSING, 8365 NULL, node, 8366 "refer", NULL); 8367 } else { 8368 /* 8369 * Create a reference item. 8370 */ 8371 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY, 8372 NULL, NULL); 8373 if (item->ref == NULL) 8374 return (NULL); 8375 xmlSchemaPValAttrNodeQName(ctxt, schema, 8376 NULL, attr, 8377 &(item->ref->targetNamespace), 8378 &(item->ref->name)); 8379 xmlSchemaCheckReference(ctxt, schema, node, attr, 8380 item->ref->targetNamespace); 8381 } 8382 } 8383 /* 8384 * And now for the children... 8385 */ 8386 child = node->children; 8387 if (IS_SCHEMA(child, "annotation")) { 8388 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); 8389 child = child->next; 8390 } 8391 if (child == NULL) { 8392 xmlSchemaPContentErr(ctxt, 8393 XML_SCHEMAP_S4S_ELEM_MISSING, 8394 NULL, node, child, 8395 "A child element is missing", 8396 "(annotation?, (selector, field+))"); 8397 } 8398 /* 8399 * Child element <selector>. 8400 */ 8401 if (IS_SCHEMA(child, "selector")) { 8402 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, 8403 item, child, 0); 8404 child = child->next; 8405 /* 8406 * Child elements <field>. 8407 */ 8408 if (IS_SCHEMA(child, "field")) { 8409 do { 8410 field = xmlSchemaParseIDCSelectorAndField(ctxt, 8411 item, child, 1); 8412 if (field != NULL) { 8413 field->index = item->nbFields; 8414 item->nbFields++; 8415 if (lastField != NULL) 8416 lastField->next = field; 8417 else 8418 item->fields = field; 8419 lastField = field; 8420 } 8421 child = child->next; 8422 } while (IS_SCHEMA(child, "field")); 8423 } else { 8424 xmlSchemaPContentErr(ctxt, 8425 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 8426 NULL, node, child, 8427 NULL, "(annotation?, (selector, field+))"); 8428 } 8429 } 8430 if (child != NULL) { 8431 xmlSchemaPContentErr(ctxt, 8432 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 8433 NULL, node, child, 8434 NULL, "(annotation?, (selector, field+))"); 8435 } 8436 8437 return (item); 8438} 8439 8440/** 8441 * xmlSchemaParseElement: 8442 * @ctxt: a schema validation context 8443 * @schema: the schema being built 8444 * @node: a subtree containing XML Schema informations 8445 * @topLevel: indicates if this is global declaration 8446 * 8447 * Parses a XML schema element declaration. 8448 * *WARNING* this interface is highly subject to change 8449 * 8450 * Returns the element declaration or a particle; NULL in case 8451 * of an error or if the particle has minOccurs==maxOccurs==0. 8452 */ 8453static xmlSchemaBasicItemPtr 8454xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 8455 xmlNodePtr node, int *isElemRef, int topLevel) 8456{ 8457 xmlSchemaElementPtr decl = NULL; 8458 xmlSchemaParticlePtr particle = NULL; 8459 xmlSchemaAnnotPtr annot = NULL; 8460 xmlNodePtr child = NULL; 8461 xmlAttrPtr attr, nameAttr; 8462 int min, max, isRef = 0; 8463 xmlChar *des = NULL; 8464 8465 /* 3.3.3 Constraints on XML Representations of Element Declarations */ 8466 /* TODO: Complete implementation of 3.3.6 */ 8467 8468 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 8469 return (NULL); 8470 8471 if (isElemRef != NULL) 8472 *isElemRef = 0; 8473 /* 8474 * If we get a "ref" attribute on a local <element> we will assume it's 8475 * a reference - even if there's a "name" attribute; this seems to be more 8476 * robust. 8477 */ 8478 nameAttr = xmlSchemaGetPropNode(node, "name"); 8479 attr = xmlSchemaGetPropNode(node, "ref"); 8480 if ((topLevel) || (attr == NULL)) { 8481 if (nameAttr == NULL) { 8482 xmlSchemaPMissingAttrErr(ctxt, 8483 XML_SCHEMAP_S4S_ATTR_MISSING, 8484 NULL, node, "name", NULL); 8485 return (NULL); 8486 } 8487 } else 8488 isRef = 1; 8489 8490 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 8491 child = node->children; 8492 if (IS_SCHEMA(child, "annotation")) { 8493 annot = xmlSchemaParseAnnotation(ctxt, child, 1); 8494 child = child->next; 8495 } 8496 /* 8497 * Skip particle part if a global declaration. 8498 */ 8499 if (topLevel) 8500 goto declaration_part; 8501 /* 8502 * The particle part ================================================== 8503 */ 8504 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger"); 8505 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)"); 8506 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max); 8507 particle = xmlSchemaAddParticle(ctxt, node, min, max); 8508 if (particle == NULL) 8509 goto return_null; 8510 8511 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */ 8512 8513 if (isRef) { 8514 const xmlChar *refNs = NULL, *ref = NULL; 8515 xmlSchemaQNameRefPtr refer = NULL; 8516 /* 8517 * The reference part ============================================= 8518 */ 8519 if (isElemRef != NULL) 8520 *isElemRef = 1; 8521 8522 xmlSchemaPValAttrNodeQName(ctxt, schema, 8523 NULL, attr, &refNs, &ref); 8524 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs); 8525 /* 8526 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both" 8527 */ 8528 if (nameAttr != NULL) { 8529 xmlSchemaPMutualExclAttrErr(ctxt, 8530 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name"); 8531 } 8532 /* 8533 * Check for illegal attributes. 8534 */ 8535 attr = node->properties; 8536 while (attr != NULL) { 8537 if (attr->ns == NULL) { 8538 if (xmlStrEqual(attr->name, BAD_CAST "ref") || 8539 xmlStrEqual(attr->name, BAD_CAST "name") || 8540 xmlStrEqual(attr->name, BAD_CAST "id") || 8541 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") || 8542 xmlStrEqual(attr->name, BAD_CAST "minOccurs")) 8543 { 8544 attr = attr->next; 8545 continue; 8546 } else { 8547 /* SPEC (3.3.3 : 2.2) */ 8548 xmlSchemaPCustomAttrErr(ctxt, 8549 XML_SCHEMAP_SRC_ELEMENT_2_2, 8550 NULL, NULL, attr, 8551 "Only the attributes 'minOccurs', 'maxOccurs' and " 8552 "'id' are allowed in addition to 'ref'"); 8553 break; 8554 } 8555 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 8556 xmlSchemaPIllegalAttrErr(ctxt, 8557 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 8558 } 8559 attr = attr->next; 8560 } 8561 /* 8562 * No children except <annotation> expected. 8563 */ 8564 if (child != NULL) { 8565 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 8566 NULL, node, child, NULL, "(annotation?)"); 8567 } 8568 if ((min == 0) && (max == 0)) 8569 goto return_null; 8570 /* 8571 * Create the reference item and attach it to the particle. 8572 */ 8573 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT, 8574 ref, refNs); 8575 if (refer == NULL) 8576 goto return_null; 8577 particle->children = (xmlSchemaTreeItemPtr) refer; 8578 particle->annot = annot; 8579 /* 8580 * Add the particle to pending components, since the reference 8581 * need to be resolved. 8582 */ 8583 WXS_ADD_PENDING(ctxt, particle); 8584 return ((xmlSchemaBasicItemPtr) particle); 8585 } 8586 /* 8587 * The declaration part =============================================== 8588 */ 8589declaration_part: 8590 { 8591 const xmlChar *ns = NULL, *fixed, *name, *attrValue; 8592 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL; 8593 8594 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr, 8595 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) 8596 goto return_null; 8597 /* 8598 * Evaluate the target namespace. 8599 */ 8600 if (topLevel) { 8601 ns = ctxt->targetNamespace; 8602 } else { 8603 attr = xmlSchemaGetPropNode(node, "form"); 8604 if (attr != NULL) { 8605 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 8606 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) { 8607 ns = ctxt->targetNamespace; 8608 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) { 8609 xmlSchemaPSimpleTypeErr(ctxt, 8610 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 8611 NULL, (xmlNodePtr) attr, 8612 NULL, "(qualified | unqualified)", 8613 attrValue, NULL, NULL, NULL); 8614 } 8615 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM) 8616 ns = ctxt->targetNamespace; 8617 } 8618 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel); 8619 if (decl == NULL) { 8620 goto return_null; 8621 } 8622 /* 8623 * Check for illegal attributes. 8624 */ 8625 attr = node->properties; 8626 while (attr != NULL) { 8627 if (attr->ns == NULL) { 8628 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) && 8629 (!xmlStrEqual(attr->name, BAD_CAST "type")) && 8630 (!xmlStrEqual(attr->name, BAD_CAST "id")) && 8631 (!xmlStrEqual(attr->name, BAD_CAST "default")) && 8632 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) && 8633 (!xmlStrEqual(attr->name, BAD_CAST "block")) && 8634 (!xmlStrEqual(attr->name, BAD_CAST "nillable"))) 8635 { 8636 if (topLevel == 0) { 8637 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) && 8638 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) && 8639 (!xmlStrEqual(attr->name, BAD_CAST "form"))) 8640 { 8641 xmlSchemaPIllegalAttrErr(ctxt, 8642 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 8643 } 8644 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) && 8645 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) && 8646 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) { 8647 8648 xmlSchemaPIllegalAttrErr(ctxt, 8649 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 8650 } 8651 } 8652 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 8653 8654 xmlSchemaPIllegalAttrErr(ctxt, 8655 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 8656 } 8657 attr = attr->next; 8658 } 8659 /* 8660 * Extract/validate attributes. 8661 */ 8662 if (topLevel) { 8663 /* 8664 * Process top attributes of global element declarations here. 8665 */ 8666 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL; 8667 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL; 8668 xmlSchemaPValAttrQName(ctxt, schema, 8669 NULL, node, "substitutionGroup", 8670 &(decl->substGroupNs), &(decl->substGroup)); 8671 if (xmlGetBooleanProp(ctxt, node, "abstract", 0)) 8672 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT; 8673 /* 8674 * Attribute "final". 8675 */ 8676 attr = xmlSchemaGetPropNode(node, "final"); 8677 if (attr == NULL) { 8678 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) 8679 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION; 8680 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) 8681 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION; 8682 } else { 8683 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 8684 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags), 8685 -1, 8686 XML_SCHEMAS_ELEM_FINAL_EXTENSION, 8687 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) { 8688 xmlSchemaPSimpleTypeErr(ctxt, 8689 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 8690 NULL, (xmlNodePtr) attr, 8691 NULL, "(#all | List of (extension | restriction))", 8692 attrValue, NULL, NULL, NULL); 8693 } 8694 } 8695 } 8696 /* 8697 * Attribute "block". 8698 */ 8699 attr = xmlSchemaGetPropNode(node, "block"); 8700 if (attr == NULL) { 8701 /* 8702 * Apply default "block" values. 8703 */ 8704 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION) 8705 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION; 8706 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION) 8707 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION; 8708 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION) 8709 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION; 8710 } else { 8711 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 8712 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags), 8713 -1, 8714 XML_SCHEMAS_ELEM_BLOCK_EXTENSION, 8715 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION, 8716 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) { 8717 xmlSchemaPSimpleTypeErr(ctxt, 8718 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 8719 NULL, (xmlNodePtr) attr, 8720 NULL, "(#all | List of (extension | " 8721 "restriction | substitution))", attrValue, 8722 NULL, NULL, NULL); 8723 } 8724 } 8725 if (xmlGetBooleanProp(ctxt, node, "nillable", 0)) 8726 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE; 8727 8728 attr = xmlSchemaGetPropNode(node, "type"); 8729 if (attr != NULL) { 8730 xmlSchemaPValAttrNodeQName(ctxt, schema, 8731 NULL, attr, 8732 &(decl->namedTypeNs), &(decl->namedType)); 8733 xmlSchemaCheckReference(ctxt, schema, node, 8734 attr, decl->namedTypeNs); 8735 } 8736 decl->value = xmlSchemaGetProp(ctxt, node, "default"); 8737 attr = xmlSchemaGetPropNode(node, "fixed"); 8738 if (attr != NULL) { 8739 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 8740 if (decl->value != NULL) { 8741 /* 8742 * 3.3.3 : 1 8743 * default and fixed must not both be present. 8744 */ 8745 xmlSchemaPMutualExclAttrErr(ctxt, 8746 XML_SCHEMAP_SRC_ELEMENT_1, 8747 NULL, attr, "default", "fixed"); 8748 } else { 8749 decl->flags |= XML_SCHEMAS_ELEM_FIXED; 8750 decl->value = fixed; 8751 } 8752 } 8753 /* 8754 * And now for the children... 8755 */ 8756 if (IS_SCHEMA(child, "complexType")) { 8757 /* 8758 * 3.3.3 : 3 8759 * "type" and either <simpleType> or <complexType> are mutually 8760 * exclusive 8761 */ 8762 if (decl->namedType != NULL) { 8763 xmlSchemaPContentErr(ctxt, 8764 XML_SCHEMAP_SRC_ELEMENT_3, 8765 NULL, node, child, 8766 "The attribute 'type' and the <complexType> child are " 8767 "mutually exclusive", NULL); 8768 } else 8769 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0); 8770 child = child->next; 8771 } else if (IS_SCHEMA(child, "simpleType")) { 8772 /* 8773 * 3.3.3 : 3 8774 * "type" and either <simpleType> or <complexType> are 8775 * mutually exclusive 8776 */ 8777 if (decl->namedType != NULL) { 8778 xmlSchemaPContentErr(ctxt, 8779 XML_SCHEMAP_SRC_ELEMENT_3, 8780 NULL, node, child, 8781 "The attribute 'type' and the <simpleType> child are " 8782 "mutually exclusive", NULL); 8783 } else 8784 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0); 8785 child = child->next; 8786 } 8787 while ((IS_SCHEMA(child, "unique")) || 8788 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) { 8789 if (IS_SCHEMA(child, "unique")) { 8790 curIDC = xmlSchemaParseIDC(ctxt, schema, child, 8791 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace); 8792 } else if (IS_SCHEMA(child, "key")) { 8793 curIDC = xmlSchemaParseIDC(ctxt, schema, child, 8794 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace); 8795 } else if (IS_SCHEMA(child, "keyref")) { 8796 curIDC = xmlSchemaParseIDC(ctxt, schema, child, 8797 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace); 8798 } 8799 if (lastIDC != NULL) 8800 lastIDC->next = curIDC; 8801 else 8802 decl->idcs = (void *) curIDC; 8803 lastIDC = curIDC; 8804 child = child->next; 8805 } 8806 if (child != NULL) { 8807 xmlSchemaPContentErr(ctxt, 8808 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 8809 NULL, node, child, 8810 NULL, "(annotation?, ((simpleType | complexType)?, " 8811 "(unique | key | keyref)*))"); 8812 } 8813 decl->annot = annot; 8814 } 8815 /* 8816 * NOTE: Element Declaration Representation OK 4. will be checked at a 8817 * different layer. 8818 */ 8819 FREE_AND_NULL(des) 8820 if (topLevel) 8821 return ((xmlSchemaBasicItemPtr) decl); 8822 else { 8823 particle->children = (xmlSchemaTreeItemPtr) decl; 8824 return ((xmlSchemaBasicItemPtr) particle); 8825 } 8826 8827return_null: 8828 FREE_AND_NULL(des); 8829 if (annot != NULL) { 8830 if (particle != NULL) 8831 particle->annot = NULL; 8832 if (decl != NULL) 8833 decl->annot = NULL; 8834 xmlSchemaFreeAnnot(annot); 8835 } 8836 return (NULL); 8837} 8838 8839/** 8840 * xmlSchemaParseUnion: 8841 * @ctxt: a schema validation context 8842 * @schema: the schema being built 8843 * @node: a subtree containing XML Schema informations 8844 * 8845 * parse a XML schema Union definition 8846 * *WARNING* this interface is highly subject to change 8847 * 8848 * Returns -1 in case of internal error, 0 in case of success and a positive 8849 * error code otherwise. 8850 */ 8851static int 8852xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 8853 xmlNodePtr node) 8854{ 8855 xmlSchemaTypePtr type; 8856 xmlNodePtr child = NULL; 8857 xmlAttrPtr attr; 8858 const xmlChar *cur = NULL; 8859 8860 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 8861 return (-1); 8862 /* Not a component, don't create it. */ 8863 type = ctxt->ctxtType; 8864 /* 8865 * Mark the simple type as being of variety "union". 8866 */ 8867 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION; 8868 /* 8869 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen, 8870 * then the �simple ur-type definition�." 8871 */ 8872 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE); 8873 /* 8874 * Check for illegal attributes. 8875 */ 8876 attr = node->properties; 8877 while (attr != NULL) { 8878 if (attr->ns == NULL) { 8879 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 8880 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) { 8881 xmlSchemaPIllegalAttrErr(ctxt, 8882 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 8883 } 8884 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 8885 xmlSchemaPIllegalAttrErr(ctxt, 8886 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 8887 } 8888 attr = attr->next; 8889 } 8890 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 8891 /* 8892 * Attribute "memberTypes". This is a list of QNames. 8893 * TODO: Check the value to contain anything. 8894 */ 8895 attr = xmlSchemaGetPropNode(node, "memberTypes"); 8896 if (attr != NULL) { 8897 const xmlChar *end; 8898 xmlChar *tmp; 8899 const xmlChar *localName, *nsName; 8900 xmlSchemaTypeLinkPtr link, lastLink = NULL; 8901 xmlSchemaQNameRefPtr ref; 8902 8903 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 8904 type->base = cur; 8905 do { 8906 while (IS_BLANK_CH(*cur)) 8907 cur++; 8908 end = cur; 8909 while ((*end != 0) && (!(IS_BLANK_CH(*end)))) 8910 end++; 8911 if (end == cur) 8912 break; 8913 tmp = xmlStrndup(cur, end - cur); 8914 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, 8915 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) { 8916 /* 8917 * Create the member type link. 8918 */ 8919 link = (xmlSchemaTypeLinkPtr) 8920 xmlMalloc(sizeof(xmlSchemaTypeLink)); 8921 if (link == NULL) { 8922 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, " 8923 "allocating a type link", NULL); 8924 return (-1); 8925 } 8926 link->type = NULL; 8927 link->next = NULL; 8928 if (lastLink == NULL) 8929 type->memberTypes = link; 8930 else 8931 lastLink->next = link; 8932 lastLink = link; 8933 /* 8934 * Create a reference item. 8935 */ 8936 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE, 8937 localName, nsName); 8938 if (ref == NULL) { 8939 FREE_AND_NULL(tmp) 8940 return (-1); 8941 } 8942 /* 8943 * Assign the reference to the link, it will be resolved 8944 * later during fixup of the union simple type. 8945 */ 8946 link->type = (xmlSchemaTypePtr) ref; 8947 } 8948 FREE_AND_NULL(tmp) 8949 cur = end; 8950 } while (*cur != 0); 8951 8952 } 8953 /* 8954 * And now for the children... 8955 */ 8956 child = node->children; 8957 if (IS_SCHEMA(child, "annotation")) { 8958 /* 8959 * Add the annotation to the simple type ancestor. 8960 */ 8961 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, 8962 xmlSchemaParseAnnotation(ctxt, child, 1)); 8963 child = child->next; 8964 } 8965 if (IS_SCHEMA(child, "simpleType")) { 8966 xmlSchemaTypePtr subtype, last = NULL; 8967 8968 /* 8969 * Anchor the member types in the "subtypes" field of the 8970 * simple type. 8971 */ 8972 while (IS_SCHEMA(child, "simpleType")) { 8973 subtype = (xmlSchemaTypePtr) 8974 xmlSchemaParseSimpleType(ctxt, schema, child, 0); 8975 if (subtype != NULL) { 8976 if (last == NULL) { 8977 type->subtypes = subtype; 8978 last = subtype; 8979 } else { 8980 last->next = subtype; 8981 last = subtype; 8982 } 8983 last->next = NULL; 8984 } 8985 child = child->next; 8986 } 8987 } 8988 if (child != NULL) { 8989 xmlSchemaPContentErr(ctxt, 8990 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 8991 NULL, node, child, NULL, "(annotation?, simpleType*)"); 8992 } 8993 if ((attr == NULL) && (type->subtypes == NULL)) { 8994 /* 8995 * src-union-memberTypes-or-simpleTypes 8996 * Either the memberTypes [attribute] of the <union> element must 8997 * be non-empty or there must be at least one simpleType [child]. 8998 */ 8999 xmlSchemaPCustomErr(ctxt, 9000 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES, 9001 NULL, node, 9002 "Either the attribute 'memberTypes' or " 9003 "at least one <simpleType> child must be present", NULL); 9004 } 9005 return (0); 9006} 9007 9008/** 9009 * xmlSchemaParseList: 9010 * @ctxt: a schema validation context 9011 * @schema: the schema being built 9012 * @node: a subtree containing XML Schema informations 9013 * 9014 * parse a XML schema List definition 9015 * *WARNING* this interface is highly subject to change 9016 * 9017 * Returns -1 in case of error, 0 if the declaration is improper and 9018 * 1 in case of success. 9019 */ 9020static xmlSchemaTypePtr 9021xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 9022 xmlNodePtr node) 9023{ 9024 xmlSchemaTypePtr type; 9025 xmlNodePtr child = NULL; 9026 xmlAttrPtr attr; 9027 9028 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 9029 return (NULL); 9030 /* Not a component, don't create it. */ 9031 type = ctxt->ctxtType; 9032 /* 9033 * Mark the type as being of variety "list". 9034 */ 9035 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST; 9036 /* 9037 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen, 9038 * then the �simple ur-type definition�." 9039 */ 9040 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE); 9041 /* 9042 * Check for illegal attributes. 9043 */ 9044 attr = node->properties; 9045 while (attr != NULL) { 9046 if (attr->ns == NULL) { 9047 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 9048 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) { 9049 xmlSchemaPIllegalAttrErr(ctxt, 9050 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 9051 } 9052 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 9053 xmlSchemaPIllegalAttrErr(ctxt, 9054 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 9055 } 9056 attr = attr->next; 9057 } 9058 9059 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 9060 9061 /* 9062 * Attribute "itemType". NOTE that we will use the "ref" and "refNs" 9063 * fields for holding the reference to the itemType. 9064 * 9065 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove 9066 * the "ref" fields. 9067 */ 9068 xmlSchemaPValAttrQName(ctxt, schema, NULL, 9069 node, "itemType", &(type->baseNs), &(type->base)); 9070 /* 9071 * And now for the children... 9072 */ 9073 child = node->children; 9074 if (IS_SCHEMA(child, "annotation")) { 9075 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, 9076 xmlSchemaParseAnnotation(ctxt, child, 1)); 9077 child = child->next; 9078 } 9079 if (IS_SCHEMA(child, "simpleType")) { 9080 /* 9081 * src-list-itemType-or-simpleType 9082 * Either the itemType [attribute] or the <simpleType> [child] of 9083 * the <list> element must be present, but not both. 9084 */ 9085 if (type->base != NULL) { 9086 xmlSchemaPCustomErr(ctxt, 9087 XML_SCHEMAP_SRC_SIMPLE_TYPE_1, 9088 NULL, node, 9089 "The attribute 'itemType' and the <simpleType> child " 9090 "are mutually exclusive", NULL); 9091 } else { 9092 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0); 9093 } 9094 child = child->next; 9095 } else if (type->base == NULL) { 9096 xmlSchemaPCustomErr(ctxt, 9097 XML_SCHEMAP_SRC_SIMPLE_TYPE_1, 9098 NULL, node, 9099 "Either the attribute 'itemType' or the <simpleType> child " 9100 "must be present", NULL); 9101 } 9102 if (child != NULL) { 9103 xmlSchemaPContentErr(ctxt, 9104 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 9105 NULL, node, child, NULL, "(annotation?, simpleType?)"); 9106 } 9107 if ((type->base == NULL) && 9108 (type->subtypes == NULL) && 9109 (xmlSchemaGetPropNode(node, "itemType") == NULL)) { 9110 xmlSchemaPCustomErr(ctxt, 9111 XML_SCHEMAP_SRC_SIMPLE_TYPE_1, 9112 NULL, node, 9113 "Either the attribute 'itemType' or the <simpleType> child " 9114 "must be present", NULL); 9115 } 9116 return (NULL); 9117} 9118 9119/** 9120 * xmlSchemaParseSimpleType: 9121 * @ctxt: a schema validation context 9122 * @schema: the schema being built 9123 * @node: a subtree containing XML Schema informations 9124 * 9125 * parse a XML schema Simple Type definition 9126 * *WARNING* this interface is highly subject to change 9127 * 9128 * Returns -1 in case of error, 0 if the declaration is improper and 9129 * 1 in case of success. 9130 */ 9131static xmlSchemaTypePtr 9132xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 9133 xmlNodePtr node, int topLevel) 9134{ 9135 xmlSchemaTypePtr type, oldCtxtType; 9136 xmlNodePtr child = NULL; 9137 const xmlChar *attrValue = NULL; 9138 xmlAttrPtr attr; 9139 int hasRestriction = 0; 9140 9141 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 9142 return (NULL); 9143 9144 if (topLevel) { 9145 attr = xmlSchemaGetPropNode(node, "name"); 9146 if (attr == NULL) { 9147 xmlSchemaPMissingAttrErr(ctxt, 9148 XML_SCHEMAP_S4S_ATTR_MISSING, 9149 NULL, node, 9150 "name", NULL); 9151 return (NULL); 9152 } else { 9153 if (xmlSchemaPValAttrNode(ctxt, 9154 NULL, attr, 9155 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) 9156 return (NULL); 9157 /* 9158 * Skip built-in types. 9159 */ 9160 if (ctxt->isS4S) { 9161 xmlSchemaTypePtr biType; 9162 9163 if (ctxt->isRedefine) { 9164 /* 9165 * REDEFINE: Disallow redefinition of built-in-types. 9166 * TODO: It seems that the spec does not say anything 9167 * about this case. 9168 */ 9169 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, 9170 NULL, node, 9171 "Redefinition of built-in simple types is not " 9172 "supported", NULL); 9173 return(NULL); 9174 } 9175 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs); 9176 if (biType != NULL) 9177 return (biType); 9178 } 9179 } 9180 } 9181 /* 9182 * TargetNamespace: 9183 * SPEC "The �actual value� of the targetNamespace [attribute] 9184 * of the <schema> ancestor element information item if present, 9185 * otherwise �absent�. 9186 */ 9187 if (topLevel == 0) { 9188#ifdef ENABLE_NAMED_LOCALS 9189 char buf[40]; 9190#endif 9191 /* 9192 * Parse as local simple type definition. 9193 */ 9194#ifdef ENABLE_NAMED_LOCALS 9195 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1); 9196 type = xmlSchemaAddType(ctxt, schema, 9197 XML_SCHEMA_TYPE_SIMPLE, 9198 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1), 9199 ctxt->targetNamespace, node, 0); 9200#else 9201 type = xmlSchemaAddType(ctxt, schema, 9202 XML_SCHEMA_TYPE_SIMPLE, 9203 NULL, ctxt->targetNamespace, node, 0); 9204#endif 9205 if (type == NULL) 9206 return (NULL); 9207 type->type = XML_SCHEMA_TYPE_SIMPLE; 9208 type->contentType = XML_SCHEMA_CONTENT_SIMPLE; 9209 /* 9210 * Check for illegal attributes. 9211 */ 9212 attr = node->properties; 9213 while (attr != NULL) { 9214 if (attr->ns == NULL) { 9215 if (!xmlStrEqual(attr->name, BAD_CAST "id")) { 9216 xmlSchemaPIllegalAttrErr(ctxt, 9217 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 9218 } 9219 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 9220 xmlSchemaPIllegalAttrErr(ctxt, 9221 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 9222 } 9223 attr = attr->next; 9224 } 9225 } else { 9226 /* 9227 * Parse as global simple type definition. 9228 * 9229 * Note that attrValue is the value of the attribute "name" here. 9230 */ 9231 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE, 9232 attrValue, ctxt->targetNamespace, node, 1); 9233 if (type == NULL) 9234 return (NULL); 9235 type->type = XML_SCHEMA_TYPE_SIMPLE; 9236 type->contentType = XML_SCHEMA_CONTENT_SIMPLE; 9237 type->flags |= XML_SCHEMAS_TYPE_GLOBAL; 9238 /* 9239 * Check for illegal attributes. 9240 */ 9241 attr = node->properties; 9242 while (attr != NULL) { 9243 if (attr->ns == NULL) { 9244 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 9245 (!xmlStrEqual(attr->name, BAD_CAST "name")) && 9246 (!xmlStrEqual(attr->name, BAD_CAST "final"))) { 9247 xmlSchemaPIllegalAttrErr(ctxt, 9248 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 9249 } 9250 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 9251 xmlSchemaPIllegalAttrErr(ctxt, 9252 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 9253 } 9254 attr = attr->next; 9255 } 9256 /* 9257 * Attribute "final". 9258 */ 9259 attr = xmlSchemaGetPropNode(node, "final"); 9260 if (attr == NULL) { 9261 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) 9262 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION; 9263 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST) 9264 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST; 9265 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION) 9266 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION; 9267 } else { 9268 attrValue = xmlSchemaGetProp(ctxt, node, "final"); 9269 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags), 9270 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1, 9271 XML_SCHEMAS_TYPE_FINAL_LIST, 9272 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) { 9273 9274 xmlSchemaPSimpleTypeErr(ctxt, 9275 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 9276 WXS_BASIC_CAST type, (xmlNodePtr) attr, 9277 NULL, "(#all | List of (list | union | restriction)", 9278 attrValue, NULL, NULL, NULL); 9279 } 9280 } 9281 } 9282 type->targetNamespace = ctxt->targetNamespace; 9283 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 9284 /* 9285 * And now for the children... 9286 */ 9287 oldCtxtType = ctxt->ctxtType; 9288 9289 ctxt->ctxtType = type; 9290 9291 child = node->children; 9292 if (IS_SCHEMA(child, "annotation")) { 9293 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1); 9294 child = child->next; 9295 } 9296 if (child == NULL) { 9297 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING, 9298 NULL, node, child, NULL, 9299 "(annotation?, (restriction | list | union))"); 9300 } else if (IS_SCHEMA(child, "restriction")) { 9301 xmlSchemaParseRestriction(ctxt, schema, child, 9302 XML_SCHEMA_TYPE_SIMPLE); 9303 hasRestriction = 1; 9304 child = child->next; 9305 } else if (IS_SCHEMA(child, "list")) { 9306 xmlSchemaParseList(ctxt, schema, child); 9307 child = child->next; 9308 } else if (IS_SCHEMA(child, "union")) { 9309 xmlSchemaParseUnion(ctxt, schema, child); 9310 child = child->next; 9311 } 9312 if (child != NULL) { 9313 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 9314 NULL, node, child, NULL, 9315 "(annotation?, (restriction | list | union))"); 9316 } 9317 /* 9318 * REDEFINE: SPEC src-redefine (5) 9319 * "Within the [children], each <simpleType> must have a 9320 * <restriction> among its [children] ... the �actual value� of whose 9321 * base [attribute] must be the same as the �actual value� of its own 9322 * name attribute plus target namespace;" 9323 */ 9324 if (topLevel && ctxt->isRedefine && (! hasRestriction)) { 9325 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, 9326 NULL, node, "This is a redefinition, thus the " 9327 "<simpleType> must have a <restriction> child", NULL); 9328 } 9329 9330 ctxt->ctxtType = oldCtxtType; 9331 return (type); 9332} 9333 9334/** 9335 * xmlSchemaParseModelGroupDefRef: 9336 * @ctxt: the parser context 9337 * @schema: the schema being built 9338 * @node: the node 9339 * 9340 * Parses a reference to a model group definition. 9341 * 9342 * We will return a particle component with a qname-component or 9343 * NULL in case of an error. 9344 */ 9345static xmlSchemaTreeItemPtr 9346xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt, 9347 xmlSchemaPtr schema, 9348 xmlNodePtr node) 9349{ 9350 xmlSchemaParticlePtr item; 9351 xmlNodePtr child = NULL; 9352 xmlAttrPtr attr; 9353 const xmlChar *ref = NULL, *refNs = NULL; 9354 int min, max; 9355 9356 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 9357 return (NULL); 9358 9359 attr = xmlSchemaGetPropNode(node, "ref"); 9360 if (attr == NULL) { 9361 xmlSchemaPMissingAttrErr(ctxt, 9362 XML_SCHEMAP_S4S_ATTR_MISSING, 9363 NULL, node, "ref", NULL); 9364 return (NULL); 9365 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, 9366 attr, &refNs, &ref) != 0) { 9367 return (NULL); 9368 } 9369 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs); 9370 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger"); 9371 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, 9372 "(xs:nonNegativeInteger | unbounded)"); 9373 /* 9374 * Check for illegal attributes. 9375 */ 9376 attr = node->properties; 9377 while (attr != NULL) { 9378 if (attr->ns == NULL) { 9379 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) && 9380 (!xmlStrEqual(attr->name, BAD_CAST "id")) && 9381 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) && 9382 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) { 9383 xmlSchemaPIllegalAttrErr(ctxt, 9384 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 9385 } 9386 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 9387 xmlSchemaPIllegalAttrErr(ctxt, 9388 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 9389 } 9390 attr = attr->next; 9391 } 9392 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 9393 item = xmlSchemaAddParticle(ctxt, node, min, max); 9394 if (item == NULL) 9395 return (NULL); 9396 /* 9397 * Create a qname-reference and set as the term; it will be substituted 9398 * for the model group after the reference has been resolved. 9399 */ 9400 item->children = (xmlSchemaTreeItemPtr) 9401 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs); 9402 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max); 9403 /* 9404 * And now for the children... 9405 */ 9406 child = node->children; 9407 /* TODO: Is annotation even allowed for a model group reference? */ 9408 if (IS_SCHEMA(child, "annotation")) { 9409 /* 9410 * TODO: What to do exactly with the annotation? 9411 */ 9412 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); 9413 child = child->next; 9414 } 9415 if (child != NULL) { 9416 xmlSchemaPContentErr(ctxt, 9417 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 9418 NULL, node, child, NULL, 9419 "(annotation?)"); 9420 } 9421 /* 9422 * Corresponds to no component at all if minOccurs==maxOccurs==0. 9423 */ 9424 if ((min == 0) && (max == 0)) 9425 return (NULL); 9426 9427 return ((xmlSchemaTreeItemPtr) item); 9428} 9429 9430/** 9431 * xmlSchemaParseModelGroupDefinition: 9432 * @ctxt: a schema validation context 9433 * @schema: the schema being built 9434 * @node: a subtree containing XML Schema informations 9435 * 9436 * Parses a XML schema model group definition. 9437 * 9438 * Note that the contraint src-redefine (6.2) can't be applied until 9439 * references have been resolved. So we will do this at the 9440 * component fixup level. 9441 * 9442 * *WARNING* this interface is highly subject to change 9443 * 9444 * Returns -1 in case of error, 0 if the declaration is improper and 9445 * 1 in case of success. 9446 */ 9447static xmlSchemaModelGroupDefPtr 9448xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt, 9449 xmlSchemaPtr schema, 9450 xmlNodePtr node) 9451{ 9452 xmlSchemaModelGroupDefPtr item; 9453 xmlNodePtr child = NULL; 9454 xmlAttrPtr attr; 9455 const xmlChar *name; 9456 9457 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 9458 return (NULL); 9459 9460 attr = xmlSchemaGetPropNode(node, "name"); 9461 if (attr == NULL) { 9462 xmlSchemaPMissingAttrErr(ctxt, 9463 XML_SCHEMAP_S4S_ATTR_MISSING, 9464 NULL, node, 9465 "name", NULL); 9466 return (NULL); 9467 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr, 9468 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { 9469 return (NULL); 9470 } 9471 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name, 9472 ctxt->targetNamespace, node); 9473 if (item == NULL) 9474 return (NULL); 9475 /* 9476 * Check for illegal attributes. 9477 */ 9478 attr = node->properties; 9479 while (attr != NULL) { 9480 if (attr->ns == NULL) { 9481 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) && 9482 (!xmlStrEqual(attr->name, BAD_CAST "id"))) { 9483 xmlSchemaPIllegalAttrErr(ctxt, 9484 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 9485 } 9486 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 9487 xmlSchemaPIllegalAttrErr(ctxt, 9488 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 9489 } 9490 attr = attr->next; 9491 } 9492 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 9493 /* 9494 * And now for the children... 9495 */ 9496 child = node->children; 9497 if (IS_SCHEMA(child, "annotation")) { 9498 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); 9499 child = child->next; 9500 } 9501 if (IS_SCHEMA(child, "all")) { 9502 item->children = xmlSchemaParseModelGroup(ctxt, schema, child, 9503 XML_SCHEMA_TYPE_ALL, 0); 9504 child = child->next; 9505 } else if (IS_SCHEMA(child, "choice")) { 9506 item->children = xmlSchemaParseModelGroup(ctxt, schema, child, 9507 XML_SCHEMA_TYPE_CHOICE, 0); 9508 child = child->next; 9509 } else if (IS_SCHEMA(child, "sequence")) { 9510 item->children = xmlSchemaParseModelGroup(ctxt, schema, child, 9511 XML_SCHEMA_TYPE_SEQUENCE, 0); 9512 child = child->next; 9513 } 9514 9515 9516 9517 if (child != NULL) { 9518 xmlSchemaPContentErr(ctxt, 9519 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 9520 NULL, node, child, NULL, 9521 "(annotation?, (all | choice | sequence)?)"); 9522 } 9523 return (item); 9524} 9525 9526/** 9527 * xmlSchemaCleanupDoc: 9528 * @ctxt: a schema validation context 9529 * @node: the root of the document. 9530 * 9531 * removes unwanted nodes in a schemas document tree 9532 */ 9533static void 9534xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root) 9535{ 9536 xmlNodePtr delete, cur; 9537 9538 if ((ctxt == NULL) || (root == NULL)) return; 9539 9540 /* 9541 * Remove all the blank text nodes 9542 */ 9543 delete = NULL; 9544 cur = root; 9545 while (cur != NULL) { 9546 if (delete != NULL) { 9547 xmlUnlinkNode(delete); 9548 xmlFreeNode(delete); 9549 delete = NULL; 9550 } 9551 if (cur->type == XML_TEXT_NODE) { 9552 if (IS_BLANK_NODE(cur)) { 9553 if (xmlNodeGetSpacePreserve(cur) != 1) { 9554 delete = cur; 9555 } 9556 } 9557 } else if ((cur->type != XML_ELEMENT_NODE) && 9558 (cur->type != XML_CDATA_SECTION_NODE)) { 9559 delete = cur; 9560 goto skip_children; 9561 } 9562 9563 /* 9564 * Skip to next node 9565 */ 9566 if (cur->children != NULL) { 9567 if ((cur->children->type != XML_ENTITY_DECL) && 9568 (cur->children->type != XML_ENTITY_REF_NODE) && 9569 (cur->children->type != XML_ENTITY_NODE)) { 9570 cur = cur->children; 9571 continue; 9572 } 9573 } 9574 skip_children: 9575 if (cur->next != NULL) { 9576 cur = cur->next; 9577 continue; 9578 } 9579 9580 do { 9581 cur = cur->parent; 9582 if (cur == NULL) 9583 break; 9584 if (cur == root) { 9585 cur = NULL; 9586 break; 9587 } 9588 if (cur->next != NULL) { 9589 cur = cur->next; 9590 break; 9591 } 9592 } while (cur != NULL); 9593 } 9594 if (delete != NULL) { 9595 xmlUnlinkNode(delete); 9596 xmlFreeNode(delete); 9597 delete = NULL; 9598 } 9599} 9600 9601 9602static void 9603xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema) 9604{ 9605 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM) 9606 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM; 9607 9608 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) 9609 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR; 9610 9611 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) 9612 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION; 9613 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) 9614 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION; 9615 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST) 9616 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST; 9617 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION) 9618 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION; 9619 9620 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION) 9621 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION; 9622 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION) 9623 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION; 9624 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION) 9625 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION; 9626} 9627 9628static int 9629xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt, 9630 xmlSchemaPtr schema, 9631 xmlNodePtr node) 9632{ 9633 xmlAttrPtr attr; 9634 const xmlChar *val; 9635 int res = 0, oldErrs = ctxt->nberrors; 9636 9637 /* 9638 * Those flags should be moved to the parser context flags, 9639 * since they are not visible at the component level. I.e. 9640 * they are used if processing schema *documents* only. 9641 */ 9642 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 9643 HFAILURE; 9644 9645 /* 9646 * Since the version is of type xs:token, we won't bother to 9647 * check it. 9648 */ 9649 /* REMOVED: 9650 attr = xmlSchemaGetPropNode(node, "version"); 9651 if (attr != NULL) { 9652 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr, 9653 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val); 9654 HFAILURE; 9655 } 9656 */ 9657 attr = xmlSchemaGetPropNode(node, "targetNamespace"); 9658 if (attr != NULL) { 9659 res = xmlSchemaPValAttrNode(ctxt, NULL, attr, 9660 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL); 9661 HFAILURE; 9662 if (res != 0) { 9663 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; 9664 goto exit; 9665 } 9666 } 9667 attr = xmlSchemaGetPropNode(node, "elementFormDefault"); 9668 if (attr != NULL) { 9669 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 9670 res = xmlSchemaPValAttrFormDefault(val, &schema->flags, 9671 XML_SCHEMAS_QUALIF_ELEM); 9672 HFAILURE; 9673 if (res != 0) { 9674 xmlSchemaPSimpleTypeErr(ctxt, 9675 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE, 9676 NULL, (xmlNodePtr) attr, NULL, 9677 "(qualified | unqualified)", val, NULL, NULL, NULL); 9678 } 9679 } 9680 attr = xmlSchemaGetPropNode(node, "attributeFormDefault"); 9681 if (attr != NULL) { 9682 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 9683 res = xmlSchemaPValAttrFormDefault(val, &schema->flags, 9684 XML_SCHEMAS_QUALIF_ATTR); 9685 HFAILURE; 9686 if (res != 0) { 9687 xmlSchemaPSimpleTypeErr(ctxt, 9688 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE, 9689 NULL, (xmlNodePtr) attr, NULL, 9690 "(qualified | unqualified)", val, NULL, NULL, NULL); 9691 } 9692 } 9693 attr = xmlSchemaGetPropNode(node, "finalDefault"); 9694 if (attr != NULL) { 9695 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 9696 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1, 9697 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION, 9698 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION, 9699 -1, 9700 XML_SCHEMAS_FINAL_DEFAULT_LIST, 9701 XML_SCHEMAS_FINAL_DEFAULT_UNION); 9702 HFAILURE; 9703 if (res != 0) { 9704 xmlSchemaPSimpleTypeErr(ctxt, 9705 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 9706 NULL, (xmlNodePtr) attr, NULL, 9707 "(#all | List of (extension | restriction | list | union))", 9708 val, NULL, NULL, NULL); 9709 } 9710 } 9711 attr = xmlSchemaGetPropNode(node, "blockDefault"); 9712 if (attr != NULL) { 9713 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); 9714 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1, 9715 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION, 9716 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION, 9717 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1); 9718 HFAILURE; 9719 if (res != 0) { 9720 xmlSchemaPSimpleTypeErr(ctxt, 9721 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 9722 NULL, (xmlNodePtr) attr, NULL, 9723 "(#all | List of (extension | restriction | substitution))", 9724 val, NULL, NULL, NULL); 9725 } 9726 } 9727 9728exit: 9729 if (oldErrs != ctxt->nberrors) 9730 res = ctxt->err; 9731 return(res); 9732exit_failure: 9733 return(-1); 9734} 9735 9736/** 9737 * xmlSchemaParseSchemaTopLevel: 9738 * @ctxt: a schema validation context 9739 * @schema: the schemas 9740 * @nodes: the list of top level nodes 9741 * 9742 * Returns the internal XML Schema structure built from the resource or 9743 * NULL in case of error 9744 */ 9745static int 9746xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt, 9747 xmlSchemaPtr schema, xmlNodePtr nodes) 9748{ 9749 xmlNodePtr child; 9750 xmlSchemaAnnotPtr annot; 9751 int res = 0, oldErrs, tmpOldErrs; 9752 9753 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL)) 9754 return(-1); 9755 9756 oldErrs = ctxt->nberrors; 9757 child = nodes; 9758 while ((IS_SCHEMA(child, "include")) || 9759 (IS_SCHEMA(child, "import")) || 9760 (IS_SCHEMA(child, "redefine")) || 9761 (IS_SCHEMA(child, "annotation"))) { 9762 if (IS_SCHEMA(child, "annotation")) { 9763 annot = xmlSchemaParseAnnotation(ctxt, child, 1); 9764 if (schema->annot == NULL) 9765 schema->annot = annot; 9766 else 9767 xmlSchemaFreeAnnot(annot); 9768 } else if (IS_SCHEMA(child, "import")) { 9769 tmpOldErrs = ctxt->nberrors; 9770 res = xmlSchemaParseImport(ctxt, schema, child); 9771 HFAILURE; 9772 HSTOP(ctxt); 9773 if (tmpOldErrs != ctxt->nberrors) 9774 goto exit; 9775 } else if (IS_SCHEMA(child, "include")) { 9776 tmpOldErrs = ctxt->nberrors; 9777 res = xmlSchemaParseInclude(ctxt, schema, child); 9778 HFAILURE; 9779 HSTOP(ctxt); 9780 if (tmpOldErrs != ctxt->nberrors) 9781 goto exit; 9782 } else if (IS_SCHEMA(child, "redefine")) { 9783 tmpOldErrs = ctxt->nberrors; 9784 res = xmlSchemaParseRedefine(ctxt, schema, child); 9785 HFAILURE; 9786 HSTOP(ctxt); 9787 if (tmpOldErrs != ctxt->nberrors) 9788 goto exit; 9789 } 9790 child = child->next; 9791 } 9792 /* 9793 * URGENT TODO: Change the functions to return int results. 9794 * We need especially to catch internal errors. 9795 */ 9796 while (child != NULL) { 9797 if (IS_SCHEMA(child, "complexType")) { 9798 xmlSchemaParseComplexType(ctxt, schema, child, 1); 9799 child = child->next; 9800 } else if (IS_SCHEMA(child, "simpleType")) { 9801 xmlSchemaParseSimpleType(ctxt, schema, child, 1); 9802 child = child->next; 9803 } else if (IS_SCHEMA(child, "element")) { 9804 xmlSchemaParseElement(ctxt, schema, child, NULL, 1); 9805 child = child->next; 9806 } else if (IS_SCHEMA(child, "attribute")) { 9807 xmlSchemaParseGlobalAttribute(ctxt, schema, child); 9808 child = child->next; 9809 } else if (IS_SCHEMA(child, "attributeGroup")) { 9810 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child); 9811 child = child->next; 9812 } else if (IS_SCHEMA(child, "group")) { 9813 xmlSchemaParseModelGroupDefinition(ctxt, schema, child); 9814 child = child->next; 9815 } else if (IS_SCHEMA(child, "notation")) { 9816 xmlSchemaParseNotation(ctxt, schema, child); 9817 child = child->next; 9818 } else { 9819 xmlSchemaPContentErr(ctxt, 9820 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 9821 NULL, child->parent, child, 9822 NULL, "((include | import | redefine | annotation)*, " 9823 "(((simpleType | complexType | group | attributeGroup) " 9824 "| element | attribute | notation), annotation*)*)"); 9825 child = child->next; 9826 } 9827 while (IS_SCHEMA(child, "annotation")) { 9828 /* 9829 * TODO: We should add all annotations. 9830 */ 9831 annot = xmlSchemaParseAnnotation(ctxt, child, 1); 9832 if (schema->annot == NULL) 9833 schema->annot = annot; 9834 else 9835 xmlSchemaFreeAnnot(annot); 9836 child = child->next; 9837 } 9838 } 9839exit: 9840 ctxt->ctxtType = NULL; 9841 if (oldErrs != ctxt->nberrors) 9842 res = ctxt->err; 9843 return(res); 9844exit_failure: 9845 return(-1); 9846} 9847 9848static xmlSchemaSchemaRelationPtr 9849xmlSchemaSchemaRelationCreate(void) 9850{ 9851 xmlSchemaSchemaRelationPtr ret; 9852 9853 ret = (xmlSchemaSchemaRelationPtr) 9854 xmlMalloc(sizeof(xmlSchemaSchemaRelation)); 9855 if (ret == NULL) { 9856 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL); 9857 return(NULL); 9858 } 9859 memset(ret, 0, sizeof(xmlSchemaSchemaRelation)); 9860 return(ret); 9861} 9862 9863#if 0 9864static void 9865xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel) 9866{ 9867 xmlFree(rel); 9868} 9869#endif 9870 9871static void 9872xmlSchemaRedefListFree(xmlSchemaRedefPtr redef) 9873{ 9874 xmlSchemaRedefPtr prev; 9875 9876 while (redef != NULL) { 9877 prev = redef; 9878 redef = redef->next; 9879 xmlFree(prev); 9880 } 9881} 9882 9883static void 9884xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con) 9885{ 9886 /* 9887 * After the construction context has been freed, there will be 9888 * no schema graph available any more. Only the schema buckets 9889 * will stay alive, which are put into the "schemasImports" and 9890 * "includes" slots of the xmlSchema. 9891 */ 9892 if (con->buckets != NULL) 9893 xmlSchemaItemListFree(con->buckets); 9894 if (con->pending != NULL) 9895 xmlSchemaItemListFree(con->pending); 9896 if (con->substGroups != NULL) 9897 xmlHashFree(con->substGroups, 9898 (xmlHashDeallocator) xmlSchemaSubstGroupFree); 9899 if (con->redefs != NULL) 9900 xmlSchemaRedefListFree(con->redefs); 9901 if (con->dict != NULL) 9902 xmlDictFree(con->dict); 9903 xmlFree(con); 9904} 9905 9906static xmlSchemaConstructionCtxtPtr 9907xmlSchemaConstructionCtxtCreate(xmlDictPtr dict) 9908{ 9909 xmlSchemaConstructionCtxtPtr ret; 9910 9911 ret = (xmlSchemaConstructionCtxtPtr) 9912 xmlMalloc(sizeof(xmlSchemaConstructionCtxt)); 9913 if (ret == NULL) { 9914 xmlSchemaPErrMemory(NULL, 9915 "allocating schema construction context", NULL); 9916 return (NULL); 9917 } 9918 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt)); 9919 9920 ret->buckets = xmlSchemaItemListCreate(); 9921 if (ret->buckets == NULL) { 9922 xmlSchemaPErrMemory(NULL, 9923 "allocating list of schema buckets", NULL); 9924 xmlFree(ret); 9925 return (NULL); 9926 } 9927 ret->pending = xmlSchemaItemListCreate(); 9928 if (ret->pending == NULL) { 9929 xmlSchemaPErrMemory(NULL, 9930 "allocating list of pending global components", NULL); 9931 xmlSchemaConstructionCtxtFree(ret); 9932 return (NULL); 9933 } 9934 ret->dict = dict; 9935 xmlDictReference(dict); 9936 return(ret); 9937} 9938 9939static xmlSchemaParserCtxtPtr 9940xmlSchemaParserCtxtCreate(void) 9941{ 9942 xmlSchemaParserCtxtPtr ret; 9943 9944 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt)); 9945 if (ret == NULL) { 9946 xmlSchemaPErrMemory(NULL, "allocating schema parser context", 9947 NULL); 9948 return (NULL); 9949 } 9950 memset(ret, 0, sizeof(xmlSchemaParserCtxt)); 9951 ret->type = XML_SCHEMA_CTXT_PARSER; 9952 ret->attrProhibs = xmlSchemaItemListCreate(); 9953 if (ret->attrProhibs == NULL) { 9954 xmlFree(ret); 9955 return(NULL); 9956 } 9957 return(ret); 9958} 9959 9960/** 9961 * xmlSchemaNewParserCtxtUseDict: 9962 * @URL: the location of the schema 9963 * @dict: the dictionary to be used 9964 * 9965 * Create an XML Schemas parse context for that file/resource expected 9966 * to contain an XML Schemas file. 9967 * 9968 * Returns the parser context or NULL in case of error 9969 */ 9970static xmlSchemaParserCtxtPtr 9971xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict) 9972{ 9973 xmlSchemaParserCtxtPtr ret; 9974 9975 ret = xmlSchemaParserCtxtCreate(); 9976 if (ret == NULL) 9977 return (NULL); 9978 ret->dict = dict; 9979 xmlDictReference(dict); 9980 if (URL != NULL) 9981 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1); 9982 return (ret); 9983} 9984 9985static int 9986xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt) 9987{ 9988 if (vctxt->pctxt == NULL) { 9989 if (vctxt->schema != NULL) 9990 vctxt->pctxt = 9991 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict); 9992 else 9993 vctxt->pctxt = xmlSchemaNewParserCtxt("*"); 9994 if (vctxt->pctxt == NULL) { 9995 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt", 9996 "failed to create a temp. parser context"); 9997 return (-1); 9998 } 9999 /* TODO: Pass user data. */ 10000 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, 10001 vctxt->warning, vctxt->errCtxt); 10002 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror, 10003 vctxt->errCtxt); 10004 } 10005 return (0); 10006} 10007 10008/** 10009 * xmlSchemaGetSchemaBucket: 10010 * @pctxt: the schema parser context 10011 * @schemaLocation: the URI of the schema document 10012 * 10013 * Returns a schema bucket if it was already parsed. 10014 * 10015 * Returns a schema bucket if it was already parsed from 10016 * @schemaLocation, NULL otherwise. 10017 */ 10018static xmlSchemaBucketPtr 10019xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt, 10020 const xmlChar *schemaLocation) 10021{ 10022 xmlSchemaBucketPtr cur; 10023 xmlSchemaItemListPtr list; 10024 10025 list = pctxt->constructor->buckets; 10026 if (list->nbItems == 0) 10027 return(NULL); 10028 else { 10029 int i; 10030 for (i = 0; i < list->nbItems; i++) { 10031 cur = (xmlSchemaBucketPtr) list->items[i]; 10032 /* Pointer comparison! */ 10033 if (cur->schemaLocation == schemaLocation) 10034 return(cur); 10035 } 10036 } 10037 return(NULL); 10038} 10039 10040static xmlSchemaBucketPtr 10041xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt, 10042 const xmlChar *schemaLocation, 10043 const xmlChar *targetNamespace) 10044{ 10045 xmlSchemaBucketPtr cur; 10046 xmlSchemaItemListPtr list; 10047 10048 list = pctxt->constructor->buckets; 10049 if (list->nbItems == 0) 10050 return(NULL); 10051 else { 10052 int i; 10053 for (i = 0; i < list->nbItems; i++) { 10054 cur = (xmlSchemaBucketPtr) list->items[i]; 10055 /* Pointer comparison! */ 10056 if ((cur->origTargetNamespace == NULL) && 10057 (cur->schemaLocation == schemaLocation) && 10058 (cur->targetNamespace == targetNamespace)) 10059 return(cur); 10060 } 10061 } 10062 return(NULL); 10063} 10064 10065 10066#define IS_BAD_SCHEMA_DOC(b) \ 10067 (((b)->doc == NULL) && ((b)->schemaLocation != NULL)) 10068 10069static xmlSchemaBucketPtr 10070xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt, 10071 const xmlChar *targetNamespace, 10072 int imported) 10073{ 10074 xmlSchemaBucketPtr cur; 10075 xmlSchemaItemListPtr list; 10076 10077 list = pctxt->constructor->buckets; 10078 if (list->nbItems == 0) 10079 return(NULL); 10080 else { 10081 int i; 10082 for (i = 0; i < list->nbItems; i++) { 10083 cur = (xmlSchemaBucketPtr) list->items[i]; 10084 if ((! IS_BAD_SCHEMA_DOC(cur)) && 10085 (cur->origTargetNamespace == targetNamespace) && 10086 ((imported && cur->imported) || 10087 ((!imported) && (!cur->imported)))) 10088 return(cur); 10089 } 10090 } 10091 return(NULL); 10092} 10093 10094static int 10095xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt, 10096 xmlSchemaPtr schema, 10097 xmlSchemaBucketPtr bucket) 10098{ 10099 int oldFlags; 10100 xmlDocPtr oldDoc; 10101 xmlNodePtr node; 10102 int ret, oldErrs; 10103 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket; 10104 10105 /* 10106 * Save old values; reset the *main* schema. 10107 * URGENT TODO: This is not good; move the per-document information 10108 * to the parser. Get rid of passing the main schema to the 10109 * parsing functions. 10110 */ 10111 oldFlags = schema->flags; 10112 oldDoc = schema->doc; 10113 if (schema->flags != 0) 10114 xmlSchemaClearSchemaDefaults(schema); 10115 schema->doc = bucket->doc; 10116 pctxt->schema = schema; 10117 /* 10118 * Keep the current target namespace on the parser *not* on the 10119 * main schema. 10120 */ 10121 pctxt->targetNamespace = bucket->targetNamespace; 10122 WXS_CONSTRUCTOR(pctxt)->bucket = bucket; 10123 10124 if ((bucket->targetNamespace != NULL) && 10125 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) { 10126 /* 10127 * We are parsing the schema for schemas! 10128 */ 10129 pctxt->isS4S = 1; 10130 } 10131 /* Mark it as parsed, even if parsing fails. */ 10132 bucket->parsed++; 10133 /* Compile the schema doc. */ 10134 node = xmlDocGetRootElement(bucket->doc); 10135 ret = xmlSchemaParseSchemaElement(pctxt, schema, node); 10136 if (ret != 0) 10137 goto exit; 10138 /* An empty schema; just get out. */ 10139 if (node->children == NULL) 10140 goto exit; 10141 oldErrs = pctxt->nberrors; 10142 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children); 10143 if (ret != 0) 10144 goto exit; 10145 /* 10146 * TODO: Not nice, but I'm not 100% sure we will get always an error 10147 * as a result of the obove functions; so better rely on pctxt->err 10148 * as well. 10149 */ 10150 if ((ret == 0) && (oldErrs != pctxt->nberrors)) { 10151 ret = pctxt->err; 10152 goto exit; 10153 } 10154 10155exit: 10156 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket; 10157 /* Restore schema values. */ 10158 schema->doc = oldDoc; 10159 schema->flags = oldFlags; 10160 return(ret); 10161} 10162 10163static int 10164xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt, 10165 xmlSchemaPtr schema, 10166 xmlSchemaBucketPtr bucket) 10167{ 10168 xmlSchemaParserCtxtPtr newpctxt; 10169 int res = 0; 10170 10171 if (bucket == NULL) 10172 return(0); 10173 if (bucket->parsed) { 10174 PERROR_INT("xmlSchemaParseNewDoc", 10175 "reparsing a schema doc"); 10176 return(-1); 10177 } 10178 if (bucket->doc == NULL) { 10179 PERROR_INT("xmlSchemaParseNewDoc", 10180 "parsing a schema doc, but there's no doc"); 10181 return(-1); 10182 } 10183 if (pctxt->constructor == NULL) { 10184 PERROR_INT("xmlSchemaParseNewDoc", 10185 "no constructor"); 10186 return(-1); 10187 } 10188 /* Create and init the temporary parser context. */ 10189 newpctxt = xmlSchemaNewParserCtxtUseDict( 10190 (const char *) bucket->schemaLocation, pctxt->dict); 10191 if (newpctxt == NULL) 10192 return(-1); 10193 newpctxt->constructor = pctxt->constructor; 10194 /* 10195 * TODO: Can we avoid that the parser knows about the main schema? 10196 * It would be better if he knows about the current schema bucket 10197 * only. 10198 */ 10199 newpctxt->schema = schema; 10200 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning, 10201 pctxt->errCtxt); 10202 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror, 10203 pctxt->errCtxt); 10204 newpctxt->counter = pctxt->counter; 10205 10206 10207 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket); 10208 10209 /* Channel back errors and cleanup the temporary parser context. */ 10210 if (res != 0) 10211 pctxt->err = res; 10212 pctxt->nberrors += newpctxt->nberrors; 10213 pctxt->counter = newpctxt->counter; 10214 newpctxt->constructor = NULL; 10215 /* Free the parser context. */ 10216 xmlSchemaFreeParserCtxt(newpctxt); 10217 return(res); 10218} 10219 10220static void 10221xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket, 10222 xmlSchemaSchemaRelationPtr rel) 10223{ 10224 xmlSchemaSchemaRelationPtr cur = bucket->relations; 10225 10226 if (cur == NULL) { 10227 bucket->relations = rel; 10228 return; 10229 } 10230 while (cur->next != NULL) 10231 cur = cur->next; 10232 cur->next = rel; 10233} 10234 10235 10236static const xmlChar * 10237xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location, 10238 xmlNodePtr ctxtNode) 10239{ 10240 /* 10241 * Build an absolue location URI. 10242 */ 10243 if (location != NULL) { 10244 if (ctxtNode == NULL) 10245 return(location); 10246 else { 10247 xmlChar *base, *URI; 10248 const xmlChar *ret = NULL; 10249 10250 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode); 10251 if (base == NULL) { 10252 URI = xmlBuildURI(location, ctxtNode->doc->URL); 10253 } else { 10254 URI = xmlBuildURI(location, base); 10255 xmlFree(base); 10256 } 10257 if (URI != NULL) { 10258 ret = xmlDictLookup(dict, URI, -1); 10259 xmlFree(URI); 10260 return(ret); 10261 } 10262 } 10263 } 10264 return(NULL); 10265} 10266 10267 10268 10269/** 10270 * xmlSchemaAddSchemaDoc: 10271 * @pctxt: a schema validation context 10272 * @schema: the schema being built 10273 * @node: a subtree containing XML Schema informations 10274 * 10275 * Parse an included (and to-be-redefined) XML schema document. 10276 * 10277 * Returns 0 on success, a positive error code on errors and 10278 * -1 in case of an internal or API error. 10279 */ 10280 10281static int 10282xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt, 10283 int type, /* import or include or redefine */ 10284 const xmlChar *schemaLocation, 10285 xmlDocPtr schemaDoc, 10286 const char *schemaBuffer, 10287 int schemaBufferLen, 10288 xmlNodePtr invokingNode, 10289 const xmlChar *sourceTargetNamespace, 10290 const xmlChar *importNamespace, 10291 xmlSchemaBucketPtr *bucket) 10292{ 10293 const xmlChar *targetNamespace = NULL; 10294 xmlSchemaSchemaRelationPtr relation = NULL; 10295 xmlDocPtr doc = NULL; 10296 int res = 0, err = 0, located = 0, preserveDoc = 0; 10297 xmlSchemaBucketPtr bkt = NULL; 10298 10299 if (bucket != NULL) 10300 *bucket = NULL; 10301 10302 switch (type) { 10303 case XML_SCHEMA_SCHEMA_IMPORT: 10304 case XML_SCHEMA_SCHEMA_MAIN: 10305 err = XML_SCHEMAP_SRC_IMPORT; 10306 break; 10307 case XML_SCHEMA_SCHEMA_INCLUDE: 10308 err = XML_SCHEMAP_SRC_INCLUDE; 10309 break; 10310 case XML_SCHEMA_SCHEMA_REDEFINE: 10311 err = XML_SCHEMAP_SRC_REDEFINE; 10312 break; 10313 } 10314 10315 10316 /* Special handling for the main schema: 10317 * skip the location and relation logic and just parse the doc. 10318 * We need just a bucket to be returned in this case. 10319 */ 10320 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt))) 10321 goto doc_load; 10322 10323 /* Note that we expect the location to be an absulute URI. */ 10324 if (schemaLocation != NULL) { 10325 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation); 10326 if ((bkt != NULL) && 10327 (pctxt->constructor->bucket == bkt)) { 10328 /* Report self-imports/inclusions/redefinitions. */ 10329 10330 xmlSchemaCustomErr(ACTXT_CAST pctxt, err, 10331 invokingNode, NULL, 10332 "The schema must not import/include/redefine itself", 10333 NULL, NULL); 10334 goto exit; 10335 } 10336 } 10337 /* 10338 * Create a relation for the graph of schemas. 10339 */ 10340 relation = xmlSchemaSchemaRelationCreate(); 10341 if (relation == NULL) 10342 return(-1); 10343 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket, 10344 relation); 10345 relation->type = type; 10346 10347 /* 10348 * Save the namespace import information. 10349 */ 10350 if (WXS_IS_BUCKET_IMPMAIN(type)) { 10351 relation->importNamespace = importNamespace; 10352 if (schemaLocation == NULL) { 10353 /* 10354 * No location; this is just an import of the namespace. 10355 * Note that we don't assign a bucket to the relation 10356 * in this case. 10357 */ 10358 goto exit; 10359 } 10360 targetNamespace = importNamespace; 10361 } 10362 10363 /* Did we already fetch the doc? */ 10364 if (bkt != NULL) { 10365 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) { 10366 /* 10367 * We included/redefined and then try to import a schema, 10368 * but the new location provided for import was different. 10369 */ 10370 if (schemaLocation == NULL) 10371 schemaLocation = BAD_CAST "in_memory_buffer"; 10372 if (!xmlStrEqual(schemaLocation, 10373 bkt->schemaLocation)) { 10374 xmlSchemaCustomErr(ACTXT_CAST pctxt, err, 10375 invokingNode, NULL, 10376 "The schema document '%s' cannot be imported, since " 10377 "it was already included or redefined", 10378 schemaLocation, NULL); 10379 goto exit; 10380 } 10381 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) { 10382 /* 10383 * We imported and then try to include/redefine a schema, 10384 * but the new location provided for the include/redefine 10385 * was different. 10386 */ 10387 if (schemaLocation == NULL) 10388 schemaLocation = BAD_CAST "in_memory_buffer"; 10389 if (!xmlStrEqual(schemaLocation, 10390 bkt->schemaLocation)) { 10391 xmlSchemaCustomErr(ACTXT_CAST pctxt, err, 10392 invokingNode, NULL, 10393 "The schema document '%s' cannot be included or " 10394 "redefined, since it was already imported", 10395 schemaLocation, NULL); 10396 goto exit; 10397 } 10398 } 10399 } 10400 10401 if (WXS_IS_BUCKET_IMPMAIN(type)) { 10402 /* 10403 * Given that the schemaLocation [attribute] is only a hint, it is open 10404 * to applications to ignore all but the first <import> for a given 10405 * namespace, regardless of the �actual value� of schemaLocation, but 10406 * such a strategy risks missing useful information when new 10407 * schemaLocations are offered. 10408 * 10409 * We will use the first <import> that comes with a location. 10410 * Further <import>s *with* a location, will result in an error. 10411 * TODO: Better would be to just report a warning here, but 10412 * we'll try it this way until someone complains. 10413 * 10414 * Schema Document Location Strategy: 10415 * 3 Based on the namespace name, identify an existing schema document, 10416 * either as a resource which is an XML document or a <schema> element 10417 * information item, in some local schema repository; 10418 * 5 Attempt to resolve the namespace name to locate such a resource. 10419 * 10420 * NOTE: (3) and (5) are not supported. 10421 */ 10422 if (bkt != NULL) { 10423 relation->bucket = bkt; 10424 goto exit; 10425 } 10426 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt, 10427 importNamespace, 1); 10428 10429 if (bkt != NULL) { 10430 relation->bucket = bkt; 10431 if (bkt->schemaLocation == NULL) { 10432 /* First given location of the schema; load the doc. */ 10433 bkt->schemaLocation = schemaLocation; 10434 } else { 10435 if (!xmlStrEqual(schemaLocation, 10436 bkt->schemaLocation)) { 10437 /* 10438 * Additional location given; just skip it. 10439 * URGENT TODO: We should report a warning here. 10440 * res = XML_SCHEMAP_SRC_IMPORT; 10441 */ 10442 if (schemaLocation == NULL) 10443 schemaLocation = BAD_CAST "in_memory_buffer"; 10444 10445 xmlSchemaCustomWarning(ACTXT_CAST pctxt, 10446 XML_SCHEMAP_WARN_SKIP_SCHEMA, 10447 invokingNode, NULL, 10448 "Skipping import of schema located at '%s' for the " 10449 "namespace '%s', since this namespace was already " 10450 "imported with the schema located at '%s'", 10451 schemaLocation, importNamespace, bkt->schemaLocation); 10452 } 10453 goto exit; 10454 } 10455 } 10456 /* 10457 * No bucket + first location: load the doc and create a 10458 * bucket. 10459 */ 10460 } else { 10461 /* <include> and <redefine> */ 10462 if (bkt != NULL) { 10463 10464 if ((bkt->origTargetNamespace == NULL) && 10465 (bkt->targetNamespace != sourceTargetNamespace)) { 10466 xmlSchemaBucketPtr chamel; 10467 10468 /* 10469 * Chameleon include/redefine: skip loading only if it was 10470 * aleady build for the targetNamespace of the including 10471 * schema. 10472 */ 10473 /* 10474 * URGENT TODO: If the schema is a chameleon-include then copy 10475 * the components into the including schema and modify the 10476 * targetNamespace of those components, do nothing otherwise. 10477 * NOTE: This is currently worked-around by compiling the 10478 * chameleon for every destinct including targetNamespace; thus 10479 * not performant at the moment. 10480 * TODO: Check when the namespace in wildcards for chameleons 10481 * needs to be converted: before we built wildcard intersections 10482 * or after. 10483 * Answer: after! 10484 */ 10485 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt, 10486 schemaLocation, sourceTargetNamespace); 10487 if (chamel != NULL) { 10488 /* A fitting chameleon was already parsed; NOP. */ 10489 relation->bucket = chamel; 10490 goto exit; 10491 } 10492 /* 10493 * We need to parse the chameleon again for a different 10494 * targetNamespace. 10495 * CHAMELEON TODO: Optimize this by only parsing the 10496 * chameleon once, and then copying the components to 10497 * the new targetNamespace. 10498 */ 10499 bkt = NULL; 10500 } else { 10501 relation->bucket = bkt; 10502 goto exit; 10503 } 10504 } 10505 } 10506 if ((bkt != NULL) && (bkt->doc != NULL)) { 10507 PERROR_INT("xmlSchemaAddSchemaDoc", 10508 "trying to load a schema doc, but a doc is already " 10509 "assigned to the schema bucket"); 10510 goto exit_failure; 10511 } 10512 10513doc_load: 10514 /* 10515 * Load the document. 10516 */ 10517 if (schemaDoc != NULL) { 10518 doc = schemaDoc; 10519 /* Don' free this one, since it was provided by the caller. */ 10520 preserveDoc = 1; 10521 /* TODO: Does the context or the doc hold the location? */ 10522 if (schemaDoc->URL != NULL) 10523 schemaLocation = xmlDictLookup(pctxt->dict, 10524 schemaDoc->URL, -1); 10525 else 10526 schemaLocation = BAD_CAST "in_memory_buffer"; 10527 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) { 10528 xmlParserCtxtPtr parserCtxt; 10529 10530 parserCtxt = xmlNewParserCtxt(); 10531 if (parserCtxt == NULL) { 10532 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, " 10533 "allocating a parser context", NULL); 10534 goto exit_failure; 10535 } 10536 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) { 10537 /* 10538 * TODO: Do we have to burden the schema parser dict with all 10539 * the content of the schema doc? 10540 */ 10541 xmlDictFree(parserCtxt->dict); 10542 parserCtxt->dict = pctxt->dict; 10543 xmlDictReference(parserCtxt->dict); 10544 } 10545 if (schemaLocation != NULL) { 10546 /* Parse from file. */ 10547 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation, 10548 NULL, SCHEMAS_PARSE_OPTIONS); 10549 } else if (schemaBuffer != NULL) { 10550 /* Parse from memory buffer. */ 10551 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen, 10552 NULL, NULL, SCHEMAS_PARSE_OPTIONS); 10553 schemaLocation = BAD_CAST "in_memory_buffer"; 10554 if (doc != NULL) 10555 doc->URL = xmlStrdup(schemaLocation); 10556 } 10557 /* 10558 * For <import>: 10559 * 2.1 The referent is (a fragment of) a resource which is an 10560 * XML document (see clause 1.1), which in turn corresponds to 10561 * a <schema> element information item in a well-formed information 10562 * set, which in turn corresponds to a valid schema. 10563 * TODO: (2.1) fragments of XML documents are not supported. 10564 * 10565 * 2.2 The referent is a <schema> element information item in 10566 * a well-formed information set, which in turn corresponds 10567 * to a valid schema. 10568 * TODO: (2.2) is not supported. 10569 */ 10570 if (doc == NULL) { 10571 xmlErrorPtr lerr; 10572 lerr = xmlGetLastError(); 10573 /* 10574 * Check if this a parser error, or if the document could 10575 * just not be located. 10576 * TODO: Try to find specific error codes to react only on 10577 * localisation failures. 10578 */ 10579 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) { 10580 /* 10581 * We assume a parser error here. 10582 */ 10583 located = 1; 10584 /* TODO: Error code ?? */ 10585 res = XML_SCHEMAP_SRC_IMPORT_2_1; 10586 xmlSchemaCustomErr(ACTXT_CAST pctxt, res, 10587 invokingNode, NULL, 10588 "Failed to parse the XML resource '%s'", 10589 schemaLocation, NULL); 10590 } 10591 } 10592 xmlFreeParserCtxt(parserCtxt); 10593 if ((doc == NULL) && located) 10594 goto exit_error; 10595 } else { 10596 xmlSchemaPErr(pctxt, NULL, 10597 XML_SCHEMAP_NOTHING_TO_PARSE, 10598 "No information for parsing was provided with the " 10599 "given schema parser context.\n", 10600 NULL, NULL); 10601 goto exit_failure; 10602 } 10603 /* 10604 * Preprocess the document. 10605 */ 10606 if (doc != NULL) { 10607 xmlNodePtr docElem = NULL; 10608 10609 located = 1; 10610 docElem = xmlDocGetRootElement(doc); 10611 if (docElem == NULL) { 10612 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT, 10613 invokingNode, NULL, 10614 "The document '%s' has no document element", 10615 schemaLocation, NULL); 10616 goto exit_error; 10617 } 10618 /* 10619 * Remove all the blank text nodes. 10620 */ 10621 xmlSchemaCleanupDoc(pctxt, docElem); 10622 /* 10623 * Check the schema's top level element. 10624 */ 10625 if (!IS_SCHEMA(docElem, "schema")) { 10626 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA, 10627 invokingNode, NULL, 10628 "The XML document '%s' is not a schema document", 10629 schemaLocation, NULL); 10630 goto exit_error; 10631 } 10632 /* 10633 * Note that we don't apply a type check for the 10634 * targetNamespace value here. 10635 */ 10636 targetNamespace = xmlSchemaGetProp(pctxt, docElem, 10637 "targetNamespace"); 10638 } 10639 10640/* after_doc_loading: */ 10641 if ((bkt == NULL) && located) { 10642 /* Only create a bucket if the schema was located. */ 10643 bkt = xmlSchemaBucketCreate(pctxt, type, 10644 targetNamespace); 10645 if (bkt == NULL) 10646 goto exit_failure; 10647 } 10648 if (bkt != NULL) { 10649 bkt->schemaLocation = schemaLocation; 10650 bkt->located = located; 10651 if (doc != NULL) { 10652 bkt->doc = doc; 10653 bkt->targetNamespace = targetNamespace; 10654 bkt->origTargetNamespace = targetNamespace; 10655 if (preserveDoc) 10656 bkt->preserveDoc = 1; 10657 } 10658 if (WXS_IS_BUCKET_IMPMAIN(type)) 10659 bkt->imported++; 10660 /* 10661 * Add it to the graph of schemas. 10662 */ 10663 if (relation != NULL) 10664 relation->bucket = bkt; 10665 } 10666 10667exit: 10668 /* 10669 * Return the bucket explicitely; this is needed for the 10670 * main schema. 10671 */ 10672 if (bucket != NULL) 10673 *bucket = bkt; 10674 return (0); 10675 10676exit_error: 10677 if ((doc != NULL) && (! preserveDoc)) { 10678 xmlFreeDoc(doc); 10679 if (bkt != NULL) 10680 bkt->doc = NULL; 10681 } 10682 return(pctxt->err); 10683 10684exit_failure: 10685 if ((doc != NULL) && (! preserveDoc)) { 10686 xmlFreeDoc(doc); 10687 if (bkt != NULL) 10688 bkt->doc = NULL; 10689 } 10690 return (-1); 10691} 10692 10693/** 10694 * xmlSchemaParseImport: 10695 * @ctxt: a schema validation context 10696 * @schema: the schema being built 10697 * @node: a subtree containing XML Schema informations 10698 * 10699 * parse a XML schema Import definition 10700 * *WARNING* this interface is highly subject to change 10701 * 10702 * Returns 0 in case of success, a positive error code if 10703 * not valid and -1 in case of an internal error. 10704 */ 10705static int 10706xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, 10707 xmlNodePtr node) 10708{ 10709 xmlNodePtr child; 10710 const xmlChar *namespaceName = NULL, *schemaLocation = NULL; 10711 const xmlChar *thisTargetNamespace; 10712 xmlAttrPtr attr; 10713 int ret = 0; 10714 xmlSchemaBucketPtr bucket = NULL; 10715 10716 if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) 10717 return (-1); 10718 10719 /* 10720 * Check for illegal attributes. 10721 */ 10722 attr = node->properties; 10723 while (attr != NULL) { 10724 if (attr->ns == NULL) { 10725 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 10726 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) && 10727 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) { 10728 xmlSchemaPIllegalAttrErr(pctxt, 10729 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 10730 } 10731 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 10732 xmlSchemaPIllegalAttrErr(pctxt, 10733 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 10734 } 10735 attr = attr->next; 10736 } 10737 /* 10738 * Extract and validate attributes. 10739 */ 10740 if (xmlSchemaPValAttr(pctxt, NULL, node, 10741 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), 10742 &namespaceName) != 0) { 10743 xmlSchemaPSimpleTypeErr(pctxt, 10744 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 10745 NULL, node, 10746 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), 10747 NULL, namespaceName, NULL, NULL, NULL); 10748 return (pctxt->err); 10749 } 10750 10751 if (xmlSchemaPValAttr(pctxt, NULL, node, 10752 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), 10753 &schemaLocation) != 0) { 10754 xmlSchemaPSimpleTypeErr(pctxt, 10755 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 10756 NULL, node, 10757 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), 10758 NULL, namespaceName, NULL, NULL, NULL); 10759 return (pctxt->err); 10760 } 10761 /* 10762 * And now for the children... 10763 */ 10764 child = node->children; 10765 if (IS_SCHEMA(child, "annotation")) { 10766 /* 10767 * the annotation here is simply discarded ... 10768 * TODO: really? 10769 */ 10770 child = child->next; 10771 } 10772 if (child != NULL) { 10773 xmlSchemaPContentErr(pctxt, 10774 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 10775 NULL, node, child, NULL, 10776 "(annotation?)"); 10777 } 10778 /* 10779 * Apply additional constraints. 10780 * 10781 * Note that it is important to use the original @targetNamespace 10782 * (or none at all), to rule out imports of schemas _with_ a 10783 * @targetNamespace if the importing schema is a chameleon schema 10784 * (with no @targetNamespace). 10785 */ 10786 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace; 10787 if (namespaceName != NULL) { 10788 /* 10789 * 1.1 If the namespace [attribute] is present, then its �actual value� 10790 * must not match the �actual value� of the enclosing <schema>'s 10791 * targetNamespace [attribute]. 10792 */ 10793 if (xmlStrEqual(thisTargetNamespace, namespaceName)) { 10794 xmlSchemaPCustomErr(pctxt, 10795 XML_SCHEMAP_SRC_IMPORT_1_1, 10796 NULL, node, 10797 "The value of the attribute 'namespace' must not match " 10798 "the target namespace '%s' of the importing schema", 10799 thisTargetNamespace); 10800 return (pctxt->err); 10801 } 10802 } else { 10803 /* 10804 * 1.2 If the namespace [attribute] is not present, then the enclosing 10805 * <schema> must have a targetNamespace [attribute]. 10806 */ 10807 if (thisTargetNamespace == NULL) { 10808 xmlSchemaPCustomErr(pctxt, 10809 XML_SCHEMAP_SRC_IMPORT_1_2, 10810 NULL, node, 10811 "The attribute 'namespace' must be existent if " 10812 "the importing schema has no target namespace", 10813 NULL); 10814 return (pctxt->err); 10815 } 10816 } 10817 /* 10818 * Locate and acquire the schema document. 10819 */ 10820 if (schemaLocation != NULL) 10821 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict, 10822 schemaLocation, node); 10823 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT, 10824 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace, 10825 namespaceName, &bucket); 10826 10827 if (ret != 0) 10828 return(ret); 10829 10830 /* 10831 * For <import>: "It is *not* an error for the application 10832 * schema reference strategy to fail." 10833 * So just don't parse if no schema document was found. 10834 * Note that we will get no bucket if the schema could not be 10835 * located or if there was no schemaLocation. 10836 */ 10837 if ((bucket == NULL) && (schemaLocation != NULL)) { 10838 xmlSchemaCustomWarning(ACTXT_CAST pctxt, 10839 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA, 10840 node, NULL, 10841 "Failed to locate a schema at location '%s'. " 10842 "Skipping the import", schemaLocation, NULL, NULL); 10843 } 10844 10845 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) { 10846 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket); 10847 } 10848 10849 return (ret); 10850} 10851 10852static int 10853xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt, 10854 xmlSchemaPtr schema, 10855 xmlNodePtr node, 10856 xmlChar **schemaLocation, 10857 int type) 10858{ 10859 xmlAttrPtr attr; 10860 10861 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) || 10862 (schemaLocation == NULL)) 10863 return (-1); 10864 10865 *schemaLocation = NULL; 10866 /* 10867 * Check for illegal attributes. 10868 * Applies for both <include> and <redefine>. 10869 */ 10870 attr = node->properties; 10871 while (attr != NULL) { 10872 if (attr->ns == NULL) { 10873 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 10874 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) { 10875 xmlSchemaPIllegalAttrErr(pctxt, 10876 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 10877 } 10878 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 10879 xmlSchemaPIllegalAttrErr(pctxt, 10880 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 10881 } 10882 attr = attr->next; 10883 } 10884 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); 10885 /* 10886 * Preliminary step, extract the URI-Reference and make an URI 10887 * from the base. 10888 */ 10889 /* 10890 * Attribute "schemaLocation" is mandatory. 10891 */ 10892 attr = xmlSchemaGetPropNode(node, "schemaLocation"); 10893 if (attr != NULL) { 10894 xmlChar *base = NULL; 10895 xmlChar *uri = NULL; 10896 10897 if (xmlSchemaPValAttrNode(pctxt, NULL, attr, 10898 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), 10899 (const xmlChar **) schemaLocation) != 0) 10900 goto exit_error; 10901 base = xmlNodeGetBase(node->doc, node); 10902 if (base == NULL) { 10903 uri = xmlBuildURI(*schemaLocation, node->doc->URL); 10904 } else { 10905 uri = xmlBuildURI(*schemaLocation, base); 10906 xmlFree(base); 10907 } 10908 if (uri == NULL) { 10909 PERROR_INT("xmlSchemaParseIncludeOrRedefine", 10910 "could not build an URI from the schemaLocation") 10911 goto exit_failure; 10912 } 10913 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1); 10914 xmlFree(uri); 10915 } else { 10916 xmlSchemaPMissingAttrErr(pctxt, 10917 XML_SCHEMAP_S4S_ATTR_MISSING, 10918 NULL, node, "schemaLocation", NULL); 10919 goto exit_error; 10920 } 10921 /* 10922 * Report self-inclusion and self-redefinition. 10923 */ 10924 if (xmlStrEqual(*schemaLocation, pctxt->URL)) { 10925 if (type == XML_SCHEMA_SCHEMA_REDEFINE) { 10926 xmlSchemaPCustomErr(pctxt, 10927 XML_SCHEMAP_SRC_REDEFINE, 10928 NULL, node, 10929 "The schema document '%s' cannot redefine itself.", 10930 *schemaLocation); 10931 } else { 10932 xmlSchemaPCustomErr(pctxt, 10933 XML_SCHEMAP_SRC_INCLUDE, 10934 NULL, node, 10935 "The schema document '%s' cannot include itself.", 10936 *schemaLocation); 10937 } 10938 goto exit_error; 10939 } 10940 10941 return(0); 10942exit_error: 10943 return(pctxt->err); 10944exit_failure: 10945 return(-1); 10946} 10947 10948static int 10949xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt, 10950 xmlSchemaPtr schema, 10951 xmlNodePtr node, 10952 int type) 10953{ 10954 xmlNodePtr child = NULL; 10955 const xmlChar *schemaLocation = NULL; 10956 int res = 0; /* hasRedefinitions = 0 */ 10957 int isChameleon = 0, wasChameleon = 0; 10958 xmlSchemaBucketPtr bucket = NULL; 10959 10960 if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) 10961 return (-1); 10962 10963 /* 10964 * Parse attributes. Note that the returned schemaLocation will 10965 * be already converted to an absolute URI. 10966 */ 10967 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema, 10968 node, (xmlChar **) (&schemaLocation), type); 10969 if (res != 0) 10970 return(res); 10971 /* 10972 * Load and add the schema document. 10973 */ 10974 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL, 10975 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket); 10976 if (res != 0) 10977 return(res); 10978 /* 10979 * If we get no schema bucket back, then this means that the schema 10980 * document could not be located or was broken XML or was not 10981 * a schema document. 10982 */ 10983 if ((bucket == NULL) || (bucket->doc == NULL)) { 10984 if (type == XML_SCHEMA_SCHEMA_INCLUDE) { 10985 /* 10986 * WARNING for <include>: 10987 * We will raise an error if the schema cannot be located 10988 * for inclusions, since the that was the feedback from the 10989 * schema people. I.e. the following spec piece will *not* be 10990 * satisfied: 10991 * SPEC src-include: "It is not an error for the �actual value� of the 10992 * schemaLocation [attribute] to fail to resolve it all, in which 10993 * case no corresponding inclusion is performed. 10994 * So do we need a warning report here?" 10995 */ 10996 res = XML_SCHEMAP_SRC_INCLUDE; 10997 xmlSchemaCustomErr(ACTXT_CAST pctxt, res, 10998 node, NULL, 10999 "Failed to load the document '%s' for inclusion", 11000 schemaLocation, NULL); 11001 } else { 11002 /* 11003 * NOTE: This was changed to raise an error even if no redefinitions 11004 * are specified. 11005 * 11006 * SPEC src-redefine (1) 11007 * "If there are any element information items among the [children] 11008 * other than <annotation> then the �actual value� of the 11009 * schemaLocation [attribute] must successfully resolve." 11010 * TODO: Ask the WG if a the location has always to resolve 11011 * here as well! 11012 */ 11013 res = XML_SCHEMAP_SRC_REDEFINE; 11014 xmlSchemaCustomErr(ACTXT_CAST pctxt, res, 11015 node, NULL, 11016 "Failed to load the document '%s' for redefinition", 11017 schemaLocation, NULL); 11018 } 11019 } else { 11020 /* 11021 * Check targetNamespace sanity before parsing the new schema. 11022 * TODO: Note that we won't check further content if the 11023 * targetNamespace was bad. 11024 */ 11025 if (bucket->origTargetNamespace != NULL) { 11026 /* 11027 * SPEC src-include (2.1) 11028 * "SII has a targetNamespace [attribute], and its �actual 11029 * value� is identical to the �actual value� of the targetNamespace 11030 * [attribute] of SII� (which must have such an [attribute])." 11031 */ 11032 if (pctxt->targetNamespace == NULL) { 11033 xmlSchemaCustomErr(ACTXT_CAST pctxt, 11034 XML_SCHEMAP_SRC_INCLUDE, 11035 node, NULL, 11036 "The target namespace of the included/redefined schema " 11037 "'%s' has to be absent, since the including/redefining " 11038 "schema has no target namespace", 11039 schemaLocation, NULL); 11040 goto exit_error; 11041 } else if (!xmlStrEqual(bucket->origTargetNamespace, 11042 pctxt->targetNamespace)) { 11043 /* TODO: Change error function. */ 11044 xmlSchemaPCustomErrExt(pctxt, 11045 XML_SCHEMAP_SRC_INCLUDE, 11046 NULL, node, 11047 "The target namespace '%s' of the included/redefined " 11048 "schema '%s' differs from '%s' of the " 11049 "including/redefining schema", 11050 bucket->origTargetNamespace, schemaLocation, 11051 pctxt->targetNamespace); 11052 goto exit_error; 11053 } 11054 } else if (pctxt->targetNamespace != NULL) { 11055 /* 11056 * Chameleons: the original target namespace will 11057 * differ from the resulting namespace. 11058 */ 11059 isChameleon = 1; 11060 if (bucket->parsed && 11061 bucket->origTargetNamespace != NULL) { 11062 xmlSchemaCustomErr(ACTXT_CAST pctxt, 11063 XML_SCHEMAP_SRC_INCLUDE, 11064 node, NULL, 11065 "The target namespace of the included/redefined schema " 11066 "'%s' has to be absent or the same as the " 11067 "including/redefining schema's target namespace", 11068 schemaLocation, NULL); 11069 goto exit_error; 11070 } 11071 bucket->targetNamespace = pctxt->targetNamespace; 11072 } 11073 } 11074 /* 11075 * Parse the schema. 11076 */ 11077 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) { 11078 if (isChameleon) { 11079 /* TODO: Get rid of this flag on the schema itself. */ 11080 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) { 11081 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS; 11082 } else 11083 wasChameleon = 1; 11084 } 11085 xmlSchemaParseNewDoc(pctxt, schema, bucket); 11086 /* Restore chameleon flag. */ 11087 if (isChameleon && (!wasChameleon)) 11088 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS; 11089 } 11090 /* 11091 * And now for the children... 11092 */ 11093 child = node->children; 11094 if (type == XML_SCHEMA_SCHEMA_REDEFINE) { 11095 /* 11096 * Parse (simpleType | complexType | group | attributeGroup))* 11097 */ 11098 pctxt->redefined = bucket; 11099 /* 11100 * How to proceed if the redefined schema was not located? 11101 */ 11102 pctxt->isRedefine = 1; 11103 while (IS_SCHEMA(child, "annotation") || 11104 IS_SCHEMA(child, "simpleType") || 11105 IS_SCHEMA(child, "complexType") || 11106 IS_SCHEMA(child, "group") || 11107 IS_SCHEMA(child, "attributeGroup")) { 11108 if (IS_SCHEMA(child, "annotation")) { 11109 /* 11110 * TODO: discard or not? 11111 */ 11112 } else if (IS_SCHEMA(child, "simpleType")) { 11113 xmlSchemaParseSimpleType(pctxt, schema, child, 1); 11114 } else if (IS_SCHEMA(child, "complexType")) { 11115 xmlSchemaParseComplexType(pctxt, schema, child, 1); 11116 /* hasRedefinitions = 1; */ 11117 } else if (IS_SCHEMA(child, "group")) { 11118 /* hasRedefinitions = 1; */ 11119 xmlSchemaParseModelGroupDefinition(pctxt, 11120 schema, child); 11121 } else if (IS_SCHEMA(child, "attributeGroup")) { 11122 /* hasRedefinitions = 1; */ 11123 xmlSchemaParseAttributeGroupDefinition(pctxt, schema, 11124 child); 11125 } 11126 child = child->next; 11127 } 11128 pctxt->redefined = NULL; 11129 pctxt->isRedefine = 0; 11130 } else { 11131 if (IS_SCHEMA(child, "annotation")) { 11132 /* 11133 * TODO: discard or not? 11134 */ 11135 child = child->next; 11136 } 11137 } 11138 if (child != NULL) { 11139 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED; 11140 if (type == XML_SCHEMA_SCHEMA_REDEFINE) { 11141 xmlSchemaPContentErr(pctxt, res, 11142 NULL, node, child, NULL, 11143 "(annotation | (simpleType | complexType | group | attributeGroup))*"); 11144 } else { 11145 xmlSchemaPContentErr(pctxt, res, 11146 NULL, node, child, NULL, 11147 "(annotation?)"); 11148 } 11149 } 11150 return(res); 11151 11152exit_error: 11153 return(pctxt->err); 11154} 11155 11156static int 11157xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, 11158 xmlNodePtr node) 11159{ 11160 int res; 11161#ifndef ENABLE_REDEFINE 11162 TODO 11163 return(0); 11164#endif 11165 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, 11166 XML_SCHEMA_SCHEMA_REDEFINE); 11167 if (res != 0) 11168 return(res); 11169 return(0); 11170} 11171 11172static int 11173xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, 11174 xmlNodePtr node) 11175{ 11176 int res; 11177 11178 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, 11179 XML_SCHEMA_SCHEMA_INCLUDE); 11180 if (res != 0) 11181 return(res); 11182 return(0); 11183} 11184 11185/** 11186 * xmlSchemaParseModelGroup: 11187 * @ctxt: a schema validation context 11188 * @schema: the schema being built 11189 * @node: a subtree containing XML Schema informations 11190 * @type: the "compositor" type 11191 * @particleNeeded: if a a model group with a particle 11192 * 11193 * parse a XML schema Sequence definition. 11194 * Applies parts of: 11195 * Schema Representation Constraint: 11196 * Redefinition Constraints and Semantics (src-redefine) 11197 * (6.1), (6.1.1), (6.1.2) 11198 * 11199 * Schema Component Constraint: 11200 * All Group Limited (cos-all-limited) (2) 11201 * TODO: Actually this should go to component-level checks, 11202 * but is done here due to performance. Move it to an other layer 11203 * is schema construction via an API is implemented. 11204 * 11205 * *WARNING* this interface is highly subject to change 11206 * 11207 * Returns -1 in case of error, 0 if the declaration is improper and 11208 * 1 in case of success. 11209 */ 11210static xmlSchemaTreeItemPtr 11211xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 11212 xmlNodePtr node, xmlSchemaTypeType type, 11213 int withParticle) 11214{ 11215 xmlSchemaModelGroupPtr item; 11216 xmlSchemaParticlePtr particle = NULL; 11217 xmlNodePtr child = NULL; 11218 xmlAttrPtr attr; 11219 int min = 1, max = 1, isElemRef, hasRefs = 0; 11220 11221 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 11222 return (NULL); 11223 /* 11224 * Create a model group with the given compositor. 11225 */ 11226 item = xmlSchemaAddModelGroup(ctxt, schema, type, node); 11227 if (item == NULL) 11228 return (NULL); 11229 11230 if (withParticle) { 11231 if (type == XML_SCHEMA_TYPE_ALL) { 11232 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)"); 11233 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1"); 11234 } else { 11235 /* choice + sequence */ 11236 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger"); 11237 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, 11238 "(xs:nonNegativeInteger | unbounded)"); 11239 } 11240 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max); 11241 /* 11242 * Create a particle 11243 */ 11244 particle = xmlSchemaAddParticle(ctxt, node, min, max); 11245 if (particle == NULL) 11246 return (NULL); 11247 particle->children = (xmlSchemaTreeItemPtr) item; 11248 /* 11249 * Check for illegal attributes. 11250 */ 11251 attr = node->properties; 11252 while (attr != NULL) { 11253 if (attr->ns == NULL) { 11254 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 11255 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) && 11256 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) { 11257 xmlSchemaPIllegalAttrErr(ctxt, 11258 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 11259 } 11260 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 11261 xmlSchemaPIllegalAttrErr(ctxt, 11262 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 11263 } 11264 attr = attr->next; 11265 } 11266 } else { 11267 /* 11268 * Check for illegal attributes. 11269 */ 11270 attr = node->properties; 11271 while (attr != NULL) { 11272 if (attr->ns == NULL) { 11273 if (!xmlStrEqual(attr->name, BAD_CAST "id")) { 11274 xmlSchemaPIllegalAttrErr(ctxt, 11275 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 11276 } 11277 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 11278 xmlSchemaPIllegalAttrErr(ctxt, 11279 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 11280 } 11281 attr = attr->next; 11282 } 11283 } 11284 11285 /* 11286 * Extract and validate attributes. 11287 */ 11288 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 11289 /* 11290 * And now for the children... 11291 */ 11292 child = node->children; 11293 if (IS_SCHEMA(child, "annotation")) { 11294 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); 11295 child = child->next; 11296 } 11297 if (type == XML_SCHEMA_TYPE_ALL) { 11298 xmlSchemaParticlePtr part, last = NULL; 11299 11300 while (IS_SCHEMA(child, "element")) { 11301 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt, 11302 schema, child, &isElemRef, 0); 11303 /* 11304 * SPEC cos-all-limited (2) 11305 * "The {max occurs} of all the particles in the {particles} 11306 * of the ('all') group must be 0 or 1. 11307 */ 11308 if (part != NULL) { 11309 if (isElemRef) 11310 hasRefs++; 11311 if (part->minOccurs > 1) { 11312 xmlSchemaPCustomErr(ctxt, 11313 XML_SCHEMAP_COS_ALL_LIMITED, 11314 NULL, child, 11315 "Invalid value for minOccurs (must be 0 or 1)", 11316 NULL); 11317 /* Reset to 1. */ 11318 part->minOccurs = 1; 11319 } 11320 if (part->maxOccurs > 1) { 11321 xmlSchemaPCustomErr(ctxt, 11322 XML_SCHEMAP_COS_ALL_LIMITED, 11323 NULL, child, 11324 "Invalid value for maxOccurs (must be 0 or 1)", 11325 NULL); 11326 /* Reset to 1. */ 11327 part->maxOccurs = 1; 11328 } 11329 if (last == NULL) 11330 item->children = (xmlSchemaTreeItemPtr) part; 11331 else 11332 last->next = (xmlSchemaTreeItemPtr) part; 11333 last = part; 11334 } 11335 child = child->next; 11336 } 11337 if (child != NULL) { 11338 xmlSchemaPContentErr(ctxt, 11339 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 11340 NULL, node, child, NULL, 11341 "(annotation?, (annotation?, element*)"); 11342 } 11343 } else { 11344 /* choice + sequence */ 11345 xmlSchemaTreeItemPtr part = NULL, last = NULL; 11346 11347 while ((IS_SCHEMA(child, "element")) || 11348 (IS_SCHEMA(child, "group")) || 11349 (IS_SCHEMA(child, "any")) || 11350 (IS_SCHEMA(child, "choice")) || 11351 (IS_SCHEMA(child, "sequence"))) { 11352 11353 if (IS_SCHEMA(child, "element")) { 11354 part = (xmlSchemaTreeItemPtr) 11355 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0); 11356 if (part && isElemRef) 11357 hasRefs++; 11358 } else if (IS_SCHEMA(child, "group")) { 11359 part = 11360 xmlSchemaParseModelGroupDefRef(ctxt, schema, child); 11361 if (part != NULL) 11362 hasRefs++; 11363 /* 11364 * Handle redefinitions. 11365 */ 11366 if (ctxt->isRedefine && ctxt->redef && 11367 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) && 11368 part && part->children) 11369 { 11370 if ((xmlSchemaGetQNameRefName(part->children) == 11371 ctxt->redef->refName) && 11372 (xmlSchemaGetQNameRefTargetNs(part->children) == 11373 ctxt->redef->refTargetNs)) 11374 { 11375 /* 11376 * SPEC src-redefine: 11377 * (6.1) "If it has a <group> among its contents at 11378 * some level the �actual value� of whose ref 11379 * [attribute] is the same as the �actual value� of 11380 * its own name attribute plus target namespace, then 11381 * all of the following must be true:" 11382 * (6.1.1) "It must have exactly one such group." 11383 */ 11384 if (ctxt->redefCounter != 0) { 11385 xmlChar *str = NULL; 11386 11387 xmlSchemaCustomErr(ACTXT_CAST ctxt, 11388 XML_SCHEMAP_SRC_REDEFINE, child, NULL, 11389 "The redefining model group definition " 11390 "'%s' must not contain more than one " 11391 "reference to the redefined definition", 11392 xmlSchemaFormatQName(&str, 11393 ctxt->redef->refTargetNs, 11394 ctxt->redef->refName), 11395 NULL); 11396 FREE_AND_NULL(str) 11397 part = NULL; 11398 } else if (((WXS_PARTICLE(part))->minOccurs != 1) || 11399 ((WXS_PARTICLE(part))->maxOccurs != 1)) 11400 { 11401 xmlChar *str = NULL; 11402 /* 11403 * SPEC src-redefine: 11404 * (6.1.2) "The �actual value� of both that 11405 * group's minOccurs and maxOccurs [attribute] 11406 * must be 1 (or �absent�). 11407 */ 11408 xmlSchemaCustomErr(ACTXT_CAST ctxt, 11409 XML_SCHEMAP_SRC_REDEFINE, child, NULL, 11410 "The redefining model group definition " 11411 "'%s' must not contain a reference to the " 11412 "redefined definition with a " 11413 "maxOccurs/minOccurs other than 1", 11414 xmlSchemaFormatQName(&str, 11415 ctxt->redef->refTargetNs, 11416 ctxt->redef->refName), 11417 NULL); 11418 FREE_AND_NULL(str) 11419 part = NULL; 11420 } 11421 ctxt->redef->reference = WXS_BASIC_CAST part; 11422 ctxt->redefCounter++; 11423 } 11424 } 11425 } else if (IS_SCHEMA(child, "any")) { 11426 part = (xmlSchemaTreeItemPtr) 11427 xmlSchemaParseAny(ctxt, schema, child); 11428 } else if (IS_SCHEMA(child, "choice")) { 11429 part = xmlSchemaParseModelGroup(ctxt, schema, child, 11430 XML_SCHEMA_TYPE_CHOICE, 1); 11431 } else if (IS_SCHEMA(child, "sequence")) { 11432 part = xmlSchemaParseModelGroup(ctxt, schema, child, 11433 XML_SCHEMA_TYPE_SEQUENCE, 1); 11434 } 11435 if (part != NULL) { 11436 if (last == NULL) 11437 item->children = part; 11438 else 11439 last->next = part; 11440 last = part; 11441 } 11442 child = child->next; 11443 } 11444 if (child != NULL) { 11445 xmlSchemaPContentErr(ctxt, 11446 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 11447 NULL, node, child, NULL, 11448 "(annotation?, (element | group | choice | sequence | any)*)"); 11449 } 11450 } 11451 if ((max == 0) && (min == 0)) 11452 return (NULL); 11453 if (hasRefs) { 11454 /* 11455 * We need to resolve references. 11456 */ 11457 WXS_ADD_PENDING(ctxt, item); 11458 } 11459 if (withParticle) 11460 return ((xmlSchemaTreeItemPtr) particle); 11461 else 11462 return ((xmlSchemaTreeItemPtr) item); 11463} 11464 11465/** 11466 * xmlSchemaParseRestriction: 11467 * @ctxt: a schema validation context 11468 * @schema: the schema being built 11469 * @node: a subtree containing XML Schema informations 11470 * 11471 * parse a XML schema Restriction definition 11472 * *WARNING* this interface is highly subject to change 11473 * 11474 * Returns the type definition or NULL in case of error 11475 */ 11476static xmlSchemaTypePtr 11477xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 11478 xmlNodePtr node, xmlSchemaTypeType parentType) 11479{ 11480 xmlSchemaTypePtr type; 11481 xmlNodePtr child = NULL; 11482 xmlAttrPtr attr; 11483 11484 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 11485 return (NULL); 11486 /* Not a component, don't create it. */ 11487 type = ctxt->ctxtType; 11488 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION; 11489 11490 /* 11491 * Check for illegal attributes. 11492 */ 11493 attr = node->properties; 11494 while (attr != NULL) { 11495 if (attr->ns == NULL) { 11496 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 11497 (!xmlStrEqual(attr->name, BAD_CAST "base"))) { 11498 xmlSchemaPIllegalAttrErr(ctxt, 11499 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 11500 } 11501 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 11502 xmlSchemaPIllegalAttrErr(ctxt, 11503 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 11504 } 11505 attr = attr->next; 11506 } 11507 /* 11508 * Extract and validate attributes. 11509 */ 11510 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 11511 /* 11512 * Attribute 11513 */ 11514 /* 11515 * Extract the base type. The "base" attribute is mandatory if inside 11516 * a complex type or if redefining. 11517 * 11518 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> " 11519 * among its [children]), the simple type definition which is 11520 * the {content type} of the type definition �resolved� to by 11521 * the �actual value� of the base [attribute]" 11522 */ 11523 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base", 11524 &(type->baseNs), &(type->base)) == 0) 11525 { 11526 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) { 11527 xmlSchemaPMissingAttrErr(ctxt, 11528 XML_SCHEMAP_S4S_ATTR_MISSING, 11529 NULL, node, "base", NULL); 11530 } else if ((ctxt->isRedefine) && 11531 (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) 11532 { 11533 if (type->base == NULL) { 11534 xmlSchemaPMissingAttrErr(ctxt, 11535 XML_SCHEMAP_S4S_ATTR_MISSING, 11536 NULL, node, "base", NULL); 11537 } else if ((! xmlStrEqual(type->base, type->name)) || 11538 (! xmlStrEqual(type->baseNs, type->targetNamespace))) 11539 { 11540 xmlChar *str1 = NULL, *str2 = NULL; 11541 /* 11542 * REDEFINE: SPEC src-redefine (5) 11543 * "Within the [children], each <simpleType> must have a 11544 * <restriction> among its [children] ... the �actual value� of 11545 * whose base [attribute] must be the same as the �actual value� 11546 * of its own name attribute plus target namespace;" 11547 */ 11548 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE, 11549 NULL, node, "This is a redefinition, but the QName " 11550 "value '%s' of the 'base' attribute does not match the " 11551 "type's designation '%s'", 11552 xmlSchemaFormatQName(&str1, type->baseNs, type->base), 11553 xmlSchemaFormatQName(&str2, type->targetNamespace, 11554 type->name), NULL); 11555 FREE_AND_NULL(str1); 11556 FREE_AND_NULL(str2); 11557 /* Avoid confusion and erase the values. */ 11558 type->base = NULL; 11559 type->baseNs = NULL; 11560 } 11561 } 11562 } 11563 /* 11564 * And now for the children... 11565 */ 11566 child = node->children; 11567 if (IS_SCHEMA(child, "annotation")) { 11568 /* 11569 * Add the annotation to the simple type ancestor. 11570 */ 11571 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, 11572 xmlSchemaParseAnnotation(ctxt, child, 1)); 11573 child = child->next; 11574 } 11575 if (parentType == XML_SCHEMA_TYPE_SIMPLE) { 11576 /* 11577 * Corresponds to <simpleType><restriction><simpleType>. 11578 */ 11579 if (IS_SCHEMA(child, "simpleType")) { 11580 if (type->base != NULL) { 11581 /* 11582 * src-restriction-base-or-simpleType 11583 * Either the base [attribute] or the simpleType [child] of the 11584 * <restriction> element must be present, but not both. 11585 */ 11586 xmlSchemaPContentErr(ctxt, 11587 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE, 11588 NULL, node, child, 11589 "The attribute 'base' and the <simpleType> child are " 11590 "mutually exclusive", NULL); 11591 } else { 11592 type->baseType = (xmlSchemaTypePtr) 11593 xmlSchemaParseSimpleType(ctxt, schema, child, 0); 11594 } 11595 child = child->next; 11596 } else if (type->base == NULL) { 11597 xmlSchemaPContentErr(ctxt, 11598 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE, 11599 NULL, node, child, 11600 "Either the attribute 'base' or a <simpleType> child " 11601 "must be present", NULL); 11602 } 11603 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { 11604 /* 11605 * Corresponds to <complexType><complexContent><restriction>... 11606 * followed by: 11607 * 11608 * Model groups <all>, <choice> and <sequence>. 11609 */ 11610 if (IS_SCHEMA(child, "all")) { 11611 type->subtypes = (xmlSchemaTypePtr) 11612 xmlSchemaParseModelGroup(ctxt, schema, child, 11613 XML_SCHEMA_TYPE_ALL, 1); 11614 child = child->next; 11615 } else if (IS_SCHEMA(child, "choice")) { 11616 type->subtypes = (xmlSchemaTypePtr) 11617 xmlSchemaParseModelGroup(ctxt, 11618 schema, child, XML_SCHEMA_TYPE_CHOICE, 1); 11619 child = child->next; 11620 } else if (IS_SCHEMA(child, "sequence")) { 11621 type->subtypes = (xmlSchemaTypePtr) 11622 xmlSchemaParseModelGroup(ctxt, schema, child, 11623 XML_SCHEMA_TYPE_SEQUENCE, 1); 11624 child = child->next; 11625 /* 11626 * Model group reference <group>. 11627 */ 11628 } else if (IS_SCHEMA(child, "group")) { 11629 type->subtypes = (xmlSchemaTypePtr) 11630 xmlSchemaParseModelGroupDefRef(ctxt, schema, child); 11631 /* 11632 * Note that the reference will be resolved in 11633 * xmlSchemaResolveTypeReferences(); 11634 */ 11635 child = child->next; 11636 } 11637 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) { 11638 /* 11639 * Corresponds to <complexType><simpleContent><restriction>... 11640 * 11641 * "1.1 the simple type definition corresponding to the <simpleType> 11642 * among the [children] of <restriction> if there is one;" 11643 */ 11644 if (IS_SCHEMA(child, "simpleType")) { 11645 /* 11646 * We will store the to-be-restricted simple type in 11647 * type->contentTypeDef *temporarily*. 11648 */ 11649 type->contentTypeDef = (xmlSchemaTypePtr) 11650 xmlSchemaParseSimpleType(ctxt, schema, child, 0); 11651 if ( type->contentTypeDef == NULL) 11652 return (NULL); 11653 child = child->next; 11654 } 11655 } 11656 11657 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) || 11658 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) { 11659 xmlSchemaFacetPtr facet, lastfacet = NULL; 11660 /* 11661 * Corresponds to <complexType><simpleContent><restriction>... 11662 * <simpleType><restriction>... 11663 */ 11664 11665 /* 11666 * Add the facets to the simple type ancestor. 11667 */ 11668 /* 11669 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of 11670 * Simple Type Definition Schema Representation Constraint: 11671 * *Single Facet Value* 11672 */ 11673 while ((IS_SCHEMA(child, "minInclusive")) || 11674 (IS_SCHEMA(child, "minExclusive")) || 11675 (IS_SCHEMA(child, "maxInclusive")) || 11676 (IS_SCHEMA(child, "maxExclusive")) || 11677 (IS_SCHEMA(child, "totalDigits")) || 11678 (IS_SCHEMA(child, "fractionDigits")) || 11679 (IS_SCHEMA(child, "pattern")) || 11680 (IS_SCHEMA(child, "enumeration")) || 11681 (IS_SCHEMA(child, "whiteSpace")) || 11682 (IS_SCHEMA(child, "length")) || 11683 (IS_SCHEMA(child, "maxLength")) || 11684 (IS_SCHEMA(child, "minLength"))) { 11685 facet = xmlSchemaParseFacet(ctxt, schema, child); 11686 if (facet != NULL) { 11687 if (lastfacet == NULL) 11688 type->facets = facet; 11689 else 11690 lastfacet->next = facet; 11691 lastfacet = facet; 11692 lastfacet->next = NULL; 11693 } 11694 child = child->next; 11695 } 11696 /* 11697 * Create links for derivation and validation. 11698 */ 11699 if (type->facets != NULL) { 11700 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL; 11701 11702 facet = type->facets; 11703 do { 11704 facetLink = (xmlSchemaFacetLinkPtr) 11705 xmlMalloc(sizeof(xmlSchemaFacetLink)); 11706 if (facetLink == NULL) { 11707 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL); 11708 xmlFree(facetLink); 11709 return (NULL); 11710 } 11711 facetLink->facet = facet; 11712 facetLink->next = NULL; 11713 if (lastFacetLink == NULL) 11714 type->facetSet = facetLink; 11715 else 11716 lastFacetLink->next = facetLink; 11717 lastFacetLink = facetLink; 11718 facet = facet->next; 11719 } while (facet != NULL); 11720 } 11721 } 11722 if (type->type == XML_SCHEMA_TYPE_COMPLEX) { 11723 /* 11724 * Attribute uses/declarations. 11725 */ 11726 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child, 11727 (xmlSchemaItemListPtr *) &(type->attrUses), 11728 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1) 11729 return(NULL); 11730 /* 11731 * Attribute wildcard. 11732 */ 11733 if (IS_SCHEMA(child, "anyAttribute")) { 11734 type->attributeWildcard = 11735 xmlSchemaParseAnyAttribute(ctxt, schema, child); 11736 child = child->next; 11737 } 11738 } 11739 if (child != NULL) { 11740 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { 11741 xmlSchemaPContentErr(ctxt, 11742 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 11743 NULL, node, child, NULL, 11744 "annotation?, (group | all | choice | sequence)?, " 11745 "((attribute | attributeGroup)*, anyAttribute?))"); 11746 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) { 11747 xmlSchemaPContentErr(ctxt, 11748 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 11749 NULL, node, child, NULL, 11750 "(annotation?, (simpleType?, (minExclusive | minInclusive | " 11751 "maxExclusive | maxInclusive | totalDigits | fractionDigits | " 11752 "length | minLength | maxLength | enumeration | whiteSpace | " 11753 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))"); 11754 } else { 11755 /* Simple type */ 11756 xmlSchemaPContentErr(ctxt, 11757 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 11758 NULL, node, child, NULL, 11759 "(annotation?, (simpleType?, (minExclusive | minInclusive | " 11760 "maxExclusive | maxInclusive | totalDigits | fractionDigits | " 11761 "length | minLength | maxLength | enumeration | whiteSpace | " 11762 "pattern)*))"); 11763 } 11764 } 11765 return (NULL); 11766} 11767 11768/** 11769 * xmlSchemaParseExtension: 11770 * @ctxt: a schema validation context 11771 * @schema: the schema being built 11772 * @node: a subtree containing XML Schema informations 11773 * 11774 * Parses an <extension>, which is found inside a 11775 * <simpleContent> or <complexContent>. 11776 * *WARNING* this interface is highly subject to change. 11777 * 11778 * TODO: Returns the type definition or NULL in case of error 11779 */ 11780static xmlSchemaTypePtr 11781xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 11782 xmlNodePtr node, xmlSchemaTypeType parentType) 11783{ 11784 xmlSchemaTypePtr type; 11785 xmlNodePtr child = NULL; 11786 xmlAttrPtr attr; 11787 11788 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 11789 return (NULL); 11790 /* Not a component, don't create it. */ 11791 type = ctxt->ctxtType; 11792 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION; 11793 11794 /* 11795 * Check for illegal attributes. 11796 */ 11797 attr = node->properties; 11798 while (attr != NULL) { 11799 if (attr->ns == NULL) { 11800 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 11801 (!xmlStrEqual(attr->name, BAD_CAST "base"))) { 11802 xmlSchemaPIllegalAttrErr(ctxt, 11803 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 11804 } 11805 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 11806 xmlSchemaPIllegalAttrErr(ctxt, 11807 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 11808 } 11809 attr = attr->next; 11810 } 11811 11812 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 11813 11814 /* 11815 * Attribute "base" - mandatory. 11816 */ 11817 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node, 11818 "base", &(type->baseNs), &(type->base)) == 0) && 11819 (type->base == NULL)) { 11820 xmlSchemaPMissingAttrErr(ctxt, 11821 XML_SCHEMAP_S4S_ATTR_MISSING, 11822 NULL, node, "base", NULL); 11823 } 11824 /* 11825 * And now for the children... 11826 */ 11827 child = node->children; 11828 if (IS_SCHEMA(child, "annotation")) { 11829 /* 11830 * Add the annotation to the type ancestor. 11831 */ 11832 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, 11833 xmlSchemaParseAnnotation(ctxt, child, 1)); 11834 child = child->next; 11835 } 11836 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { 11837 /* 11838 * Corresponds to <complexType><complexContent><extension>... and: 11839 * 11840 * Model groups <all>, <choice>, <sequence> and <group>. 11841 */ 11842 if (IS_SCHEMA(child, "all")) { 11843 type->subtypes = (xmlSchemaTypePtr) 11844 xmlSchemaParseModelGroup(ctxt, schema, 11845 child, XML_SCHEMA_TYPE_ALL, 1); 11846 child = child->next; 11847 } else if (IS_SCHEMA(child, "choice")) { 11848 type->subtypes = (xmlSchemaTypePtr) 11849 xmlSchemaParseModelGroup(ctxt, schema, 11850 child, XML_SCHEMA_TYPE_CHOICE, 1); 11851 child = child->next; 11852 } else if (IS_SCHEMA(child, "sequence")) { 11853 type->subtypes = (xmlSchemaTypePtr) 11854 xmlSchemaParseModelGroup(ctxt, schema, 11855 child, XML_SCHEMA_TYPE_SEQUENCE, 1); 11856 child = child->next; 11857 } else if (IS_SCHEMA(child, "group")) { 11858 type->subtypes = (xmlSchemaTypePtr) 11859 xmlSchemaParseModelGroupDefRef(ctxt, schema, child); 11860 /* 11861 * Note that the reference will be resolved in 11862 * xmlSchemaResolveTypeReferences(); 11863 */ 11864 child = child->next; 11865 } 11866 } 11867 if (child != NULL) { 11868 /* 11869 * Attribute uses/declarations. 11870 */ 11871 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child, 11872 (xmlSchemaItemListPtr *) &(type->attrUses), 11873 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1) 11874 return(NULL); 11875 /* 11876 * Attribute wildcard. 11877 */ 11878 if (IS_SCHEMA(child, "anyAttribute")) { 11879 ctxt->ctxtType->attributeWildcard = 11880 xmlSchemaParseAnyAttribute(ctxt, schema, child); 11881 child = child->next; 11882 } 11883 } 11884 if (child != NULL) { 11885 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { 11886 /* Complex content extension. */ 11887 xmlSchemaPContentErr(ctxt, 11888 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 11889 NULL, node, child, NULL, 11890 "(annotation?, ((group | all | choice | sequence)?, " 11891 "((attribute | attributeGroup)*, anyAttribute?)))"); 11892 } else { 11893 /* Simple content extension. */ 11894 xmlSchemaPContentErr(ctxt, 11895 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 11896 NULL, node, child, NULL, 11897 "(annotation?, ((attribute | attributeGroup)*, " 11898 "anyAttribute?))"); 11899 } 11900 } 11901 return (NULL); 11902} 11903 11904/** 11905 * xmlSchemaParseSimpleContent: 11906 * @ctxt: a schema validation context 11907 * @schema: the schema being built 11908 * @node: a subtree containing XML Schema informations 11909 * 11910 * parse a XML schema SimpleContent definition 11911 * *WARNING* this interface is highly subject to change 11912 * 11913 * Returns the type definition or NULL in case of error 11914 */ 11915static int 11916xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt, 11917 xmlSchemaPtr schema, xmlNodePtr node, 11918 int *hasRestrictionOrExtension) 11919{ 11920 xmlSchemaTypePtr type; 11921 xmlNodePtr child = NULL; 11922 xmlAttrPtr attr; 11923 11924 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || 11925 (hasRestrictionOrExtension == NULL)) 11926 return (-1); 11927 *hasRestrictionOrExtension = 0; 11928 /* Not a component, don't create it. */ 11929 type = ctxt->ctxtType; 11930 type->contentType = XML_SCHEMA_CONTENT_SIMPLE; 11931 /* 11932 * Check for illegal attributes. 11933 */ 11934 attr = node->properties; 11935 while (attr != NULL) { 11936 if (attr->ns == NULL) { 11937 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) { 11938 xmlSchemaPIllegalAttrErr(ctxt, 11939 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 11940 } 11941 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 11942 xmlSchemaPIllegalAttrErr(ctxt, 11943 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 11944 } 11945 attr = attr->next; 11946 } 11947 11948 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 11949 11950 /* 11951 * And now for the children... 11952 */ 11953 child = node->children; 11954 if (IS_SCHEMA(child, "annotation")) { 11955 /* 11956 * Add the annotation to the complex type ancestor. 11957 */ 11958 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, 11959 xmlSchemaParseAnnotation(ctxt, child, 1)); 11960 child = child->next; 11961 } 11962 if (child == NULL) { 11963 xmlSchemaPContentErr(ctxt, 11964 XML_SCHEMAP_S4S_ELEM_MISSING, 11965 NULL, node, NULL, NULL, 11966 "(annotation?, (restriction | extension))"); 11967 } 11968 if (child == NULL) { 11969 xmlSchemaPContentErr(ctxt, 11970 XML_SCHEMAP_S4S_ELEM_MISSING, 11971 NULL, node, NULL, NULL, 11972 "(annotation?, (restriction | extension))"); 11973 } 11974 if (IS_SCHEMA(child, "restriction")) { 11975 xmlSchemaParseRestriction(ctxt, schema, child, 11976 XML_SCHEMA_TYPE_SIMPLE_CONTENT); 11977 (*hasRestrictionOrExtension) = 1; 11978 child = child->next; 11979 } else if (IS_SCHEMA(child, "extension")) { 11980 xmlSchemaParseExtension(ctxt, schema, child, 11981 XML_SCHEMA_TYPE_SIMPLE_CONTENT); 11982 (*hasRestrictionOrExtension) = 1; 11983 child = child->next; 11984 } 11985 if (child != NULL) { 11986 xmlSchemaPContentErr(ctxt, 11987 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 11988 NULL, node, child, NULL, 11989 "(annotation?, (restriction | extension))"); 11990 } 11991 return (0); 11992} 11993 11994/** 11995 * xmlSchemaParseComplexContent: 11996 * @ctxt: a schema validation context 11997 * @schema: the schema being built 11998 * @node: a subtree containing XML Schema informations 11999 * 12000 * parse a XML schema ComplexContent definition 12001 * *WARNING* this interface is highly subject to change 12002 * 12003 * Returns the type definition or NULL in case of error 12004 */ 12005static int 12006xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt, 12007 xmlSchemaPtr schema, xmlNodePtr node, 12008 int *hasRestrictionOrExtension) 12009{ 12010 xmlSchemaTypePtr type; 12011 xmlNodePtr child = NULL; 12012 xmlAttrPtr attr; 12013 12014 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || 12015 (hasRestrictionOrExtension == NULL)) 12016 return (-1); 12017 *hasRestrictionOrExtension = 0; 12018 /* Not a component, don't create it. */ 12019 type = ctxt->ctxtType; 12020 /* 12021 * Check for illegal attributes. 12022 */ 12023 attr = node->properties; 12024 while (attr != NULL) { 12025 if (attr->ns == NULL) { 12026 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && 12027 (!xmlStrEqual(attr->name, BAD_CAST "mixed"))) 12028 { 12029 xmlSchemaPIllegalAttrErr(ctxt, 12030 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 12031 } 12032 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 12033 xmlSchemaPIllegalAttrErr(ctxt, 12034 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 12035 } 12036 attr = attr->next; 12037 } 12038 12039 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 12040 12041 /* 12042 * Set the 'mixed' on the complex type ancestor. 12043 */ 12044 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) { 12045 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0) 12046 type->flags |= XML_SCHEMAS_TYPE_MIXED; 12047 } 12048 child = node->children; 12049 if (IS_SCHEMA(child, "annotation")) { 12050 /* 12051 * Add the annotation to the complex type ancestor. 12052 */ 12053 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, 12054 xmlSchemaParseAnnotation(ctxt, child, 1)); 12055 child = child->next; 12056 } 12057 if (child == NULL) { 12058 xmlSchemaPContentErr(ctxt, 12059 XML_SCHEMAP_S4S_ELEM_MISSING, 12060 NULL, node, NULL, 12061 NULL, "(annotation?, (restriction | extension))"); 12062 } 12063 if (child == NULL) { 12064 xmlSchemaPContentErr(ctxt, 12065 XML_SCHEMAP_S4S_ELEM_MISSING, 12066 NULL, node, NULL, 12067 NULL, "(annotation?, (restriction | extension))"); 12068 } 12069 if (IS_SCHEMA(child, "restriction")) { 12070 xmlSchemaParseRestriction(ctxt, schema, child, 12071 XML_SCHEMA_TYPE_COMPLEX_CONTENT); 12072 (*hasRestrictionOrExtension) = 1; 12073 child = child->next; 12074 } else if (IS_SCHEMA(child, "extension")) { 12075 xmlSchemaParseExtension(ctxt, schema, child, 12076 XML_SCHEMA_TYPE_COMPLEX_CONTENT); 12077 (*hasRestrictionOrExtension) = 1; 12078 child = child->next; 12079 } 12080 if (child != NULL) { 12081 xmlSchemaPContentErr(ctxt, 12082 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 12083 NULL, node, child, 12084 NULL, "(annotation?, (restriction | extension))"); 12085 } 12086 return (0); 12087} 12088 12089/** 12090 * xmlSchemaParseComplexType: 12091 * @ctxt: a schema validation context 12092 * @schema: the schema being built 12093 * @node: a subtree containing XML Schema informations 12094 * 12095 * parse a XML schema Complex Type definition 12096 * *WARNING* this interface is highly subject to change 12097 * 12098 * Returns the type definition or NULL in case of error 12099 */ 12100static xmlSchemaTypePtr 12101xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 12102 xmlNodePtr node, int topLevel) 12103{ 12104 xmlSchemaTypePtr type, ctxtType; 12105 xmlNodePtr child = NULL; 12106 const xmlChar *name = NULL; 12107 xmlAttrPtr attr; 12108 const xmlChar *attrValue; 12109#ifdef ENABLE_NAMED_LOCALS 12110 char buf[40]; 12111#endif 12112 int final = 0, block = 0, hasRestrictionOrExtension = 0; 12113 12114 12115 if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) 12116 return (NULL); 12117 12118 ctxtType = ctxt->ctxtType; 12119 12120 if (topLevel) { 12121 attr = xmlSchemaGetPropNode(node, "name"); 12122 if (attr == NULL) { 12123 xmlSchemaPMissingAttrErr(ctxt, 12124 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL); 12125 return (NULL); 12126 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr, 12127 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { 12128 return (NULL); 12129 } 12130 } 12131 12132 if (topLevel == 0) { 12133 /* 12134 * Parse as local complex type definition. 12135 */ 12136#ifdef ENABLE_NAMED_LOCALS 12137 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1); 12138 type = xmlSchemaAddType(ctxt, schema, 12139 XML_SCHEMA_TYPE_COMPLEX, 12140 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1), 12141 ctxt->targetNamespace, node, 0); 12142#else 12143 type = xmlSchemaAddType(ctxt, schema, 12144 XML_SCHEMA_TYPE_COMPLEX, 12145 NULL, ctxt->targetNamespace, node, 0); 12146#endif 12147 if (type == NULL) 12148 return (NULL); 12149 name = type->name; 12150 type->node = node; 12151 type->type = XML_SCHEMA_TYPE_COMPLEX; 12152 /* 12153 * TODO: We need the target namespace. 12154 */ 12155 } else { 12156 /* 12157 * Parse as global complex type definition. 12158 */ 12159 type = xmlSchemaAddType(ctxt, schema, 12160 XML_SCHEMA_TYPE_COMPLEX, 12161 name, ctxt->targetNamespace, node, 1); 12162 if (type == NULL) 12163 return (NULL); 12164 type->node = node; 12165 type->type = XML_SCHEMA_TYPE_COMPLEX; 12166 type->flags |= XML_SCHEMAS_TYPE_GLOBAL; 12167 } 12168 type->targetNamespace = ctxt->targetNamespace; 12169 /* 12170 * Handle attributes. 12171 */ 12172 attr = node->properties; 12173 while (attr != NULL) { 12174 if (attr->ns == NULL) { 12175 if (xmlStrEqual(attr->name, BAD_CAST "id")) { 12176 /* 12177 * Attribute "id". 12178 */ 12179 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); 12180 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) { 12181 /* 12182 * Attribute "mixed". 12183 */ 12184 if (xmlSchemaPGetBoolNodeValue(ctxt, 12185 NULL, (xmlNodePtr) attr)) 12186 type->flags |= XML_SCHEMAS_TYPE_MIXED; 12187 } else if (topLevel) { 12188 /* 12189 * Attributes of global complex type definitions. 12190 */ 12191 if (xmlStrEqual(attr->name, BAD_CAST "name")) { 12192 /* Pass. */ 12193 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) { 12194 /* 12195 * Attribute "abstract". 12196 */ 12197 if (xmlSchemaPGetBoolNodeValue(ctxt, 12198 NULL, (xmlNodePtr) attr)) 12199 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT; 12200 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) { 12201 /* 12202 * Attribute "final". 12203 */ 12204 attrValue = xmlSchemaGetNodeContent(ctxt, 12205 (xmlNodePtr) attr); 12206 if (xmlSchemaPValAttrBlockFinal(attrValue, 12207 &(type->flags), 12208 -1, 12209 XML_SCHEMAS_TYPE_FINAL_EXTENSION, 12210 XML_SCHEMAS_TYPE_FINAL_RESTRICTION, 12211 -1, -1, -1) != 0) 12212 { 12213 xmlSchemaPSimpleTypeErr(ctxt, 12214 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 12215 NULL, (xmlNodePtr) attr, NULL, 12216 "(#all | List of (extension | restriction))", 12217 attrValue, NULL, NULL, NULL); 12218 } else 12219 final = 1; 12220 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) { 12221 /* 12222 * Attribute "block". 12223 */ 12224 attrValue = xmlSchemaGetNodeContent(ctxt, 12225 (xmlNodePtr) attr); 12226 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags), 12227 -1, 12228 XML_SCHEMAS_TYPE_BLOCK_EXTENSION, 12229 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION, 12230 -1, -1, -1) != 0) { 12231 xmlSchemaPSimpleTypeErr(ctxt, 12232 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 12233 NULL, (xmlNodePtr) attr, NULL, 12234 "(#all | List of (extension | restriction)) ", 12235 attrValue, NULL, NULL, NULL); 12236 } else 12237 block = 1; 12238 } else { 12239 xmlSchemaPIllegalAttrErr(ctxt, 12240 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 12241 } 12242 } else { 12243 xmlSchemaPIllegalAttrErr(ctxt, 12244 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 12245 } 12246 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { 12247 xmlSchemaPIllegalAttrErr(ctxt, 12248 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); 12249 } 12250 attr = attr->next; 12251 } 12252 if (! block) { 12253 /* 12254 * Apply default "block" values. 12255 */ 12256 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION) 12257 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; 12258 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION) 12259 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; 12260 } 12261 if (! final) { 12262 /* 12263 * Apply default "block" values. 12264 */ 12265 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) 12266 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION; 12267 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) 12268 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION; 12269 } 12270 /* 12271 * And now for the children... 12272 */ 12273 child = node->children; 12274 if (IS_SCHEMA(child, "annotation")) { 12275 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1); 12276 child = child->next; 12277 } 12278 ctxt->ctxtType = type; 12279 if (IS_SCHEMA(child, "simpleContent")) { 12280 /* 12281 * <complexType><simpleContent>... 12282 * 3.4.3 : 2.2 12283 * Specifying mixed='true' when the <simpleContent> 12284 * alternative is chosen has no effect 12285 */ 12286 if (type->flags & XML_SCHEMAS_TYPE_MIXED) 12287 type->flags ^= XML_SCHEMAS_TYPE_MIXED; 12288 xmlSchemaParseSimpleContent(ctxt, schema, child, 12289 &hasRestrictionOrExtension); 12290 child = child->next; 12291 } else if (IS_SCHEMA(child, "complexContent")) { 12292 /* 12293 * <complexType><complexContent>... 12294 */ 12295 type->contentType = XML_SCHEMA_CONTENT_EMPTY; 12296 xmlSchemaParseComplexContent(ctxt, schema, child, 12297 &hasRestrictionOrExtension); 12298 child = child->next; 12299 } else { 12300 /* 12301 * E.g <complexType><sequence>... or <complexType><attribute>... etc. 12302 * 12303 * SPEC 12304 * "...the third alternative (neither <simpleContent> nor 12305 * <complexContent>) is chosen. This case is understood as shorthand 12306 * for complex content restricting the �ur-type definition�, and the 12307 * details of the mappings should be modified as necessary. 12308 */ 12309 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); 12310 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION; 12311 /* 12312 * Parse model groups. 12313 */ 12314 if (IS_SCHEMA(child, "all")) { 12315 type->subtypes = (xmlSchemaTypePtr) 12316 xmlSchemaParseModelGroup(ctxt, schema, child, 12317 XML_SCHEMA_TYPE_ALL, 1); 12318 child = child->next; 12319 } else if (IS_SCHEMA(child, "choice")) { 12320 type->subtypes = (xmlSchemaTypePtr) 12321 xmlSchemaParseModelGroup(ctxt, schema, child, 12322 XML_SCHEMA_TYPE_CHOICE, 1); 12323 child = child->next; 12324 } else if (IS_SCHEMA(child, "sequence")) { 12325 type->subtypes = (xmlSchemaTypePtr) 12326 xmlSchemaParseModelGroup(ctxt, schema, child, 12327 XML_SCHEMA_TYPE_SEQUENCE, 1); 12328 child = child->next; 12329 } else if (IS_SCHEMA(child, "group")) { 12330 type->subtypes = (xmlSchemaTypePtr) 12331 xmlSchemaParseModelGroupDefRef(ctxt, schema, child); 12332 /* 12333 * Note that the reference will be resolved in 12334 * xmlSchemaResolveTypeReferences(); 12335 */ 12336 child = child->next; 12337 } 12338 /* 12339 * Parse attribute decls/refs. 12340 */ 12341 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child, 12342 (xmlSchemaItemListPtr *) &(type->attrUses), 12343 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1) 12344 return(NULL); 12345 /* 12346 * Parse attribute wildcard. 12347 */ 12348 if (IS_SCHEMA(child, "anyAttribute")) { 12349 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child); 12350 child = child->next; 12351 } 12352 } 12353 if (child != NULL) { 12354 xmlSchemaPContentErr(ctxt, 12355 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, 12356 NULL, node, child, 12357 NULL, "(annotation?, (simpleContent | complexContent | " 12358 "((group | all | choice | sequence)?, ((attribute | " 12359 "attributeGroup)*, anyAttribute?))))"); 12360 } 12361 /* 12362 * REDEFINE: SPEC src-redefine (5) 12363 */ 12364 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) { 12365 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, 12366 NULL, node, "This is a redefinition, thus the " 12367 "<complexType> must have a <restriction> or <extension> " 12368 "grand-child", NULL); 12369 } 12370 ctxt->ctxtType = ctxtType; 12371 return (type); 12372} 12373 12374/************************************************************************ 12375 * * 12376 * Validating using Schemas * 12377 * * 12378 ************************************************************************/ 12379 12380/************************************************************************ 12381 * * 12382 * Reading/Writing Schemas * 12383 * * 12384 ************************************************************************/ 12385 12386#if 0 /* Will be enabled if it is clear what options are needed. */ 12387/** 12388 * xmlSchemaParserCtxtSetOptions: 12389 * @ctxt: a schema parser context 12390 * @options: a combination of xmlSchemaParserOption 12391 * 12392 * Sets the options to be used during the parse. 12393 * 12394 * Returns 0 in case of success, -1 in case of an 12395 * API error. 12396 */ 12397static int 12398xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt, 12399 int options) 12400 12401{ 12402 int i; 12403 12404 if (ctxt == NULL) 12405 return (-1); 12406 /* 12407 * WARNING: Change the start value if adding to the 12408 * xmlSchemaParseOption. 12409 */ 12410 for (i = 1; i < (int) sizeof(int) * 8; i++) { 12411 if (options & 1<<i) { 12412 return (-1); 12413 } 12414 } 12415 ctxt->options = options; 12416 return (0); 12417} 12418 12419/** 12420 * xmlSchemaValidCtxtGetOptions: 12421 * @ctxt: a schema parser context 12422 * 12423 * Returns the option combination of the parser context. 12424 */ 12425static int 12426xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt) 12427 12428{ 12429 if (ctxt == NULL) 12430 return (-1); 12431 else 12432 return (ctxt->options); 12433} 12434#endif 12435 12436/** 12437 * xmlSchemaNewParserCtxt: 12438 * @URL: the location of the schema 12439 * 12440 * Create an XML Schemas parse context for that file/resource expected 12441 * to contain an XML Schemas file. 12442 * 12443 * Returns the parser context or NULL in case of error 12444 */ 12445xmlSchemaParserCtxtPtr 12446xmlSchemaNewParserCtxt(const char *URL) 12447{ 12448 xmlSchemaParserCtxtPtr ret; 12449 12450 if (URL == NULL) 12451 return (NULL); 12452 12453 ret = xmlSchemaParserCtxtCreate(); 12454 if (ret == NULL) 12455 return(NULL); 12456 ret->dict = xmlDictCreate(); 12457 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1); 12458 return (ret); 12459} 12460 12461/** 12462 * xmlSchemaNewMemParserCtxt: 12463 * @buffer: a pointer to a char array containing the schemas 12464 * @size: the size of the array 12465 * 12466 * Create an XML Schemas parse context for that memory buffer expected 12467 * to contain an XML Schemas file. 12468 * 12469 * Returns the parser context or NULL in case of error 12470 */ 12471xmlSchemaParserCtxtPtr 12472xmlSchemaNewMemParserCtxt(const char *buffer, int size) 12473{ 12474 xmlSchemaParserCtxtPtr ret; 12475 12476 if ((buffer == NULL) || (size <= 0)) 12477 return (NULL); 12478 ret = xmlSchemaParserCtxtCreate(); 12479 if (ret == NULL) 12480 return(NULL); 12481 ret->buffer = buffer; 12482 ret->size = size; 12483 ret->dict = xmlDictCreate(); 12484 return (ret); 12485} 12486 12487/** 12488 * xmlSchemaNewDocParserCtxt: 12489 * @doc: a preparsed document tree 12490 * 12491 * Create an XML Schemas parse context for that document. 12492 * NB. The document may be modified during the parsing process. 12493 * 12494 * Returns the parser context or NULL in case of error 12495 */ 12496xmlSchemaParserCtxtPtr 12497xmlSchemaNewDocParserCtxt(xmlDocPtr doc) 12498{ 12499 xmlSchemaParserCtxtPtr ret; 12500 12501 if (doc == NULL) 12502 return (NULL); 12503 ret = xmlSchemaParserCtxtCreate(); 12504 if (ret == NULL) 12505 return(NULL); 12506 ret->doc = doc; 12507 ret->dict = xmlDictCreate(); 12508 /* The application has responsibility for the document */ 12509 ret->preserve = 1; 12510 12511 return (ret); 12512} 12513 12514/** 12515 * xmlSchemaFreeParserCtxt: 12516 * @ctxt: the schema parser context 12517 * 12518 * Free the resources associated to the schema parser context 12519 */ 12520void 12521xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt) 12522{ 12523 if (ctxt == NULL) 12524 return; 12525 if (ctxt->doc != NULL && !ctxt->preserve) 12526 xmlFreeDoc(ctxt->doc); 12527 if (ctxt->vctxt != NULL) { 12528 xmlSchemaFreeValidCtxt(ctxt->vctxt); 12529 } 12530 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) { 12531 xmlSchemaConstructionCtxtFree(ctxt->constructor); 12532 ctxt->constructor = NULL; 12533 ctxt->ownsConstructor = 0; 12534 } 12535 if (ctxt->attrProhibs != NULL) 12536 xmlSchemaItemListFree(ctxt->attrProhibs); 12537 xmlDictFree(ctxt->dict); 12538 xmlFree(ctxt); 12539} 12540 12541/************************************************************************ 12542 * * 12543 * Building the content models * 12544 * * 12545 ************************************************************************/ 12546 12547/** 12548 * xmlSchemaBuildContentModelForSubstGroup: 12549 * 12550 * Returns 1 if nillable, 0 otherwise 12551 */ 12552static int 12553xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt, 12554 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end) 12555{ 12556 xmlAutomataStatePtr start, tmp; 12557 xmlSchemaElementPtr elemDecl, member; 12558 xmlSchemaSubstGroupPtr substGroup; 12559 int i; 12560 int ret = 0; 12561 12562 elemDecl = (xmlSchemaElementPtr) particle->children; 12563 /* 12564 * Wrap the substitution group with a CHOICE. 12565 */ 12566 start = pctxt->state; 12567 if (end == NULL) 12568 end = xmlAutomataNewState(pctxt->am); 12569 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl); 12570 if (substGroup == NULL) { 12571 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle), 12572 XML_SCHEMAP_INTERNAL, 12573 "Internal error: xmlSchemaBuildContentModelForSubstGroup, " 12574 "declaration is marked having a subst. group but none " 12575 "available.\n", elemDecl->name, NULL); 12576 return(0); 12577 } 12578 if (counter >= 0) { 12579 /* 12580 * NOTE that we put the declaration in, even if it's abstract. 12581 * However, an error will be raised during *validation* if an element 12582 * information item shall be validated against an abstract element 12583 * declaration. 12584 */ 12585 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter); 12586 xmlAutomataNewTransition2(pctxt->am, tmp, end, 12587 elemDecl->name, elemDecl->targetNamespace, elemDecl); 12588 /* 12589 * Add subst. group members. 12590 */ 12591 for (i = 0; i < substGroup->members->nbItems; i++) { 12592 member = (xmlSchemaElementPtr) substGroup->members->items[i]; 12593 xmlAutomataNewTransition2(pctxt->am, tmp, end, 12594 member->name, member->targetNamespace, member); 12595 } 12596 } else if (particle->maxOccurs == 1) { 12597 /* 12598 * NOTE that we put the declaration in, even if it's abstract, 12599 */ 12600 xmlAutomataNewEpsilon(pctxt->am, 12601 xmlAutomataNewTransition2(pctxt->am, 12602 start, NULL, 12603 elemDecl->name, elemDecl->targetNamespace, elemDecl), end); 12604 /* 12605 * Add subst. group members. 12606 */ 12607 for (i = 0; i < substGroup->members->nbItems; i++) { 12608 member = (xmlSchemaElementPtr) substGroup->members->items[i]; 12609 /* 12610 * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2() 12611 * was incorrectly used instead of xmlAutomataNewTransition2() 12612 * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL 12613 * section in xmlSchemaBuildAContentModel() ). 12614 * TODO: Check if xmlAutomataNewOnceTrans2() was instead 12615 * intended for the above "counter" section originally. I.e., 12616 * check xs:all with subst-groups. 12617 * 12618 * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL, 12619 * member->name, member->targetNamespace, 12620 * 1, 1, member); 12621 */ 12622 tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL, 12623 member->name, member->targetNamespace, member); 12624 xmlAutomataNewEpsilon(pctxt->am, tmp, end); 12625 } 12626 } else { 12627 xmlAutomataStatePtr hop; 12628 int maxOccurs = particle->maxOccurs == UNBOUNDED ? 12629 UNBOUNDED : particle->maxOccurs - 1; 12630 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1; 12631 12632 counter = 12633 xmlAutomataNewCounter(pctxt->am, minOccurs, 12634 maxOccurs); 12635 hop = xmlAutomataNewState(pctxt->am); 12636 12637 xmlAutomataNewEpsilon(pctxt->am, 12638 xmlAutomataNewTransition2(pctxt->am, 12639 start, NULL, 12640 elemDecl->name, elemDecl->targetNamespace, elemDecl), 12641 hop); 12642 /* 12643 * Add subst. group members. 12644 */ 12645 for (i = 0; i < substGroup->members->nbItems; i++) { 12646 member = (xmlSchemaElementPtr) substGroup->members->items[i]; 12647 xmlAutomataNewEpsilon(pctxt->am, 12648 xmlAutomataNewTransition2(pctxt->am, 12649 start, NULL, 12650 member->name, member->targetNamespace, member), 12651 hop); 12652 } 12653 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter); 12654 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); 12655 } 12656 if (particle->minOccurs == 0) { 12657 xmlAutomataNewEpsilon(pctxt->am, start, end); 12658 ret = 1; 12659 } 12660 pctxt->state = end; 12661 return(ret); 12662} 12663 12664/** 12665 * xmlSchemaBuildContentModelForElement: 12666 * 12667 * Returns 1 if nillable, 0 otherwise 12668 */ 12669static int 12670xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt, 12671 xmlSchemaParticlePtr particle) 12672{ 12673 int ret = 0; 12674 12675 if (((xmlSchemaElementPtr) particle->children)->flags & 12676 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) { 12677 /* 12678 * Substitution groups. 12679 */ 12680 ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL); 12681 } else { 12682 xmlSchemaElementPtr elemDecl; 12683 xmlAutomataStatePtr start; 12684 12685 elemDecl = (xmlSchemaElementPtr) particle->children; 12686 12687 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) 12688 return(0); 12689 if (particle->maxOccurs == 1) { 12690 start = ctxt->state; 12691 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, 12692 elemDecl->name, elemDecl->targetNamespace, elemDecl); 12693 } else if ((particle->maxOccurs >= UNBOUNDED) && 12694 (particle->minOccurs < 2)) { 12695 /* Special case. */ 12696 start = ctxt->state; 12697 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, 12698 elemDecl->name, elemDecl->targetNamespace, elemDecl); 12699 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state, 12700 elemDecl->name, elemDecl->targetNamespace, elemDecl); 12701 } else { 12702 int counter; 12703 int maxOccurs = particle->maxOccurs == UNBOUNDED ? 12704 UNBOUNDED : particle->maxOccurs - 1; 12705 int minOccurs = particle->minOccurs < 1 ? 12706 0 : particle->minOccurs - 1; 12707 12708 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL); 12709 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs); 12710 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, 12711 elemDecl->name, elemDecl->targetNamespace, elemDecl); 12712 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter); 12713 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state, 12714 NULL, counter); 12715 } 12716 if (particle->minOccurs == 0) { 12717 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state); 12718 ret = 1; 12719 } 12720 } 12721 return(ret); 12722} 12723 12724/** 12725 * xmlSchemaBuildAContentModel: 12726 * @ctxt: the schema parser context 12727 * @particle: the particle component 12728 * @name: the complex type's name whose content is being built 12729 * 12730 * Create the automaton for the {content type} of a complex type. 12731 * 12732 * Returns 1 if the content is nillable, 0 otherwise 12733 */ 12734static int 12735xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt, 12736 xmlSchemaParticlePtr particle) 12737{ 12738 int ret = 0, tmp2; 12739 12740 if (particle == NULL) { 12741 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL"); 12742 return(1); 12743 } 12744 if (particle->children == NULL) { 12745 /* 12746 * Just return in this case. A missing "term" of the particle 12747 * might arise due to an invalid "term" component. 12748 */ 12749 return(1); 12750 } 12751 12752 switch (particle->children->type) { 12753 case XML_SCHEMA_TYPE_ANY: { 12754 xmlAutomataStatePtr start, end; 12755 xmlSchemaWildcardPtr wild; 12756 xmlSchemaWildcardNsPtr ns; 12757 12758 wild = (xmlSchemaWildcardPtr) particle->children; 12759 12760 start = pctxt->state; 12761 end = xmlAutomataNewState(pctxt->am); 12762 12763 if (particle->maxOccurs == 1) { 12764 if (wild->any == 1) { 12765 /* 12766 * We need to add both transitions: 12767 * 12768 * 1. the {"*", "*"} for elements in a namespace. 12769 */ 12770 pctxt->state = 12771 xmlAutomataNewTransition2(pctxt->am, 12772 start, NULL, BAD_CAST "*", BAD_CAST "*", wild); 12773 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); 12774 /* 12775 * 2. the {"*"} for elements in no namespace. 12776 */ 12777 pctxt->state = 12778 xmlAutomataNewTransition2(pctxt->am, 12779 start, NULL, BAD_CAST "*", NULL, wild); 12780 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); 12781 12782 } else if (wild->nsSet != NULL) { 12783 ns = wild->nsSet; 12784 do { 12785 pctxt->state = start; 12786 pctxt->state = xmlAutomataNewTransition2(pctxt->am, 12787 pctxt->state, NULL, BAD_CAST "*", ns->value, wild); 12788 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); 12789 ns = ns->next; 12790 } while (ns != NULL); 12791 12792 } else if (wild->negNsSet != NULL) { 12793 pctxt->state = xmlAutomataNewNegTrans(pctxt->am, 12794 start, end, BAD_CAST "*", wild->negNsSet->value, 12795 wild); 12796 } 12797 } else { 12798 int counter; 12799 xmlAutomataStatePtr hop; 12800 int maxOccurs = 12801 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : 12802 particle->maxOccurs - 1; 12803 int minOccurs = 12804 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1; 12805 12806 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs); 12807 hop = xmlAutomataNewState(pctxt->am); 12808 if (wild->any == 1) { 12809 pctxt->state = 12810 xmlAutomataNewTransition2(pctxt->am, 12811 start, NULL, BAD_CAST "*", BAD_CAST "*", wild); 12812 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); 12813 pctxt->state = 12814 xmlAutomataNewTransition2(pctxt->am, 12815 start, NULL, BAD_CAST "*", NULL, wild); 12816 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); 12817 } else if (wild->nsSet != NULL) { 12818 ns = wild->nsSet; 12819 do { 12820 pctxt->state = 12821 xmlAutomataNewTransition2(pctxt->am, 12822 start, NULL, BAD_CAST "*", ns->value, wild); 12823 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); 12824 ns = ns->next; 12825 } while (ns != NULL); 12826 12827 } else if (wild->negNsSet != NULL) { 12828 pctxt->state = xmlAutomataNewNegTrans(pctxt->am, 12829 start, hop, BAD_CAST "*", wild->negNsSet->value, 12830 wild); 12831 } 12832 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter); 12833 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); 12834 } 12835 if (particle->minOccurs == 0) { 12836 xmlAutomataNewEpsilon(pctxt->am, start, end); 12837 ret = 1; 12838 } 12839 pctxt->state = end; 12840 break; 12841 } 12842 case XML_SCHEMA_TYPE_ELEMENT: 12843 ret = xmlSchemaBuildContentModelForElement(pctxt, particle); 12844 break; 12845 case XML_SCHEMA_TYPE_SEQUENCE:{ 12846 xmlSchemaTreeItemPtr sub; 12847 12848 ret = 1; 12849 /* 12850 * If max and min occurances are default (1) then 12851 * simply iterate over the particles of the <sequence>. 12852 */ 12853 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) { 12854 sub = particle->children->children; 12855 12856 while (sub != NULL) { 12857 tmp2 = xmlSchemaBuildAContentModel(pctxt, 12858 (xmlSchemaParticlePtr) sub); 12859 if (tmp2 != 1) ret = 0; 12860 sub = sub->next; 12861 } 12862 } else { 12863 xmlAutomataStatePtr oldstate = pctxt->state; 12864 12865 if (particle->maxOccurs >= UNBOUNDED) { 12866 if (particle->minOccurs > 1) { 12867 xmlAutomataStatePtr tmp; 12868 int counter; 12869 12870 pctxt->state = xmlAutomataNewEpsilon(pctxt->am, 12871 oldstate, NULL); 12872 oldstate = pctxt->state; 12873 12874 counter = xmlAutomataNewCounter(pctxt->am, 12875 particle->minOccurs - 1, UNBOUNDED); 12876 12877 sub = particle->children->children; 12878 while (sub != NULL) { 12879 tmp2 = xmlSchemaBuildAContentModel(pctxt, 12880 (xmlSchemaParticlePtr) sub); 12881 if (tmp2 != 1) ret = 0; 12882 sub = sub->next; 12883 } 12884 tmp = pctxt->state; 12885 xmlAutomataNewCountedTrans(pctxt->am, tmp, 12886 oldstate, counter); 12887 pctxt->state = 12888 xmlAutomataNewCounterTrans(pctxt->am, tmp, 12889 NULL, counter); 12890 if (ret == 1) 12891 xmlAutomataNewEpsilon(pctxt->am, 12892 oldstate, pctxt->state); 12893 12894 } else { 12895 pctxt->state = xmlAutomataNewEpsilon(pctxt->am, 12896 oldstate, NULL); 12897 oldstate = pctxt->state; 12898 12899 sub = particle->children->children; 12900 while (sub != NULL) { 12901 tmp2 = xmlSchemaBuildAContentModel(pctxt, 12902 (xmlSchemaParticlePtr) sub); 12903 if (tmp2 != 1) ret = 0; 12904 sub = sub->next; 12905 } 12906 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, 12907 oldstate); 12908 /* 12909 * epsilon needed to block previous trans from 12910 * being allowed to enter back from another 12911 * construct 12912 */ 12913 pctxt->state = xmlAutomataNewEpsilon(pctxt->am, 12914 pctxt->state, NULL); 12915 if (particle->minOccurs == 0) { 12916 xmlAutomataNewEpsilon(pctxt->am, 12917 oldstate, pctxt->state); 12918 ret = 1; 12919 } 12920 } 12921 } else if ((particle->maxOccurs > 1) 12922 || (particle->minOccurs > 1)) { 12923 xmlAutomataStatePtr tmp; 12924 int counter; 12925 12926 pctxt->state = xmlAutomataNewEpsilon(pctxt->am, 12927 oldstate, NULL); 12928 oldstate = pctxt->state; 12929 12930 counter = xmlAutomataNewCounter(pctxt->am, 12931 particle->minOccurs - 1, 12932 particle->maxOccurs - 1); 12933 12934 sub = particle->children->children; 12935 while (sub != NULL) { 12936 tmp2 = xmlSchemaBuildAContentModel(pctxt, 12937 (xmlSchemaParticlePtr) sub); 12938 if (tmp2 != 1) ret = 0; 12939 sub = sub->next; 12940 } 12941 tmp = pctxt->state; 12942 xmlAutomataNewCountedTrans(pctxt->am, 12943 tmp, oldstate, counter); 12944 pctxt->state = 12945 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL, 12946 counter); 12947 if ((particle->minOccurs == 0) || (ret == 1)) { 12948 xmlAutomataNewEpsilon(pctxt->am, 12949 oldstate, pctxt->state); 12950 ret = 1; 12951 } 12952 } else { 12953 sub = particle->children->children; 12954 while (sub != NULL) { 12955 tmp2 = xmlSchemaBuildAContentModel(pctxt, 12956 (xmlSchemaParticlePtr) sub); 12957 if (tmp2 != 1) ret = 0; 12958 sub = sub->next; 12959 } 12960 12961 /* 12962 * epsilon needed to block previous trans from 12963 * being allowed to enter back from another 12964 * construct 12965 */ 12966 pctxt->state = xmlAutomataNewEpsilon(pctxt->am, 12967 pctxt->state, NULL); 12968 12969 if (particle->minOccurs == 0) { 12970 xmlAutomataNewEpsilon(pctxt->am, oldstate, 12971 pctxt->state); 12972 ret = 1; 12973 } 12974 } 12975 } 12976 break; 12977 } 12978 case XML_SCHEMA_TYPE_CHOICE:{ 12979 xmlSchemaTreeItemPtr sub; 12980 xmlAutomataStatePtr start, end; 12981 12982 ret = 0; 12983 start = pctxt->state; 12984 end = xmlAutomataNewState(pctxt->am); 12985 12986 /* 12987 * iterate over the subtypes and remerge the end with an 12988 * epsilon transition 12989 */ 12990 if (particle->maxOccurs == 1) { 12991 sub = particle->children->children; 12992 while (sub != NULL) { 12993 pctxt->state = start; 12994 tmp2 = xmlSchemaBuildAContentModel(pctxt, 12995 (xmlSchemaParticlePtr) sub); 12996 if (tmp2 == 1) ret = 1; 12997 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); 12998 sub = sub->next; 12999 } 13000 } else { 13001 int counter; 13002 xmlAutomataStatePtr hop, base; 13003 int maxOccurs = particle->maxOccurs == UNBOUNDED ? 13004 UNBOUNDED : particle->maxOccurs - 1; 13005 int minOccurs = 13006 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1; 13007 13008 /* 13009 * use a counter to keep track of the number of transtions 13010 * which went through the choice. 13011 */ 13012 counter = 13013 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs); 13014 hop = xmlAutomataNewState(pctxt->am); 13015 base = xmlAutomataNewState(pctxt->am); 13016 13017 sub = particle->children->children; 13018 while (sub != NULL) { 13019 pctxt->state = base; 13020 tmp2 = xmlSchemaBuildAContentModel(pctxt, 13021 (xmlSchemaParticlePtr) sub); 13022 if (tmp2 == 1) ret = 1; 13023 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); 13024 sub = sub->next; 13025 } 13026 xmlAutomataNewEpsilon(pctxt->am, start, base); 13027 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter); 13028 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); 13029 if (ret == 1) 13030 xmlAutomataNewEpsilon(pctxt->am, base, end); 13031 } 13032 if (particle->minOccurs == 0) { 13033 xmlAutomataNewEpsilon(pctxt->am, start, end); 13034 ret = 1; 13035 } 13036 pctxt->state = end; 13037 break; 13038 } 13039 case XML_SCHEMA_TYPE_ALL:{ 13040 xmlAutomataStatePtr start, tmp; 13041 xmlSchemaParticlePtr sub; 13042 xmlSchemaElementPtr elemDecl; 13043 13044 ret = 1; 13045 13046 sub = (xmlSchemaParticlePtr) particle->children->children; 13047 if (sub == NULL) 13048 break; 13049 13050 ret = 0; 13051 13052 start = pctxt->state; 13053 tmp = xmlAutomataNewState(pctxt->am); 13054 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp); 13055 pctxt->state = tmp; 13056 while (sub != NULL) { 13057 pctxt->state = tmp; 13058 13059 elemDecl = (xmlSchemaElementPtr) sub->children; 13060 if (elemDecl == NULL) { 13061 PERROR_INT("xmlSchemaBuildAContentModel", 13062 "<element> particle has no term"); 13063 return(ret); 13064 }; 13065 /* 13066 * NOTE: The {max occurs} of all the particles in the 13067 * {particles} of the group must be 0 or 1; this is 13068 * already ensured during the parse of the content of 13069 * <all>. 13070 */ 13071 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) { 13072 int counter; 13073 13074 /* 13075 * This is an abstract group, we need to share 13076 * the same counter for all the element transitions 13077 * derived from the group 13078 */ 13079 counter = xmlAutomataNewCounter(pctxt->am, 13080 sub->minOccurs, sub->maxOccurs); 13081 xmlSchemaBuildContentModelForSubstGroup(pctxt, 13082 sub, counter, pctxt->state); 13083 } else { 13084 if ((sub->minOccurs == 1) && 13085 (sub->maxOccurs == 1)) { 13086 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state, 13087 pctxt->state, 13088 elemDecl->name, 13089 elemDecl->targetNamespace, 13090 1, 1, elemDecl); 13091 } else if ((sub->minOccurs == 0) && 13092 (sub->maxOccurs == 1)) { 13093 13094 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state, 13095 pctxt->state, 13096 elemDecl->name, 13097 elemDecl->targetNamespace, 13098 0, 13099 1, 13100 elemDecl); 13101 } 13102 } 13103 sub = (xmlSchemaParticlePtr) sub->next; 13104 } 13105 pctxt->state = 13106 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0); 13107 if (particle->minOccurs == 0) { 13108 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state); 13109 ret = 1; 13110 } 13111 break; 13112 } 13113 case XML_SCHEMA_TYPE_GROUP: 13114 /* 13115 * If we hit a model group definition, then this means that 13116 * it was empty, thus was not substituted for the containing 13117 * model group. Just do nothing in this case. 13118 * TODO: But the group should be substituted and not occur at 13119 * all in the content model at this point. Fix this. 13120 */ 13121 ret = 1; 13122 break; 13123 default: 13124 xmlSchemaInternalErr2(ACTXT_CAST pctxt, 13125 "xmlSchemaBuildAContentModel", 13126 "found unexpected term of type '%s' in content model", 13127 WXS_ITEM_TYPE_NAME(particle->children), NULL); 13128 return(ret); 13129 } 13130 return(ret); 13131} 13132 13133/** 13134 * xmlSchemaBuildContentModel: 13135 * @ctxt: the schema parser context 13136 * @type: the complex type definition 13137 * @name: the element name 13138 * 13139 * Builds the content model of the complex type. 13140 */ 13141static void 13142xmlSchemaBuildContentModel(xmlSchemaTypePtr type, 13143 xmlSchemaParserCtxtPtr ctxt) 13144{ 13145 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || 13146 (type->contModel != NULL) || 13147 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) && 13148 (type->contentType != XML_SCHEMA_CONTENT_MIXED))) 13149 return; 13150 13151#ifdef DEBUG_CONTENT 13152 xmlGenericError(xmlGenericErrorContext, 13153 "Building content model for %s\n", name); 13154#endif 13155 ctxt->am = NULL; 13156 ctxt->am = xmlNewAutomata(); 13157 if (ctxt->am == NULL) { 13158 xmlGenericError(xmlGenericErrorContext, 13159 "Cannot create automata for complex type %s\n", type->name); 13160 return; 13161 } 13162 ctxt->state = xmlAutomataGetInitState(ctxt->am); 13163 /* 13164 * Build the automaton. 13165 */ 13166 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type)); 13167 xmlAutomataSetFinalState(ctxt->am, ctxt->state); 13168 type->contModel = xmlAutomataCompile(ctxt->am); 13169 if (type->contModel == NULL) { 13170 xmlSchemaPCustomErr(ctxt, 13171 XML_SCHEMAP_INTERNAL, 13172 WXS_BASIC_CAST type, type->node, 13173 "Failed to compile the content model", NULL); 13174 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) { 13175 xmlSchemaPCustomErr(ctxt, 13176 XML_SCHEMAP_NOT_DETERMINISTIC, 13177 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */ 13178 WXS_BASIC_CAST type, type->node, 13179 "The content model is not determinist", NULL); 13180 } else { 13181#ifdef DEBUG_CONTENT_REGEXP 13182 xmlGenericError(xmlGenericErrorContext, 13183 "Content model of %s:\n", type->name); 13184 xmlRegexpPrint(stderr, type->contModel); 13185#endif 13186 } 13187 ctxt->state = NULL; 13188 xmlFreeAutomata(ctxt->am); 13189 ctxt->am = NULL; 13190} 13191 13192/** 13193 * xmlSchemaResolveElementReferences: 13194 * @elem: the schema element context 13195 * @ctxt: the schema parser context 13196 * 13197 * Resolves the references of an element declaration 13198 * or particle, which has an element declaration as it's 13199 * term. 13200 */ 13201static void 13202xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl, 13203 xmlSchemaParserCtxtPtr ctxt) 13204{ 13205 if ((ctxt == NULL) || (elemDecl == NULL) || 13206 ((elemDecl != NULL) && 13207 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED))) 13208 return; 13209 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED; 13210 13211 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) { 13212 xmlSchemaTypePtr type; 13213 13214 /* (type definition) ... otherwise the type definition �resolved� 13215 * to by the �actual value� of the type [attribute] ... 13216 */ 13217 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType, 13218 elemDecl->namedTypeNs); 13219 if (type == NULL) { 13220 xmlSchemaPResCompAttrErr(ctxt, 13221 XML_SCHEMAP_SRC_RESOLVE, 13222 WXS_BASIC_CAST elemDecl, elemDecl->node, 13223 "type", elemDecl->namedType, elemDecl->namedTypeNs, 13224 XML_SCHEMA_TYPE_BASIC, "type definition"); 13225 } else 13226 elemDecl->subtypes = type; 13227 } 13228 if (elemDecl->substGroup != NULL) { 13229 xmlSchemaElementPtr substHead; 13230 13231 /* 13232 * FIXME TODO: Do we need a new field in _xmlSchemaElement for 13233 * substitutionGroup? 13234 */ 13235 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup, 13236 elemDecl->substGroupNs); 13237 if (substHead == NULL) { 13238 xmlSchemaPResCompAttrErr(ctxt, 13239 XML_SCHEMAP_SRC_RESOLVE, 13240 WXS_BASIC_CAST elemDecl, NULL, 13241 "substitutionGroup", elemDecl->substGroup, 13242 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL); 13243 } else { 13244 xmlSchemaResolveElementReferences(substHead, ctxt); 13245 /* 13246 * Set the "substitution group affiliation". 13247 * NOTE that now we use the "refDecl" field for this. 13248 */ 13249 WXS_SUBST_HEAD(elemDecl) = substHead; 13250 /* 13251 * The type definitions is set to: 13252 * SPEC "...the {type definition} of the element 13253 * declaration �resolved� to by the �actual value� 13254 * of the substitutionGroup [attribute], if present" 13255 */ 13256 if (elemDecl->subtypes == NULL) 13257 elemDecl->subtypes = substHead->subtypes; 13258 } 13259 } 13260 /* 13261 * SPEC "The definition of anyType serves as the default type definition 13262 * for element declarations whose XML representation does not specify one." 13263 */ 13264 if ((elemDecl->subtypes == NULL) && 13265 (elemDecl->namedType == NULL) && 13266 (elemDecl->substGroup == NULL)) 13267 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); 13268} 13269 13270/** 13271 * xmlSchemaResolveUnionMemberTypes: 13272 * @ctxt: the schema parser context 13273 * @type: the schema simple type definition 13274 * 13275 * Checks and builds the "member type definitions" property of the union 13276 * simple type. This handles part (1), part (2) is done in 13277 * xmlSchemaFinishMemberTypeDefinitionsProperty() 13278 * 13279 * Returns -1 in case of an internal error, 0 otherwise. 13280 */ 13281static int 13282xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt, 13283 xmlSchemaTypePtr type) 13284{ 13285 13286 xmlSchemaTypeLinkPtr link, lastLink, newLink; 13287 xmlSchemaTypePtr memberType; 13288 13289 /* 13290 * SPEC (1) "If the <union> alternative is chosen, then [Definition:] 13291 * define the explicit members as the type definitions �resolved� 13292 * to by the items in the �actual value� of the memberTypes [attribute], 13293 * if any, followed by the type definitions corresponding to the 13294 * <simpleType>s among the [children] of <union>, if any." 13295 */ 13296 /* 13297 * Resolve references. 13298 */ 13299 link = type->memberTypes; 13300 lastLink = NULL; 13301 while (link != NULL) { 13302 const xmlChar *name, *nsName; 13303 13304 name = ((xmlSchemaQNameRefPtr) link->type)->name; 13305 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace; 13306 13307 memberType = xmlSchemaGetType(ctxt->schema, name, nsName); 13308 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) { 13309 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE, 13310 WXS_BASIC_CAST type, type->node, "memberTypes", 13311 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL); 13312 /* 13313 * Remove the member type link. 13314 */ 13315 if (lastLink == NULL) 13316 type->memberTypes = link->next; 13317 else 13318 lastLink->next = link->next; 13319 newLink = link; 13320 link = link->next; 13321 xmlFree(newLink); 13322 } else { 13323 link->type = memberType; 13324 lastLink = link; 13325 link = link->next; 13326 } 13327 } 13328 /* 13329 * Add local simple types, 13330 */ 13331 memberType = type->subtypes; 13332 while (memberType != NULL) { 13333 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink)); 13334 if (link == NULL) { 13335 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL); 13336 return (-1); 13337 } 13338 link->type = memberType; 13339 link->next = NULL; 13340 if (lastLink == NULL) 13341 type->memberTypes = link; 13342 else 13343 lastLink->next = link; 13344 lastLink = link; 13345 memberType = memberType->next; 13346 } 13347 return (0); 13348} 13349 13350/** 13351 * xmlSchemaIsDerivedFromBuiltInType: 13352 * @ctxt: the schema parser context 13353 * @type: the type definition 13354 * @valType: the value type 13355 * 13356 * 13357 * Returns 1 if the type has the given value type, or 13358 * is derived from such a type. 13359 */ 13360static int 13361xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType) 13362{ 13363 if (type == NULL) 13364 return (0); 13365 if (WXS_IS_COMPLEX(type)) 13366 return (0); 13367 if (type->type == XML_SCHEMA_TYPE_BASIC) { 13368 if (type->builtInType == valType) 13369 return(1); 13370 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) || 13371 (type->builtInType == XML_SCHEMAS_ANYTYPE)) 13372 return (0); 13373 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType)); 13374 } 13375 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType)); 13376} 13377 13378#if 0 13379/** 13380 * xmlSchemaIsDerivedFromBuiltInType: 13381 * @ctxt: the schema parser context 13382 * @type: the type definition 13383 * @valType: the value type 13384 * 13385 * 13386 * Returns 1 if the type has the given value type, or 13387 * is derived from such a type. 13388 */ 13389static int 13390xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType) 13391{ 13392 if (type == NULL) 13393 return (0); 13394 if (WXS_IS_COMPLEX(type)) 13395 return (0); 13396 if (type->type == XML_SCHEMA_TYPE_BASIC) { 13397 if (type->builtInType == valType) 13398 return(1); 13399 return (0); 13400 } else 13401 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType)); 13402 13403 return (0); 13404} 13405 13406static xmlSchemaTypePtr 13407xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type) 13408{ 13409 if (type == NULL) 13410 return (NULL); 13411 if (WXS_IS_COMPLEX(type)) 13412 return (NULL); 13413 if (type->type == XML_SCHEMA_TYPE_BASIC) 13414 return(type); 13415 return(xmlSchemaQueryBuiltInType(type->subtypes)); 13416} 13417#endif 13418 13419/** 13420 * xmlSchemaGetPrimitiveType: 13421 * @type: the simpleType definition 13422 * 13423 * Returns the primitive type of the given type or 13424 * NULL in case of error. 13425 */ 13426static xmlSchemaTypePtr 13427xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type) 13428{ 13429 13430 while (type != NULL) { 13431 /* 13432 * Note that anySimpleType is actually not a primitive type 13433 * but we need that here. 13434 */ 13435 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) || 13436 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)) 13437 return (type); 13438 type = type->baseType; 13439 } 13440 13441 return (NULL); 13442} 13443 13444#if 0 13445/** 13446 * xmlSchemaGetBuiltInTypeAncestor: 13447 * @type: the simpleType definition 13448 * 13449 * Returns the primitive type of the given type or 13450 * NULL in case of error. 13451 */ 13452static xmlSchemaTypePtr 13453xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type) 13454{ 13455 if (WXS_IS_LIST(type) || WXS_IS_UNION(type)) 13456 return (0); 13457 while (type != NULL) { 13458 if (type->type == XML_SCHEMA_TYPE_BASIC) 13459 return (type); 13460 type = type->baseType; 13461 } 13462 13463 return (NULL); 13464} 13465#endif 13466 13467/** 13468 * xmlSchemaCloneWildcardNsConstraints: 13469 * @ctxt: the schema parser context 13470 * @dest: the destination wildcard 13471 * @source: the source wildcard 13472 * 13473 * Clones the namespace constraints of source 13474 * and assignes them to dest. 13475 * Returns -1 on internal error, 0 otherwise. 13476 */ 13477static int 13478xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt, 13479 xmlSchemaWildcardPtr dest, 13480 xmlSchemaWildcardPtr source) 13481{ 13482 xmlSchemaWildcardNsPtr cur, tmp, last; 13483 13484 if ((source == NULL) || (dest == NULL)) 13485 return(-1); 13486 dest->any = source->any; 13487 cur = source->nsSet; 13488 last = NULL; 13489 while (cur != NULL) { 13490 tmp = xmlSchemaNewWildcardNsConstraint(ctxt); 13491 if (tmp == NULL) 13492 return(-1); 13493 tmp->value = cur->value; 13494 if (last == NULL) 13495 dest->nsSet = tmp; 13496 else 13497 last->next = tmp; 13498 last = tmp; 13499 cur = cur->next; 13500 } 13501 if (dest->negNsSet != NULL) 13502 xmlSchemaFreeWildcardNsSet(dest->negNsSet); 13503 if (source->negNsSet != NULL) { 13504 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); 13505 if (dest->negNsSet == NULL) 13506 return(-1); 13507 dest->negNsSet->value = source->negNsSet->value; 13508 } else 13509 dest->negNsSet = NULL; 13510 return(0); 13511} 13512 13513/** 13514 * xmlSchemaUnionWildcards: 13515 * @ctxt: the schema parser context 13516 * @completeWild: the first wildcard 13517 * @curWild: the second wildcard 13518 * 13519 * Unions the namespace constraints of the given wildcards. 13520 * @completeWild will hold the resulting union. 13521 * Returns a positive error code on failure, -1 in case of an 13522 * internal error, 0 otherwise. 13523 */ 13524static int 13525xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt, 13526 xmlSchemaWildcardPtr completeWild, 13527 xmlSchemaWildcardPtr curWild) 13528{ 13529 xmlSchemaWildcardNsPtr cur, curB, tmp; 13530 13531 /* 13532 * 1 If O1 and O2 are the same value, then that value must be the 13533 * value. 13534 */ 13535 if ((completeWild->any == curWild->any) && 13536 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) && 13537 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) { 13538 13539 if ((completeWild->negNsSet == NULL) || 13540 (completeWild->negNsSet->value == curWild->negNsSet->value)) { 13541 13542 if (completeWild->nsSet != NULL) { 13543 int found = 0; 13544 13545 /* 13546 * Check equality of sets. 13547 */ 13548 cur = completeWild->nsSet; 13549 while (cur != NULL) { 13550 found = 0; 13551 curB = curWild->nsSet; 13552 while (curB != NULL) { 13553 if (cur->value == curB->value) { 13554 found = 1; 13555 break; 13556 } 13557 curB = curB->next; 13558 } 13559 if (!found) 13560 break; 13561 cur = cur->next; 13562 } 13563 if (found) 13564 return(0); 13565 } else 13566 return(0); 13567 } 13568 } 13569 /* 13570 * 2 If either O1 or O2 is any, then any must be the value 13571 */ 13572 if (completeWild->any != curWild->any) { 13573 if (completeWild->any == 0) { 13574 completeWild->any = 1; 13575 if (completeWild->nsSet != NULL) { 13576 xmlSchemaFreeWildcardNsSet(completeWild->nsSet); 13577 completeWild->nsSet = NULL; 13578 } 13579 if (completeWild->negNsSet != NULL) { 13580 xmlFree(completeWild->negNsSet); 13581 completeWild->negNsSet = NULL; 13582 } 13583 } 13584 return (0); 13585 } 13586 /* 13587 * 3 If both O1 and O2 are sets of (namespace names or �absent�), 13588 * then the union of those sets must be the value. 13589 */ 13590 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) { 13591 int found; 13592 xmlSchemaWildcardNsPtr start; 13593 13594 cur = curWild->nsSet; 13595 start = completeWild->nsSet; 13596 while (cur != NULL) { 13597 found = 0; 13598 curB = start; 13599 while (curB != NULL) { 13600 if (cur->value == curB->value) { 13601 found = 1; 13602 break; 13603 } 13604 curB = curB->next; 13605 } 13606 if (!found) { 13607 tmp = xmlSchemaNewWildcardNsConstraint(ctxt); 13608 if (tmp == NULL) 13609 return (-1); 13610 tmp->value = cur->value; 13611 tmp->next = completeWild->nsSet; 13612 completeWild->nsSet = tmp; 13613 } 13614 cur = cur->next; 13615 } 13616 13617 return(0); 13618 } 13619 /* 13620 * 4 If the two are negations of different values (namespace names 13621 * or �absent�), then a pair of not and �absent� must be the value. 13622 */ 13623 if ((completeWild->negNsSet != NULL) && 13624 (curWild->negNsSet != NULL) && 13625 (completeWild->negNsSet->value != curWild->negNsSet->value)) { 13626 completeWild->negNsSet->value = NULL; 13627 13628 return(0); 13629 } 13630 /* 13631 * 5. 13632 */ 13633 if (((completeWild->negNsSet != NULL) && 13634 (completeWild->negNsSet->value != NULL) && 13635 (curWild->nsSet != NULL)) || 13636 ((curWild->negNsSet != NULL) && 13637 (curWild->negNsSet->value != NULL) && 13638 (completeWild->nsSet != NULL))) { 13639 13640 int nsFound, absentFound = 0; 13641 13642 if (completeWild->nsSet != NULL) { 13643 cur = completeWild->nsSet; 13644 curB = curWild->negNsSet; 13645 } else { 13646 cur = curWild->nsSet; 13647 curB = completeWild->negNsSet; 13648 } 13649 nsFound = 0; 13650 while (cur != NULL) { 13651 if (cur->value == NULL) 13652 absentFound = 1; 13653 else if (cur->value == curB->value) 13654 nsFound = 1; 13655 if (nsFound && absentFound) 13656 break; 13657 cur = cur->next; 13658 } 13659 13660 if (nsFound && absentFound) { 13661 /* 13662 * 5.1 If the set S includes both the negated namespace 13663 * name and �absent�, then any must be the value. 13664 */ 13665 completeWild->any = 1; 13666 if (completeWild->nsSet != NULL) { 13667 xmlSchemaFreeWildcardNsSet(completeWild->nsSet); 13668 completeWild->nsSet = NULL; 13669 } 13670 if (completeWild->negNsSet != NULL) { 13671 xmlFree(completeWild->negNsSet); 13672 completeWild->negNsSet = NULL; 13673 } 13674 } else if (nsFound && (!absentFound)) { 13675 /* 13676 * 5.2 If the set S includes the negated namespace name 13677 * but not �absent�, then a pair of not and �absent� must 13678 * be the value. 13679 */ 13680 if (completeWild->nsSet != NULL) { 13681 xmlSchemaFreeWildcardNsSet(completeWild->nsSet); 13682 completeWild->nsSet = NULL; 13683 } 13684 if (completeWild->negNsSet == NULL) { 13685 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); 13686 if (completeWild->negNsSet == NULL) 13687 return (-1); 13688 } 13689 completeWild->negNsSet->value = NULL; 13690 } else if ((!nsFound) && absentFound) { 13691 /* 13692 * 5.3 If the set S includes �absent� but not the negated 13693 * namespace name, then the union is not expressible. 13694 */ 13695 xmlSchemaPErr(ctxt, completeWild->node, 13696 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE, 13697 "The union of the wilcard is not expressible.\n", 13698 NULL, NULL); 13699 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE); 13700 } else if ((!nsFound) && (!absentFound)) { 13701 /* 13702 * 5.4 If the set S does not include either the negated namespace 13703 * name or �absent�, then whichever of O1 or O2 is a pair of not 13704 * and a namespace name must be the value. 13705 */ 13706 if (completeWild->negNsSet == NULL) { 13707 if (completeWild->nsSet != NULL) { 13708 xmlSchemaFreeWildcardNsSet(completeWild->nsSet); 13709 completeWild->nsSet = NULL; 13710 } 13711 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); 13712 if (completeWild->negNsSet == NULL) 13713 return (-1); 13714 completeWild->negNsSet->value = curWild->negNsSet->value; 13715 } 13716 } 13717 return (0); 13718 } 13719 /* 13720 * 6. 13721 */ 13722 if (((completeWild->negNsSet != NULL) && 13723 (completeWild->negNsSet->value == NULL) && 13724 (curWild->nsSet != NULL)) || 13725 ((curWild->negNsSet != NULL) && 13726 (curWild->negNsSet->value == NULL) && 13727 (completeWild->nsSet != NULL))) { 13728 13729 if (completeWild->nsSet != NULL) { 13730 cur = completeWild->nsSet; 13731 } else { 13732 cur = curWild->nsSet; 13733 } 13734 while (cur != NULL) { 13735 if (cur->value == NULL) { 13736 /* 13737 * 6.1 If the set S includes �absent�, then any must be the 13738 * value. 13739 */ 13740 completeWild->any = 1; 13741 if (completeWild->nsSet != NULL) { 13742 xmlSchemaFreeWildcardNsSet(completeWild->nsSet); 13743 completeWild->nsSet = NULL; 13744 } 13745 if (completeWild->negNsSet != NULL) { 13746 xmlFree(completeWild->negNsSet); 13747 completeWild->negNsSet = NULL; 13748 } 13749 return (0); 13750 } 13751 cur = cur->next; 13752 } 13753 if (completeWild->negNsSet == NULL) { 13754 /* 13755 * 6.2 If the set S does not include �absent�, then a pair of not 13756 * and �absent� must be the value. 13757 */ 13758 if (completeWild->nsSet != NULL) { 13759 xmlSchemaFreeWildcardNsSet(completeWild->nsSet); 13760 completeWild->nsSet = NULL; 13761 } 13762 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); 13763 if (completeWild->negNsSet == NULL) 13764 return (-1); 13765 completeWild->negNsSet->value = NULL; 13766 } 13767 return (0); 13768 } 13769 return (0); 13770 13771} 13772 13773/** 13774 * xmlSchemaIntersectWildcards: 13775 * @ctxt: the schema parser context 13776 * @completeWild: the first wildcard 13777 * @curWild: the second wildcard 13778 * 13779 * Intersects the namespace constraints of the given wildcards. 13780 * @completeWild will hold the resulting intersection. 13781 * Returns a positive error code on failure, -1 in case of an 13782 * internal error, 0 otherwise. 13783 */ 13784static int 13785xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt, 13786 xmlSchemaWildcardPtr completeWild, 13787 xmlSchemaWildcardPtr curWild) 13788{ 13789 xmlSchemaWildcardNsPtr cur, curB, prev, tmp; 13790 13791 /* 13792 * 1 If O1 and O2 are the same value, then that value must be the 13793 * value. 13794 */ 13795 if ((completeWild->any == curWild->any) && 13796 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) && 13797 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) { 13798 13799 if ((completeWild->negNsSet == NULL) || 13800 (completeWild->negNsSet->value == curWild->negNsSet->value)) { 13801 13802 if (completeWild->nsSet != NULL) { 13803 int found = 0; 13804 13805 /* 13806 * Check equality of sets. 13807 */ 13808 cur = completeWild->nsSet; 13809 while (cur != NULL) { 13810 found = 0; 13811 curB = curWild->nsSet; 13812 while (curB != NULL) { 13813 if (cur->value == curB->value) { 13814 found = 1; 13815 break; 13816 } 13817 curB = curB->next; 13818 } 13819 if (!found) 13820 break; 13821 cur = cur->next; 13822 } 13823 if (found) 13824 return(0); 13825 } else 13826 return(0); 13827 } 13828 } 13829 /* 13830 * 2 If either O1 or O2 is any, then the other must be the value. 13831 */ 13832 if ((completeWild->any != curWild->any) && (completeWild->any)) { 13833 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1) 13834 return(-1); 13835 return(0); 13836 } 13837 /* 13838 * 3 If either O1 or O2 is a pair of not and a value (a namespace 13839 * name or �absent�) and the other is a set of (namespace names or 13840 * �absent�), then that set, minus the negated value if it was in 13841 * the set, minus �absent� if it was in the set, must be the value. 13842 */ 13843 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) || 13844 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) { 13845 const xmlChar *neg; 13846 13847 if (completeWild->nsSet == NULL) { 13848 neg = completeWild->negNsSet->value; 13849 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1) 13850 return(-1); 13851 } else 13852 neg = curWild->negNsSet->value; 13853 /* 13854 * Remove absent and negated. 13855 */ 13856 prev = NULL; 13857 cur = completeWild->nsSet; 13858 while (cur != NULL) { 13859 if (cur->value == NULL) { 13860 if (prev == NULL) 13861 completeWild->nsSet = cur->next; 13862 else 13863 prev->next = cur->next; 13864 xmlFree(cur); 13865 break; 13866 } 13867 prev = cur; 13868 cur = cur->next; 13869 } 13870 if (neg != NULL) { 13871 prev = NULL; 13872 cur = completeWild->nsSet; 13873 while (cur != NULL) { 13874 if (cur->value == neg) { 13875 if (prev == NULL) 13876 completeWild->nsSet = cur->next; 13877 else 13878 prev->next = cur->next; 13879 xmlFree(cur); 13880 break; 13881 } 13882 prev = cur; 13883 cur = cur->next; 13884 } 13885 } 13886 13887 return(0); 13888 } 13889 /* 13890 * 4 If both O1 and O2 are sets of (namespace names or �absent�), 13891 * then the intersection of those sets must be the value. 13892 */ 13893 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) { 13894 int found; 13895 13896 cur = completeWild->nsSet; 13897 prev = NULL; 13898 while (cur != NULL) { 13899 found = 0; 13900 curB = curWild->nsSet; 13901 while (curB != NULL) { 13902 if (cur->value == curB->value) { 13903 found = 1; 13904 break; 13905 } 13906 curB = curB->next; 13907 } 13908 if (!found) { 13909 if (prev == NULL) 13910 completeWild->nsSet = cur->next; 13911 else 13912 prev->next = cur->next; 13913 tmp = cur->next; 13914 xmlFree(cur); 13915 cur = tmp; 13916 continue; 13917 } 13918 prev = cur; 13919 cur = cur->next; 13920 } 13921 13922 return(0); 13923 } 13924 /* 5 If the two are negations of different namespace names, 13925 * then the intersection is not expressible 13926 */ 13927 if ((completeWild->negNsSet != NULL) && 13928 (curWild->negNsSet != NULL) && 13929 (completeWild->negNsSet->value != curWild->negNsSet->value) && 13930 (completeWild->negNsSet->value != NULL) && 13931 (curWild->negNsSet->value != NULL)) { 13932 13933 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE, 13934 "The intersection of the wilcard is not expressible.\n", 13935 NULL, NULL); 13936 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE); 13937 } 13938 /* 13939 * 6 If the one is a negation of a namespace name and the other 13940 * is a negation of �absent�, then the one which is the negation 13941 * of a namespace name must be the value. 13942 */ 13943 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) && 13944 (completeWild->negNsSet->value != curWild->negNsSet->value) && 13945 (completeWild->negNsSet->value == NULL)) { 13946 completeWild->negNsSet->value = curWild->negNsSet->value; 13947 } 13948 return(0); 13949} 13950 13951/** 13952 * xmlSchemaIsWildcardNsConstraintSubset: 13953 * @ctxt: the schema parser context 13954 * @sub: the first wildcard 13955 * @super: the second wildcard 13956 * 13957 * Schema Component Constraint: Wildcard Subset (cos-ns-subset) 13958 * 13959 * Returns 0 if the namespace constraint of @sub is an intensional 13960 * subset of @super, 1 otherwise. 13961 */ 13962static int 13963xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub, 13964 xmlSchemaWildcardPtr super) 13965{ 13966 /* 13967 * 1 super must be any. 13968 */ 13969 if (super->any) 13970 return (0); 13971 /* 13972 * 2.1 sub must be a pair of not and a namespace name or �absent�. 13973 * 2.2 super must be a pair of not and the same value. 13974 */ 13975 if ((sub->negNsSet != NULL) && 13976 (super->negNsSet != NULL) && 13977 (sub->negNsSet->value == super->negNsSet->value)) 13978 return (0); 13979 /* 13980 * 3.1 sub must be a set whose members are either namespace names or �absent�. 13981 */ 13982 if (sub->nsSet != NULL) { 13983 /* 13984 * 3.2.1 super must be the same set or a superset thereof. 13985 */ 13986 if (super->nsSet != NULL) { 13987 xmlSchemaWildcardNsPtr cur, curB; 13988 int found = 0; 13989 13990 cur = sub->nsSet; 13991 while (cur != NULL) { 13992 found = 0; 13993 curB = super->nsSet; 13994 while (curB != NULL) { 13995 if (cur->value == curB->value) { 13996 found = 1; 13997 break; 13998 } 13999 curB = curB->next; 14000 } 14001 if (!found) 14002 return (1); 14003 cur = cur->next; 14004 } 14005 if (found) 14006 return (0); 14007 } else if (super->negNsSet != NULL) { 14008 xmlSchemaWildcardNsPtr cur; 14009 /* 14010 * 3.2.2 super must be a pair of not and a namespace name or 14011 * �absent� and that value must not be in sub's set. 14012 */ 14013 cur = sub->nsSet; 14014 while (cur != NULL) { 14015 if (cur->value == super->negNsSet->value) 14016 return (1); 14017 cur = cur->next; 14018 } 14019 return (0); 14020 } 14021 } 14022 return (1); 14023} 14024 14025static int 14026xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse, 14027 int *fixed, 14028 const xmlChar **value, 14029 xmlSchemaValPtr *val) 14030{ 14031 *fixed = 0; 14032 *value = NULL; 14033 if (val != 0) 14034 *val = NULL; 14035 14036 if (attruse->defValue != NULL) { 14037 *value = attruse->defValue; 14038 if (val != NULL) 14039 *val = attruse->defVal; 14040 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED) 14041 *fixed = 1; 14042 return(1); 14043 } else if ((attruse->attrDecl != NULL) && 14044 (attruse->attrDecl->defValue != NULL)) { 14045 *value = attruse->attrDecl->defValue; 14046 if (val != NULL) 14047 *val = attruse->attrDecl->defVal; 14048 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED) 14049 *fixed = 1; 14050 return(1); 14051 } 14052 return(0); 14053} 14054/** 14055 * xmlSchemaCheckCVCWildcardNamespace: 14056 * @wild: the wildcard 14057 * @ns: the namespace 14058 * 14059 * Validation Rule: Wildcard allows Namespace Name 14060 * (cvc-wildcard-namespace) 14061 * 14062 * Returns 0 if the given namespace matches the wildcard, 14063 * 1 otherwise and -1 on API errors. 14064 */ 14065static int 14066xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild, 14067 const xmlChar* ns) 14068{ 14069 if (wild == NULL) 14070 return(-1); 14071 14072 if (wild->any) 14073 return(0); 14074 else if (wild->nsSet != NULL) { 14075 xmlSchemaWildcardNsPtr cur; 14076 14077 cur = wild->nsSet; 14078 while (cur != NULL) { 14079 if (xmlStrEqual(cur->value, ns)) 14080 return(0); 14081 cur = cur->next; 14082 } 14083 } else if ((wild->negNsSet != NULL) && (ns != NULL) && 14084 (!xmlStrEqual(wild->negNsSet->value, ns))) 14085 return(0); 14086 14087 return(1); 14088} 14089 14090#define XML_SCHEMA_ACTION_DERIVE 0 14091#define XML_SCHEMA_ACTION_REDEFINE 1 14092 14093#define WXS_ACTION_STR(a) \ 14094((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined" 14095 14096/* 14097* Schema Component Constraint: 14098* Derivation Valid (Restriction, Complex) 14099* derivation-ok-restriction (2) - (4) 14100* 14101* ATTENTION: 14102* In XML Schema 1.1 this will be: 14103* Validation Rule: 14104* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3) 14105* 14106*/ 14107static int 14108xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt, 14109 int action, 14110 xmlSchemaBasicItemPtr item, 14111 xmlSchemaBasicItemPtr baseItem, 14112 xmlSchemaItemListPtr uses, 14113 xmlSchemaItemListPtr baseUses, 14114 xmlSchemaWildcardPtr wild, 14115 xmlSchemaWildcardPtr baseWild) 14116{ 14117 xmlSchemaAttributeUsePtr cur = NULL, bcur; 14118 int i, j, found; /* err = 0; */ 14119 const xmlChar *bEffValue; 14120 int effFixed; 14121 14122 if (uses != NULL) { 14123 for (i = 0; i < uses->nbItems; i++) { 14124 cur = uses->items[i]; 14125 found = 0; 14126 if (baseUses == NULL) 14127 goto not_found; 14128 for (j = 0; j < baseUses->nbItems; j++) { 14129 bcur = baseUses->items[j]; 14130 if ((WXS_ATTRUSE_DECL_NAME(cur) == 14131 WXS_ATTRUSE_DECL_NAME(bcur)) && 14132 (WXS_ATTRUSE_DECL_TNS(cur) == 14133 WXS_ATTRUSE_DECL_TNS(bcur))) 14134 { 14135 /* 14136 * (2.1) "If there is an attribute use in the {attribute 14137 * uses} of the {base type definition} (call this B) whose 14138 * {attribute declaration} has the same {name} and {target 14139 * namespace}, then all of the following must be true:" 14140 */ 14141 found = 1; 14142 14143 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) && 14144 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) 14145 { 14146 xmlChar *str = NULL; 14147 /* 14148 * (2.1.1) "one of the following must be true:" 14149 * (2.1.1.1) "B's {required} is false." 14150 * (2.1.1.2) "R's {required} is true." 14151 */ 14152 xmlSchemaPAttrUseErr4(pctxt, 14153 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1, 14154 WXS_ITEM_NODE(item), item, cur, 14155 "The 'optional' attribute use is inconsistent " 14156 "with the corresponding 'required' attribute use of " 14157 "the %s %s", 14158 WXS_ACTION_STR(action), 14159 xmlSchemaGetComponentDesignation(&str, baseItem), 14160 NULL, NULL); 14161 FREE_AND_NULL(str); 14162 /* err = pctxt->err; */ 14163 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, 14164 WXS_ATTRUSE_TYPEDEF(cur), 14165 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0) 14166 { 14167 xmlChar *strA = NULL, *strB = NULL, *strC = NULL; 14168 14169 /* 14170 * SPEC (2.1.2) "R's {attribute declaration}'s 14171 * {type definition} must be validly derived from 14172 * B's {type definition} given the empty set as 14173 * defined in Type Derivation OK (Simple) (�3.14.6)." 14174 */ 14175 xmlSchemaPAttrUseErr4(pctxt, 14176 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2, 14177 WXS_ITEM_NODE(item), item, cur, 14178 "The attribute declaration's %s " 14179 "is not validly derived from " 14180 "the corresponding %s of the " 14181 "attribute declaration in the %s %s", 14182 xmlSchemaGetComponentDesignation(&strA, 14183 WXS_ATTRUSE_TYPEDEF(cur)), 14184 xmlSchemaGetComponentDesignation(&strB, 14185 WXS_ATTRUSE_TYPEDEF(bcur)), 14186 WXS_ACTION_STR(action), 14187 xmlSchemaGetComponentDesignation(&strC, baseItem)); 14188 /* xmlSchemaGetComponentDesignation(&str, baseItem), */ 14189 FREE_AND_NULL(strA); 14190 FREE_AND_NULL(strB); 14191 FREE_AND_NULL(strC); 14192 /* err = pctxt->err; */ 14193 } else { 14194 /* 14195 * 2.1.3 [Definition:] Let the effective value 14196 * constraint of an attribute use be its {value 14197 * constraint}, if present, otherwise its {attribute 14198 * declaration}'s {value constraint} . 14199 */ 14200 xmlSchemaGetEffectiveValueConstraint(bcur, 14201 &effFixed, &bEffValue, NULL); 14202 /* 14203 * 2.1.3 ... one of the following must be true 14204 * 14205 * 2.1.3.1 B's �effective value constraint� is 14206 * �absent� or default. 14207 */ 14208 if ((bEffValue != NULL) && 14209 (effFixed == 1)) { 14210 const xmlChar *rEffValue = NULL; 14211 14212 xmlSchemaGetEffectiveValueConstraint(bcur, 14213 &effFixed, &rEffValue, NULL); 14214 /* 14215 * 2.1.3.2 R's �effective value constraint� is 14216 * fixed with the same string as B's. 14217 * MAYBE TODO: Compare the computed values. 14218 * Hmm, it says "same string" so 14219 * string-equality might really be sufficient. 14220 */ 14221 if ((effFixed == 0) || 14222 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue))) 14223 { 14224 xmlChar *str = NULL; 14225 14226 xmlSchemaPAttrUseErr4(pctxt, 14227 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3, 14228 WXS_ITEM_NODE(item), item, cur, 14229 "The effective value constraint of the " 14230 "attribute use is inconsistent with " 14231 "its correspondent in the %s %s", 14232 WXS_ACTION_STR(action), 14233 xmlSchemaGetComponentDesignation(&str, 14234 baseItem), 14235 NULL, NULL); 14236 FREE_AND_NULL(str); 14237 /* err = pctxt->err; */ 14238 } 14239 } 14240 } 14241 break; 14242 } 14243 } 14244not_found: 14245 if (!found) { 14246 /* 14247 * (2.2) "otherwise the {base type definition} must have an 14248 * {attribute wildcard} and the {target namespace} of the 14249 * R's {attribute declaration} must be �valid� with respect 14250 * to that wildcard, as defined in Wildcard allows Namespace 14251 * Name (�3.10.4)." 14252 */ 14253 if ((baseWild == NULL) || 14254 (xmlSchemaCheckCVCWildcardNamespace(baseWild, 14255 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0)) 14256 { 14257 xmlChar *str = NULL; 14258 14259 xmlSchemaPAttrUseErr4(pctxt, 14260 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2, 14261 WXS_ITEM_NODE(item), item, cur, 14262 "Neither a matching attribute use, " 14263 "nor a matching wildcard exists in the %s %s", 14264 WXS_ACTION_STR(action), 14265 xmlSchemaGetComponentDesignation(&str, baseItem), 14266 NULL, NULL); 14267 FREE_AND_NULL(str); 14268 /* err = pctxt->err; */ 14269 } 14270 } 14271 } 14272 } 14273 /* 14274 * SPEC derivation-ok-restriction (3): 14275 * (3) "For each attribute use in the {attribute uses} of the {base type 14276 * definition} whose {required} is true, there must be an attribute 14277 * use with an {attribute declaration} with the same {name} and 14278 * {target namespace} as its {attribute declaration} in the {attribute 14279 * uses} of the complex type definition itself whose {required} is true. 14280 */ 14281 if (baseUses != NULL) { 14282 for (j = 0; j < baseUses->nbItems; j++) { 14283 bcur = baseUses->items[j]; 14284 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED) 14285 continue; 14286 found = 0; 14287 if (uses != NULL) { 14288 for (i = 0; i < uses->nbItems; i++) { 14289 cur = uses->items[i]; 14290 if ((WXS_ATTRUSE_DECL_NAME(cur) == 14291 WXS_ATTRUSE_DECL_NAME(bcur)) && 14292 (WXS_ATTRUSE_DECL_TNS(cur) == 14293 WXS_ATTRUSE_DECL_TNS(bcur))) { 14294 found = 1; 14295 break; 14296 } 14297 } 14298 } 14299 if (!found) { 14300 xmlChar *strA = NULL, *strB = NULL; 14301 14302 xmlSchemaCustomErr4(ACTXT_CAST pctxt, 14303 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3, 14304 NULL, item, 14305 "A matching attribute use for the " 14306 "'required' %s of the %s %s is missing", 14307 xmlSchemaGetComponentDesignation(&strA, bcur), 14308 WXS_ACTION_STR(action), 14309 xmlSchemaGetComponentDesignation(&strB, baseItem), 14310 NULL); 14311 FREE_AND_NULL(strA); 14312 FREE_AND_NULL(strB); 14313 } 14314 } 14315 } 14316 /* 14317 * derivation-ok-restriction (4) 14318 */ 14319 if (wild != NULL) { 14320 /* 14321 * (4) "If there is an {attribute wildcard}, all of the 14322 * following must be true:" 14323 */ 14324 if (baseWild == NULL) { 14325 xmlChar *str = NULL; 14326 14327 /* 14328 * (4.1) "The {base type definition} must also have one." 14329 */ 14330 xmlSchemaCustomErr4(ACTXT_CAST pctxt, 14331 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1, 14332 NULL, item, 14333 "The %s has an attribute wildcard, " 14334 "but the %s %s '%s' does not have one", 14335 WXS_ITEM_TYPE_NAME(item), 14336 WXS_ACTION_STR(action), 14337 WXS_ITEM_TYPE_NAME(baseItem), 14338 xmlSchemaGetComponentQName(&str, baseItem)); 14339 FREE_AND_NULL(str); 14340 return(pctxt->err); 14341 } else if ((baseWild->any == 0) && 14342 xmlSchemaCheckCOSNSSubset(wild, baseWild)) 14343 { 14344 xmlChar *str = NULL; 14345 /* 14346 * (4.2) "The complex type definition's {attribute wildcard}'s 14347 * {namespace constraint} must be a subset of the {base type 14348 * definition}'s {attribute wildcard}'s {namespace constraint}, 14349 * as defined by Wildcard Subset (�3.10.6)." 14350 */ 14351 xmlSchemaCustomErr4(ACTXT_CAST pctxt, 14352 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2, 14353 NULL, item, 14354 "The attribute wildcard is not a valid " 14355 "subset of the wildcard in the %s %s '%s'", 14356 WXS_ACTION_STR(action), 14357 WXS_ITEM_TYPE_NAME(baseItem), 14358 xmlSchemaGetComponentQName(&str, baseItem), 14359 NULL); 14360 FREE_AND_NULL(str); 14361 return(pctxt->err); 14362 } 14363 /* 4.3 Unless the {base type definition} is the �ur-type 14364 * definition�, the complex type definition's {attribute 14365 * wildcard}'s {process contents} must be identical to or 14366 * stronger than the {base type definition}'s {attribute 14367 * wildcard}'s {process contents}, where strict is stronger 14368 * than lax is stronger than skip. 14369 */ 14370 if ((! WXS_IS_ANYTYPE(baseItem)) && 14371 (wild->processContents < baseWild->processContents)) { 14372 xmlChar *str = NULL; 14373 xmlSchemaCustomErr4(ACTXT_CAST pctxt, 14374 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3, 14375 NULL, baseItem, 14376 "The {process contents} of the attribute wildcard is " 14377 "weaker than the one in the %s %s '%s'", 14378 WXS_ACTION_STR(action), 14379 WXS_ITEM_TYPE_NAME(baseItem), 14380 xmlSchemaGetComponentQName(&str, baseItem), 14381 NULL); 14382 FREE_AND_NULL(str) 14383 return(pctxt->err); 14384 } 14385 } 14386 return(0); 14387} 14388 14389 14390static int 14391xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt, 14392 xmlSchemaBasicItemPtr item, 14393 xmlSchemaWildcardPtr *completeWild, 14394 xmlSchemaItemListPtr list, 14395 xmlSchemaItemListPtr prohibs); 14396/** 14397 * xmlSchemaFixupTypeAttributeUses: 14398 * @ctxt: the schema parser context 14399 * @type: the complex type definition 14400 * 14401 * 14402 * Builds the wildcard and the attribute uses on the given complex type. 14403 * Returns -1 if an internal error occurs, 0 otherwise. 14404 * 14405 * ATTENTION TODO: Experimantally this uses pointer comparisons for 14406 * strings, so recheck this if we start to hardcode some schemata, since 14407 * they might not be in the same dict. 14408 * NOTE: It is allowed to "extend" the xs:anyType type. 14409 */ 14410static int 14411xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt, 14412 xmlSchemaTypePtr type) 14413{ 14414 xmlSchemaTypePtr baseType = NULL; 14415 xmlSchemaAttributeUsePtr use; 14416 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL; 14417 14418 if (type->baseType == NULL) { 14419 PERROR_INT("xmlSchemaFixupTypeAttributeUses", 14420 "no base type"); 14421 return (-1); 14422 } 14423 baseType = type->baseType; 14424 if (WXS_IS_TYPE_NOT_FIXED(baseType)) 14425 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1) 14426 return(-1); 14427 14428 uses = type->attrUses; 14429 baseUses = baseType->attrUses; 14430 /* 14431 * Expand attribute group references. And build the 'complete' 14432 * wildcard, i.e. intersect multiple wildcards. 14433 * Move attribute prohibitions into a separate list. 14434 */ 14435 if (uses != NULL) { 14436 if (WXS_IS_RESTRICTION(type)) { 14437 /* 14438 * This one will transfer all attr. prohibitions 14439 * into pctxt->attrProhibs. 14440 */ 14441 if (xmlSchemaExpandAttributeGroupRefs(pctxt, 14442 WXS_BASIC_CAST type, &(type->attributeWildcard), uses, 14443 pctxt->attrProhibs) == -1) 14444 { 14445 PERROR_INT("xmlSchemaFixupTypeAttributeUses", 14446 "failed to expand attributes"); 14447 } 14448 if (pctxt->attrProhibs->nbItems != 0) 14449 prohibs = pctxt->attrProhibs; 14450 } else { 14451 if (xmlSchemaExpandAttributeGroupRefs(pctxt, 14452 WXS_BASIC_CAST type, &(type->attributeWildcard), uses, 14453 NULL) == -1) 14454 { 14455 PERROR_INT("xmlSchemaFixupTypeAttributeUses", 14456 "failed to expand attributes"); 14457 } 14458 } 14459 } 14460 /* 14461 * Inherit the attribute uses of the base type. 14462 */ 14463 if (baseUses != NULL) { 14464 int i, j; 14465 xmlSchemaAttributeUseProhibPtr pro; 14466 14467 if (WXS_IS_RESTRICTION(type)) { 14468 int usesCount; 14469 xmlSchemaAttributeUsePtr tmp; 14470 14471 if (uses != NULL) 14472 usesCount = uses->nbItems; 14473 else 14474 usesCount = 0; 14475 14476 /* Restriction. */ 14477 for (i = 0; i < baseUses->nbItems; i++) { 14478 use = baseUses->items[i]; 14479 if (prohibs) { 14480 /* 14481 * Filter out prohibited uses. 14482 */ 14483 for (j = 0; j < prohibs->nbItems; j++) { 14484 pro = prohibs->items[j]; 14485 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) && 14486 (WXS_ATTRUSE_DECL_TNS(use) == 14487 pro->targetNamespace)) 14488 { 14489 goto inherit_next; 14490 } 14491 } 14492 } 14493 if (usesCount) { 14494 /* 14495 * Filter out existing uses. 14496 */ 14497 for (j = 0; j < usesCount; j++) { 14498 tmp = uses->items[j]; 14499 if ((WXS_ATTRUSE_DECL_NAME(use) == 14500 WXS_ATTRUSE_DECL_NAME(tmp)) && 14501 (WXS_ATTRUSE_DECL_TNS(use) == 14502 WXS_ATTRUSE_DECL_TNS(tmp))) 14503 { 14504 goto inherit_next; 14505 } 14506 } 14507 } 14508 if (uses == NULL) { 14509 type->attrUses = xmlSchemaItemListCreate(); 14510 if (type->attrUses == NULL) 14511 goto exit_failure; 14512 uses = type->attrUses; 14513 } 14514 xmlSchemaItemListAddSize(uses, 2, use); 14515inherit_next: {} 14516 } 14517 } else { 14518 /* Extension. */ 14519 for (i = 0; i < baseUses->nbItems; i++) { 14520 use = baseUses->items[i]; 14521 if (uses == NULL) { 14522 type->attrUses = xmlSchemaItemListCreate(); 14523 if (type->attrUses == NULL) 14524 goto exit_failure; 14525 uses = type->attrUses; 14526 } 14527 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use); 14528 } 14529 } 14530 } 14531 /* 14532 * Shrink attr. uses. 14533 */ 14534 if (uses) { 14535 if (uses->nbItems == 0) { 14536 xmlSchemaItemListFree(uses); 14537 type->attrUses = NULL; 14538 } 14539 /* 14540 * TODO: We could shrink the size of the array 14541 * to fit the actual number of items. 14542 */ 14543 } 14544 /* 14545 * Compute the complete wildcard. 14546 */ 14547 if (WXS_IS_EXTENSION(type)) { 14548 if (baseType->attributeWildcard != NULL) { 14549 /* 14550 * (3.2.2.1) "If the �base wildcard� is non-�absent�, then 14551 * the appropriate case among the following:" 14552 */ 14553 if (type->attributeWildcard != NULL) { 14554 /* 14555 * Union the complete wildcard with the base wildcard. 14556 * SPEC {attribute wildcard} 14557 * (3.2.2.1.2) "otherwise a wildcard whose {process contents} 14558 * and {annotation} are those of the �complete wildcard�, 14559 * and whose {namespace constraint} is the intensional union 14560 * of the {namespace constraint} of the �complete wildcard� 14561 * and of the �base wildcard�, as defined in Attribute 14562 * Wildcard Union (�3.10.6)." 14563 */ 14564 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard, 14565 baseType->attributeWildcard) == -1) 14566 goto exit_failure; 14567 } else { 14568 /* 14569 * (3.2.2.1.1) "If the �complete wildcard� is �absent�, 14570 * then the �base wildcard�." 14571 */ 14572 type->attributeWildcard = baseType->attributeWildcard; 14573 } 14574 } else { 14575 /* 14576 * (3.2.2.2) "otherwise (the �base wildcard� is �absent�) the 14577 * �complete wildcard" 14578 * NOOP 14579 */ 14580 } 14581 } else { 14582 /* 14583 * SPEC {attribute wildcard} 14584 * (3.1) "If the <restriction> alternative is chosen, then the 14585 * �complete wildcard�;" 14586 * NOOP 14587 */ 14588 } 14589 14590 return (0); 14591 14592exit_failure: 14593 return(-1); 14594} 14595 14596/** 14597 * xmlSchemaTypeFinalContains: 14598 * @schema: the schema 14599 * @type: the type definition 14600 * @final: the final 14601 * 14602 * Evaluates if a type definition contains the given "final". 14603 * This does take "finalDefault" into account as well. 14604 * 14605 * Returns 1 if the type does containt the given "final", 14606 * 0 otherwise. 14607 */ 14608static int 14609xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final) 14610{ 14611 if (type == NULL) 14612 return (0); 14613 if (type->flags & final) 14614 return (1); 14615 else 14616 return (0); 14617} 14618 14619/** 14620 * xmlSchemaGetUnionSimpleTypeMemberTypes: 14621 * @type: the Union Simple Type 14622 * 14623 * Returns a list of member types of @type if existing, 14624 * returns NULL otherwise. 14625 */ 14626static xmlSchemaTypeLinkPtr 14627xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type) 14628{ 14629 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) { 14630 if (type->memberTypes != NULL) 14631 return (type->memberTypes); 14632 else 14633 type = type->baseType; 14634 } 14635 return (NULL); 14636} 14637 14638/** 14639 * xmlSchemaGetParticleTotalRangeMin: 14640 * @particle: the particle 14641 * 14642 * Schema Component Constraint: Effective Total Range 14643 * (all and sequence) + (choice) 14644 * 14645 * Returns the minimun Effective Total Range. 14646 */ 14647static int 14648xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle) 14649{ 14650 if ((particle->children == NULL) || 14651 (particle->minOccurs == 0)) 14652 return (0); 14653 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) { 14654 int min = -1, cur; 14655 xmlSchemaParticlePtr part = 14656 (xmlSchemaParticlePtr) particle->children->children; 14657 14658 if (part == NULL) 14659 return (0); 14660 while (part != NULL) { 14661 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || 14662 (part->children->type == XML_SCHEMA_TYPE_ANY)) 14663 cur = part->minOccurs; 14664 else 14665 cur = xmlSchemaGetParticleTotalRangeMin(part); 14666 if (cur == 0) 14667 return (0); 14668 if ((min > cur) || (min == -1)) 14669 min = cur; 14670 part = (xmlSchemaParticlePtr) part->next; 14671 } 14672 return (particle->minOccurs * min); 14673 } else { 14674 /* <all> and <sequence> */ 14675 int sum = 0; 14676 xmlSchemaParticlePtr part = 14677 (xmlSchemaParticlePtr) particle->children->children; 14678 14679 if (part == NULL) 14680 return (0); 14681 do { 14682 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || 14683 (part->children->type == XML_SCHEMA_TYPE_ANY)) 14684 sum += part->minOccurs; 14685 else 14686 sum += xmlSchemaGetParticleTotalRangeMin(part); 14687 part = (xmlSchemaParticlePtr) part->next; 14688 } while (part != NULL); 14689 return (particle->minOccurs * sum); 14690 } 14691} 14692 14693#if 0 14694/** 14695 * xmlSchemaGetParticleTotalRangeMax: 14696 * @particle: the particle 14697 * 14698 * Schema Component Constraint: Effective Total Range 14699 * (all and sequence) + (choice) 14700 * 14701 * Returns the maximum Effective Total Range. 14702 */ 14703static int 14704xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle) 14705{ 14706 if ((particle->children == NULL) || 14707 (particle->children->children == NULL)) 14708 return (0); 14709 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) { 14710 int max = -1, cur; 14711 xmlSchemaParticlePtr part = 14712 (xmlSchemaParticlePtr) particle->children->children; 14713 14714 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) { 14715 if (part->children == NULL) 14716 continue; 14717 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || 14718 (part->children->type == XML_SCHEMA_TYPE_ANY)) 14719 cur = part->maxOccurs; 14720 else 14721 cur = xmlSchemaGetParticleTotalRangeMax(part); 14722 if (cur == UNBOUNDED) 14723 return (UNBOUNDED); 14724 if ((max < cur) || (max == -1)) 14725 max = cur; 14726 } 14727 /* TODO: Handle overflows? */ 14728 return (particle->maxOccurs * max); 14729 } else { 14730 /* <all> and <sequence> */ 14731 int sum = 0, cur; 14732 xmlSchemaParticlePtr part = 14733 (xmlSchemaParticlePtr) particle->children->children; 14734 14735 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) { 14736 if (part->children == NULL) 14737 continue; 14738 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || 14739 (part->children->type == XML_SCHEMA_TYPE_ANY)) 14740 cur = part->maxOccurs; 14741 else 14742 cur = xmlSchemaGetParticleTotalRangeMax(part); 14743 if (cur == UNBOUNDED) 14744 return (UNBOUNDED); 14745 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED)) 14746 return (UNBOUNDED); 14747 sum += cur; 14748 } 14749 /* TODO: Handle overflows? */ 14750 return (particle->maxOccurs * sum); 14751 } 14752} 14753#endif 14754 14755/** 14756 * xmlSchemaIsParticleEmptiable: 14757 * @particle: the particle 14758 * 14759 * Schema Component Constraint: Particle Emptiable 14760 * Checks whether the given particle is emptiable. 14761 * 14762 * Returns 1 if emptiable, 0 otherwise. 14763 */ 14764static int 14765xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle) 14766{ 14767 /* 14768 * SPEC (1) "Its {min occurs} is 0." 14769 */ 14770 if ((particle == NULL) || (particle->minOccurs == 0) || 14771 (particle->children == NULL)) 14772 return (1); 14773 /* 14774 * SPEC (2) "Its {term} is a group and the minimum part of the 14775 * effective total range of that group, [...] is 0." 14776 */ 14777 if (WXS_IS_MODEL_GROUP(particle->children)) { 14778 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0) 14779 return (1); 14780 } 14781 return (0); 14782} 14783 14784/** 14785 * xmlSchemaCheckCOSSTDerivedOK: 14786 * @actxt: a context 14787 * @type: the derived simple type definition 14788 * @baseType: the base type definition 14789 * @subset: the subset of ('restriction', ect.) 14790 * 14791 * Schema Component Constraint: 14792 * Type Derivation OK (Simple) (cos-st-derived-OK) 14793 * 14794 * Checks wheter @type can be validly 14795 * derived from @baseType. 14796 * 14797 * Returns 0 on success, an positive error code otherwise. 14798 */ 14799static int 14800xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt, 14801 xmlSchemaTypePtr type, 14802 xmlSchemaTypePtr baseType, 14803 int subset) 14804{ 14805 /* 14806 * 1 They are the same type definition. 14807 * TODO: The identy check might have to be more complex than this. 14808 */ 14809 if (type == baseType) 14810 return (0); 14811 /* 14812 * 2.1 restriction is not in the subset, or in the {final} 14813 * of its own {base type definition}; 14814 * 14815 * NOTE that this will be used also via "xsi:type". 14816 * 14817 * TODO: Revise this, it looks strange. How can the "type" 14818 * not be fixed or *in* fixing? 14819 */ 14820 if (WXS_IS_TYPE_NOT_FIXED(type)) 14821 if (xmlSchemaTypeFixup(type, actxt) == -1) 14822 return(-1); 14823 if (WXS_IS_TYPE_NOT_FIXED(baseType)) 14824 if (xmlSchemaTypeFixup(baseType, actxt) == -1) 14825 return(-1); 14826 if ((subset & SUBSET_RESTRICTION) || 14827 (xmlSchemaTypeFinalContains(type->baseType, 14828 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) { 14829 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1); 14830 } 14831 /* 2.2 */ 14832 if (type->baseType == baseType) { 14833 /* 14834 * 2.2.1 D's �base type definition� is B. 14835 */ 14836 return (0); 14837 } 14838 /* 14839 * 2.2.2 D's �base type definition� is not the �ur-type definition� 14840 * and is validly derived from B given the subset, as defined by this 14841 * constraint. 14842 */ 14843 if ((! WXS_IS_ANYTYPE(type->baseType)) && 14844 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType, 14845 baseType, subset) == 0)) { 14846 return (0); 14847 } 14848 /* 14849 * 2.2.3 D's {variety} is list or union and B is the �simple ur-type 14850 * definition�. 14851 */ 14852 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) && 14853 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) { 14854 return (0); 14855 } 14856 /* 14857 * 2.2.4 B's {variety} is union and D is validly derived from a type 14858 * definition in B's {member type definitions} given the subset, as 14859 * defined by this constraint. 14860 * 14861 * NOTE: This seems not to involve built-in types, since there is no 14862 * built-in Union Simple Type. 14863 */ 14864 if (WXS_IS_UNION(baseType)) { 14865 xmlSchemaTypeLinkPtr cur; 14866 14867 cur = baseType->memberTypes; 14868 while (cur != NULL) { 14869 if (WXS_IS_TYPE_NOT_FIXED(cur->type)) 14870 if (xmlSchemaTypeFixup(cur->type, actxt) == -1) 14871 return(-1); 14872 if (xmlSchemaCheckCOSSTDerivedOK(actxt, 14873 type, cur->type, subset) == 0) 14874 { 14875 /* 14876 * It just has to be validly derived from at least one 14877 * member-type. 14878 */ 14879 return (0); 14880 } 14881 cur = cur->next; 14882 } 14883 } 14884 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2); 14885} 14886 14887/** 14888 * xmlSchemaCheckTypeDefCircularInternal: 14889 * @pctxt: the schema parser context 14890 * @ctxtType: the type definition 14891 * @ancestor: an ancestor of @ctxtType 14892 * 14893 * Checks st-props-correct (2) + ct-props-correct (3). 14894 * Circular type definitions are not allowed. 14895 * 14896 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is 14897 * circular, 0 otherwise. 14898 */ 14899static int 14900xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt, 14901 xmlSchemaTypePtr ctxtType, 14902 xmlSchemaTypePtr ancestor) 14903{ 14904 int ret; 14905 14906 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC)) 14907 return (0); 14908 14909 if (ctxtType == ancestor) { 14910 xmlSchemaPCustomErr(pctxt, 14911 XML_SCHEMAP_ST_PROPS_CORRECT_2, 14912 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType), 14913 "The definition is circular", NULL); 14914 return (XML_SCHEMAP_ST_PROPS_CORRECT_2); 14915 } 14916 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) { 14917 /* 14918 * Avoid inifinite recursion on circular types not yet checked. 14919 */ 14920 return (0); 14921 } 14922 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED; 14923 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType, 14924 ancestor->baseType); 14925 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED; 14926 return (ret); 14927} 14928 14929/** 14930 * xmlSchemaCheckTypeDefCircular: 14931 * @item: the complex/simple type definition 14932 * @ctxt: the parser context 14933 * @name: the name 14934 * 14935 * Checks for circular type definitions. 14936 */ 14937static void 14938xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item, 14939 xmlSchemaParserCtxtPtr ctxt) 14940{ 14941 if ((item == NULL) || 14942 (item->type == XML_SCHEMA_TYPE_BASIC) || 14943 (item->baseType == NULL)) 14944 return; 14945 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, 14946 item->baseType); 14947} 14948 14949/* 14950* Simple Type Definition Representation OK (src-simple-type) 4 14951* 14952* "4 Circular union type definition is disallowed. That is, if the 14953* <union> alternative is chosen, there must not be any entries in the 14954* memberTypes [attribute] at any depth which resolve to the component 14955* corresponding to the <simpleType>." 14956* 14957* Note that this should work on the *representation* of a component, 14958* thus assumes any union types in the member types not being yet 14959* substituted. At this stage we need the variety of the types 14960* to be already computed. 14961*/ 14962static int 14963xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt, 14964 xmlSchemaTypePtr ctxType, 14965 xmlSchemaTypeLinkPtr members) 14966{ 14967 xmlSchemaTypeLinkPtr member; 14968 xmlSchemaTypePtr memberType; 14969 14970 member = members; 14971 while (member != NULL) { 14972 memberType = member->type; 14973 while ((memberType != NULL) && 14974 (memberType->type != XML_SCHEMA_TYPE_BASIC)) { 14975 if (memberType == ctxType) { 14976 xmlSchemaPCustomErr(pctxt, 14977 XML_SCHEMAP_SRC_SIMPLE_TYPE_4, 14978 WXS_BASIC_CAST ctxType, NULL, 14979 "The union type definition is circular", NULL); 14980 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4); 14981 } 14982 if ((WXS_IS_UNION(memberType)) && 14983 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0)) 14984 { 14985 int res; 14986 memberType->flags |= XML_SCHEMAS_TYPE_MARKED; 14987 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, 14988 ctxType, 14989 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType)); 14990 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED; 14991 if (res != 0) 14992 return(res); 14993 } 14994 memberType = memberType->baseType; 14995 } 14996 member = member->next; 14997 } 14998 return(0); 14999} 15000 15001static int 15002xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt, 15003 xmlSchemaTypePtr type) 15004{ 15005 if (! WXS_IS_UNION(type)) 15006 return(0); 15007 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type, 15008 type->memberTypes)); 15009} 15010 15011/** 15012 * xmlSchemaResolveTypeReferences: 15013 * @item: the complex/simple type definition 15014 * @ctxt: the parser context 15015 * @name: the name 15016 * 15017 * Resolvese type definition references 15018 */ 15019static void 15020xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef, 15021 xmlSchemaParserCtxtPtr ctxt) 15022{ 15023 if (typeDef == NULL) 15024 return; 15025 15026 /* 15027 * Resolve the base type. 15028 */ 15029 if (typeDef->baseType == NULL) { 15030 typeDef->baseType = xmlSchemaGetType(ctxt->schema, 15031 typeDef->base, typeDef->baseNs); 15032 if (typeDef->baseType == NULL) { 15033 xmlSchemaPResCompAttrErr(ctxt, 15034 XML_SCHEMAP_SRC_RESOLVE, 15035 WXS_BASIC_CAST typeDef, typeDef->node, 15036 "base", typeDef->base, typeDef->baseNs, 15037 XML_SCHEMA_TYPE_SIMPLE, NULL); 15038 return; 15039 } 15040 } 15041 if (WXS_IS_SIMPLE(typeDef)) { 15042 if (WXS_IS_UNION(typeDef)) { 15043 /* 15044 * Resolve the memberTypes. 15045 */ 15046 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef); 15047 return; 15048 } else if (WXS_IS_LIST(typeDef)) { 15049 /* 15050 * Resolve the itemType. 15051 */ 15052 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) { 15053 15054 typeDef->subtypes = xmlSchemaGetType(ctxt->schema, 15055 typeDef->base, typeDef->baseNs); 15056 15057 if ((typeDef->subtypes == NULL) || 15058 (! WXS_IS_SIMPLE(typeDef->subtypes))) 15059 { 15060 typeDef->subtypes = NULL; 15061 xmlSchemaPResCompAttrErr(ctxt, 15062 XML_SCHEMAP_SRC_RESOLVE, 15063 WXS_BASIC_CAST typeDef, typeDef->node, 15064 "itemType", typeDef->base, typeDef->baseNs, 15065 XML_SCHEMA_TYPE_SIMPLE, NULL); 15066 } 15067 } 15068 return; 15069 } 15070 } 15071 /* 15072 * The ball of letters below means, that if we have a particle 15073 * which has a QName-helper component as its {term}, we want 15074 * to resolve it... 15075 */ 15076 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) && 15077 ((WXS_TYPE_CONTENTTYPE(typeDef))->type == 15078 XML_SCHEMA_TYPE_PARTICLE) && 15079 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) && 15080 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type == 15081 XML_SCHEMA_EXTRA_QNAMEREF)) 15082 { 15083 xmlSchemaQNameRefPtr ref = 15084 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef); 15085 xmlSchemaModelGroupDefPtr groupDef; 15086 15087 /* 15088 * URGENT TODO: Test this. 15089 */ 15090 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL; 15091 /* 15092 * Resolve the MG definition reference. 15093 */ 15094 groupDef = 15095 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema, 15096 ref->itemType, ref->name, ref->targetNamespace); 15097 if (groupDef == NULL) { 15098 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE, 15099 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), 15100 "ref", ref->name, ref->targetNamespace, ref->itemType, 15101 NULL); 15102 /* Remove the particle. */ 15103 WXS_TYPE_CONTENTTYPE(typeDef) = NULL; 15104 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL) 15105 /* Remove the particle. */ 15106 WXS_TYPE_CONTENTTYPE(typeDef) = NULL; 15107 else { 15108 /* 15109 * Assign the MG definition's {model group} to the 15110 * particle's {term}. 15111 */ 15112 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef); 15113 15114 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) { 15115 /* 15116 * SPEC cos-all-limited (1.2) 15117 * "1.2 the {term} property of a particle with 15118 * {max occurs}=1 which is part of a pair which constitutes 15119 * the {content type} of a complex type definition." 15120 */ 15121 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) { 15122 xmlSchemaCustomErr(ACTXT_CAST ctxt, 15123 /* TODO: error code */ 15124 XML_SCHEMAP_COS_ALL_LIMITED, 15125 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL, 15126 "The particle's {max occurs} must be 1, since the " 15127 "reference resolves to an 'all' model group", 15128 NULL, NULL); 15129 } 15130 } 15131 } 15132 } 15133} 15134 15135 15136 15137/** 15138 * xmlSchemaCheckSTPropsCorrect: 15139 * @ctxt: the schema parser context 15140 * @type: the simple type definition 15141 * 15142 * Checks st-props-correct. 15143 * 15144 * Returns 0 if the properties are correct, 15145 * if not, a positive error code and -1 on internal 15146 * errors. 15147 */ 15148static int 15149xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt, 15150 xmlSchemaTypePtr type) 15151{ 15152 xmlSchemaTypePtr baseType = type->baseType; 15153 xmlChar *str = NULL; 15154 15155 /* STATE: error funcs converted. */ 15156 /* 15157 * Schema Component Constraint: Simple Type Definition Properties Correct 15158 * 15159 * NOTE: This is somehow redundant, since we actually built a simple type 15160 * to have all the needed information; this acts as an self test. 15161 */ 15162 /* Base type: If the datatype has been �derived� by �restriction� 15163 * then the Simple Type Definition component from which it is �derived�, 15164 * otherwise the Simple Type Definition for anySimpleType (�4.1.6). 15165 */ 15166 if (baseType == NULL) { 15167 /* 15168 * TODO: Think about: "modulo the impact of Missing 15169 * Sub-components (�5.3)." 15170 */ 15171 xmlSchemaPCustomErr(ctxt, 15172 XML_SCHEMAP_ST_PROPS_CORRECT_1, 15173 WXS_BASIC_CAST type, NULL, 15174 "No base type existent", NULL); 15175 return (XML_SCHEMAP_ST_PROPS_CORRECT_1); 15176 15177 } 15178 if (! WXS_IS_SIMPLE(baseType)) { 15179 xmlSchemaPCustomErr(ctxt, 15180 XML_SCHEMAP_ST_PROPS_CORRECT_1, 15181 WXS_BASIC_CAST type, NULL, 15182 "The base type '%s' is not a simple type", 15183 xmlSchemaGetComponentQName(&str, baseType)); 15184 FREE_AND_NULL(str) 15185 return (XML_SCHEMAP_ST_PROPS_CORRECT_1); 15186 } 15187 if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) && 15188 (WXS_IS_RESTRICTION(type) == 0) && 15189 ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) && 15190 (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) { 15191 xmlSchemaPCustomErr(ctxt, 15192 XML_SCHEMAP_ST_PROPS_CORRECT_1, 15193 WXS_BASIC_CAST type, NULL, 15194 "A type, derived by list or union, must have " 15195 "the simple ur-type definition as base type, not '%s'", 15196 xmlSchemaGetComponentQName(&str, baseType)); 15197 FREE_AND_NULL(str) 15198 return (XML_SCHEMAP_ST_PROPS_CORRECT_1); 15199 } 15200 /* 15201 * Variety: One of {atomic, list, union}. 15202 */ 15203 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) && 15204 (! WXS_IS_LIST(type))) { 15205 xmlSchemaPCustomErr(ctxt, 15206 XML_SCHEMAP_ST_PROPS_CORRECT_1, 15207 WXS_BASIC_CAST type, NULL, 15208 "The variety is absent", NULL); 15209 return (XML_SCHEMAP_ST_PROPS_CORRECT_1); 15210 } 15211 /* TODO: Finish this. Hmm, is this finished? */ 15212 15213 /* 15214 * 3 The {final} of the {base type definition} must not contain restriction. 15215 */ 15216 if (xmlSchemaTypeFinalContains(baseType, 15217 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { 15218 xmlSchemaPCustomErr(ctxt, 15219 XML_SCHEMAP_ST_PROPS_CORRECT_3, 15220 WXS_BASIC_CAST type, NULL, 15221 "The 'final' of its base type '%s' must not contain " 15222 "'restriction'", 15223 xmlSchemaGetComponentQName(&str, baseType)); 15224 FREE_AND_NULL(str) 15225 return (XML_SCHEMAP_ST_PROPS_CORRECT_3); 15226 } 15227 15228 /* 15229 * 2 All simple type definitions must be derived ultimately from the �simple 15230 * ur-type definition (so� circular definitions are disallowed). That is, it 15231 * must be possible to reach a built-in primitive datatype or the �simple 15232 * ur-type definition� by repeatedly following the {base type definition}. 15233 * 15234 * NOTE: this is done in xmlSchemaCheckTypeDefCircular(). 15235 */ 15236 return (0); 15237} 15238 15239/** 15240 * xmlSchemaCheckCOSSTRestricts: 15241 * @ctxt: the schema parser context 15242 * @type: the simple type definition 15243 * 15244 * Schema Component Constraint: 15245 * Derivation Valid (Restriction, Simple) (cos-st-restricts) 15246 15247 * Checks if the given @type (simpleType) is derived validly by restriction. 15248 * STATUS: 15249 * 15250 * Returns -1 on internal errors, 0 if the type is validly derived, 15251 * a positive error code otherwise. 15252 */ 15253static int 15254xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt, 15255 xmlSchemaTypePtr type) 15256{ 15257 xmlChar *str = NULL; 15258 15259 if (type->type != XML_SCHEMA_TYPE_SIMPLE) { 15260 PERROR_INT("xmlSchemaCheckCOSSTRestricts", 15261 "given type is not a user-derived simpleType"); 15262 return (-1); 15263 } 15264 15265 if (WXS_IS_ATOMIC(type)) { 15266 xmlSchemaTypePtr primitive; 15267 /* 15268 * 1.1 The {base type definition} must be an atomic simple 15269 * type definition or a built-in primitive datatype. 15270 */ 15271 if (! WXS_IS_ATOMIC(type->baseType)) { 15272 xmlSchemaPCustomErr(pctxt, 15273 XML_SCHEMAP_COS_ST_RESTRICTS_1_1, 15274 WXS_BASIC_CAST type, NULL, 15275 "The base type '%s' is not an atomic simple type", 15276 xmlSchemaGetComponentQName(&str, type->baseType)); 15277 FREE_AND_NULL(str) 15278 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1); 15279 } 15280 /* 1.2 The {final} of the {base type definition} must not contain 15281 * restriction. 15282 */ 15283 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */ 15284 if (xmlSchemaTypeFinalContains(type->baseType, 15285 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { 15286 xmlSchemaPCustomErr(pctxt, 15287 XML_SCHEMAP_COS_ST_RESTRICTS_1_2, 15288 WXS_BASIC_CAST type, NULL, 15289 "The final of its base type '%s' must not contain 'restriction'", 15290 xmlSchemaGetComponentQName(&str, type->baseType)); 15291 FREE_AND_NULL(str) 15292 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2); 15293 } 15294 15295 /* 15296 * 1.3.1 DF must be an allowed constraining facet for the {primitive 15297 * type definition}, as specified in the appropriate subsection of 3.2 15298 * Primitive datatypes. 15299 */ 15300 if (type->facets != NULL) { 15301 xmlSchemaFacetPtr facet; 15302 int ok = 1; 15303 15304 primitive = xmlSchemaGetPrimitiveType(type); 15305 if (primitive == NULL) { 15306 PERROR_INT("xmlSchemaCheckCOSSTRestricts", 15307 "failed to get primitive type"); 15308 return (-1); 15309 } 15310 facet = type->facets; 15311 do { 15312 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) { 15313 ok = 0; 15314 xmlSchemaPIllegalFacetAtomicErr(pctxt, 15315 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1, 15316 type, primitive, facet); 15317 } 15318 facet = facet->next; 15319 } while (facet != NULL); 15320 if (ok == 0) 15321 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1); 15322 } 15323 /* 15324 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets} 15325 * of the {base type definition} (call this BF),then the DF's {value} 15326 * must be a valid restriction of BF's {value} as defined in 15327 * [XML Schemas: Datatypes]." 15328 * 15329 * NOTE (1.3.2) Facet derivation constraints are currently handled in 15330 * xmlSchemaDeriveAndValidateFacets() 15331 */ 15332 } else if (WXS_IS_LIST(type)) { 15333 xmlSchemaTypePtr itemType = NULL; 15334 15335 itemType = type->subtypes; 15336 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) { 15337 PERROR_INT("xmlSchemaCheckCOSSTRestricts", 15338 "failed to evaluate the item type"); 15339 return (-1); 15340 } 15341 if (WXS_IS_TYPE_NOT_FIXED(itemType)) 15342 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt); 15343 /* 15344 * 2.1 The {item type definition} must have a {variety} of atomic or 15345 * union (in which case all the {member type definitions} 15346 * must be atomic). 15347 */ 15348 if ((! WXS_IS_ATOMIC(itemType)) && 15349 (! WXS_IS_UNION(itemType))) { 15350 xmlSchemaPCustomErr(pctxt, 15351 XML_SCHEMAP_COS_ST_RESTRICTS_2_1, 15352 WXS_BASIC_CAST type, NULL, 15353 "The item type '%s' does not have a variety of atomic or union", 15354 xmlSchemaGetComponentQName(&str, itemType)); 15355 FREE_AND_NULL(str) 15356 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1); 15357 } else if (WXS_IS_UNION(itemType)) { 15358 xmlSchemaTypeLinkPtr member; 15359 15360 member = itemType->memberTypes; 15361 while (member != NULL) { 15362 if (! WXS_IS_ATOMIC(member->type)) { 15363 xmlSchemaPCustomErr(pctxt, 15364 XML_SCHEMAP_COS_ST_RESTRICTS_2_1, 15365 WXS_BASIC_CAST type, NULL, 15366 "The item type is a union type, but the " 15367 "member type '%s' of this item type is not atomic", 15368 xmlSchemaGetComponentQName(&str, member->type)); 15369 FREE_AND_NULL(str) 15370 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1); 15371 } 15372 member = member->next; 15373 } 15374 } 15375 15376 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) { 15377 xmlSchemaFacetPtr facet; 15378 /* 15379 * This is the case if we have: <simpleType><list .. 15380 */ 15381 /* 15382 * 2.3.1 15383 * 2.3.1.1 The {final} of the {item type definition} must not 15384 * contain list. 15385 */ 15386 if (xmlSchemaTypeFinalContains(itemType, 15387 XML_SCHEMAS_TYPE_FINAL_LIST)) { 15388 xmlSchemaPCustomErr(pctxt, 15389 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1, 15390 WXS_BASIC_CAST type, NULL, 15391 "The final of its item type '%s' must not contain 'list'", 15392 xmlSchemaGetComponentQName(&str, itemType)); 15393 FREE_AND_NULL(str) 15394 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1); 15395 } 15396 /* 15397 * 2.3.1.2 The {facets} must only contain the whiteSpace 15398 * facet component. 15399 * OPTIMIZE TODO: the S4S already disallows any facet 15400 * to be specified. 15401 */ 15402 if (type->facets != NULL) { 15403 facet = type->facets; 15404 do { 15405 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) { 15406 xmlSchemaPIllegalFacetListUnionErr(pctxt, 15407 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2, 15408 type, facet); 15409 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2); 15410 } 15411 facet = facet->next; 15412 } while (facet != NULL); 15413 } 15414 /* 15415 * MAYBE TODO: (Hmm, not really) Datatypes states: 15416 * A �list� datatype can be �derived� from an �atomic� datatype 15417 * whose �lexical space� allows space (such as string or anyURI)or 15418 * a �union� datatype any of whose {member type definitions}'s 15419 * �lexical space� allows space. 15420 */ 15421 } else { 15422 /* 15423 * This is the case if we have: <simpleType><restriction ... 15424 * I.e. the variety of "list" is inherited. 15425 */ 15426 /* 15427 * 2.3.2 15428 * 2.3.2.1 The {base type definition} must have a {variety} of list. 15429 */ 15430 if (! WXS_IS_LIST(type->baseType)) { 15431 xmlSchemaPCustomErr(pctxt, 15432 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1, 15433 WXS_BASIC_CAST type, NULL, 15434 "The base type '%s' must be a list type", 15435 xmlSchemaGetComponentQName(&str, type->baseType)); 15436 FREE_AND_NULL(str) 15437 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1); 15438 } 15439 /* 15440 * 2.3.2.2 The {final} of the {base type definition} must not 15441 * contain restriction. 15442 */ 15443 if (xmlSchemaTypeFinalContains(type->baseType, 15444 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { 15445 xmlSchemaPCustomErr(pctxt, 15446 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2, 15447 WXS_BASIC_CAST type, NULL, 15448 "The 'final' of the base type '%s' must not contain 'restriction'", 15449 xmlSchemaGetComponentQName(&str, type->baseType)); 15450 FREE_AND_NULL(str) 15451 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2); 15452 } 15453 /* 15454 * 2.3.2.3 The {item type definition} must be validly derived 15455 * from the {base type definition}'s {item type definition} given 15456 * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6). 15457 */ 15458 { 15459 xmlSchemaTypePtr baseItemType; 15460 15461 baseItemType = type->baseType->subtypes; 15462 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) { 15463 PERROR_INT("xmlSchemaCheckCOSSTRestricts", 15464 "failed to eval the item type of a base type"); 15465 return (-1); 15466 } 15467 if ((itemType != baseItemType) && 15468 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType, 15469 baseItemType, 0) != 0)) { 15470 xmlChar *strBIT = NULL, *strBT = NULL; 15471 xmlSchemaPCustomErrExt(pctxt, 15472 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3, 15473 WXS_BASIC_CAST type, NULL, 15474 "The item type '%s' is not validly derived from " 15475 "the item type '%s' of the base type '%s'", 15476 xmlSchemaGetComponentQName(&str, itemType), 15477 xmlSchemaGetComponentQName(&strBIT, baseItemType), 15478 xmlSchemaGetComponentQName(&strBT, type->baseType)); 15479 15480 FREE_AND_NULL(str) 15481 FREE_AND_NULL(strBIT) 15482 FREE_AND_NULL(strBT) 15483 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3); 15484 } 15485 } 15486 15487 if (type->facets != NULL) { 15488 xmlSchemaFacetPtr facet; 15489 int ok = 1; 15490 /* 15491 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern 15492 * and enumeration facet components are allowed among the {facets}. 15493 */ 15494 facet = type->facets; 15495 do { 15496 switch (facet->type) { 15497 case XML_SCHEMA_FACET_LENGTH: 15498 case XML_SCHEMA_FACET_MINLENGTH: 15499 case XML_SCHEMA_FACET_MAXLENGTH: 15500 case XML_SCHEMA_FACET_WHITESPACE: 15501 /* 15502 * TODO: 2.5.1.2 List datatypes 15503 * The value of �whiteSpace� is fixed to the value collapse. 15504 */ 15505 case XML_SCHEMA_FACET_PATTERN: 15506 case XML_SCHEMA_FACET_ENUMERATION: 15507 break; 15508 default: { 15509 xmlSchemaPIllegalFacetListUnionErr(pctxt, 15510 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4, 15511 type, facet); 15512 /* 15513 * We could return, but it's nicer to report all 15514 * invalid facets. 15515 */ 15516 ok = 0; 15517 } 15518 } 15519 facet = facet->next; 15520 } while (facet != NULL); 15521 if (ok == 0) 15522 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4); 15523 /* 15524 * SPEC (2.3.2.5) (same as 1.3.2) 15525 * 15526 * NOTE (2.3.2.5) This is currently done in 15527 * xmlSchemaDeriveAndValidateFacets() 15528 */ 15529 } 15530 } 15531 } else if (WXS_IS_UNION(type)) { 15532 /* 15533 * 3.1 The {member type definitions} must all have {variety} of 15534 * atomic or list. 15535 */ 15536 xmlSchemaTypeLinkPtr member; 15537 15538 member = type->memberTypes; 15539 while (member != NULL) { 15540 if (WXS_IS_TYPE_NOT_FIXED(member->type)) 15541 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt); 15542 15543 if ((! WXS_IS_ATOMIC(member->type)) && 15544 (! WXS_IS_LIST(member->type))) { 15545 xmlSchemaPCustomErr(pctxt, 15546 XML_SCHEMAP_COS_ST_RESTRICTS_3_1, 15547 WXS_BASIC_CAST type, NULL, 15548 "The member type '%s' is neither an atomic, nor a list type", 15549 xmlSchemaGetComponentQName(&str, member->type)); 15550 FREE_AND_NULL(str) 15551 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1); 15552 } 15553 member = member->next; 15554 } 15555 /* 15556 * 3.3.1 If the {base type definition} is the �simple ur-type 15557 * definition� 15558 */ 15559 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) { 15560 /* 15561 * 3.3.1.1 All of the {member type definitions} must have a 15562 * {final} which does not contain union. 15563 */ 15564 member = type->memberTypes; 15565 while (member != NULL) { 15566 if (xmlSchemaTypeFinalContains(member->type, 15567 XML_SCHEMAS_TYPE_FINAL_UNION)) { 15568 xmlSchemaPCustomErr(pctxt, 15569 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1, 15570 WXS_BASIC_CAST type, NULL, 15571 "The 'final' of member type '%s' contains 'union'", 15572 xmlSchemaGetComponentQName(&str, member->type)); 15573 FREE_AND_NULL(str) 15574 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1); 15575 } 15576 member = member->next; 15577 } 15578 /* 15579 * 3.3.1.2 The {facets} must be empty. 15580 */ 15581 if (type->facetSet != NULL) { 15582 xmlSchemaPCustomErr(pctxt, 15583 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2, 15584 WXS_BASIC_CAST type, NULL, 15585 "No facets allowed", NULL); 15586 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2); 15587 } 15588 } else { 15589 /* 15590 * 3.3.2.1 The {base type definition} must have a {variety} of union. 15591 * I.e. the variety of "list" is inherited. 15592 */ 15593 if (! WXS_IS_UNION(type->baseType)) { 15594 xmlSchemaPCustomErr(pctxt, 15595 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1, 15596 WXS_BASIC_CAST type, NULL, 15597 "The base type '%s' is not a union type", 15598 xmlSchemaGetComponentQName(&str, type->baseType)); 15599 FREE_AND_NULL(str) 15600 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1); 15601 } 15602 /* 15603 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction. 15604 */ 15605 if (xmlSchemaTypeFinalContains(type->baseType, 15606 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { 15607 xmlSchemaPCustomErr(pctxt, 15608 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2, 15609 WXS_BASIC_CAST type, NULL, 15610 "The 'final' of its base type '%s' must not contain 'restriction'", 15611 xmlSchemaGetComponentQName(&str, type->baseType)); 15612 FREE_AND_NULL(str) 15613 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2); 15614 } 15615 /* 15616 * 3.3.2.3 The {member type definitions}, in order, must be validly 15617 * derived from the corresponding type definitions in the {base 15618 * type definition}'s {member type definitions} given the empty set, 15619 * as defined in Type Derivation OK (Simple) (�3.14.6). 15620 */ 15621 { 15622 xmlSchemaTypeLinkPtr baseMember; 15623 15624 /* 15625 * OPTIMIZE: if the type is restricting, it has no local defined 15626 * member types and inherits the member types of the base type; 15627 * thus a check for equality can be skipped. 15628 */ 15629 /* 15630 * Even worse: I cannot see a scenario where a restricting 15631 * union simple type can have other member types as the member 15632 * types of it's base type. This check seems not necessary with 15633 * respect to the derivation process in libxml2. 15634 * But necessary if constructing types with an API. 15635 */ 15636 if (type->memberTypes != NULL) { 15637 member = type->memberTypes; 15638 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType); 15639 if ((member == NULL) && (baseMember != NULL)) { 15640 PERROR_INT("xmlSchemaCheckCOSSTRestricts", 15641 "different number of member types in base"); 15642 } 15643 while (member != NULL) { 15644 if (baseMember == NULL) { 15645 PERROR_INT("xmlSchemaCheckCOSSTRestricts", 15646 "different number of member types in base"); 15647 } else if ((member->type != baseMember->type) && 15648 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, 15649 member->type, baseMember->type, 0) != 0)) { 15650 xmlChar *strBMT = NULL, *strBT = NULL; 15651 15652 xmlSchemaPCustomErrExt(pctxt, 15653 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3, 15654 WXS_BASIC_CAST type, NULL, 15655 "The member type %s is not validly " 15656 "derived from its corresponding member " 15657 "type %s of the base type %s", 15658 xmlSchemaGetComponentQName(&str, member->type), 15659 xmlSchemaGetComponentQName(&strBMT, baseMember->type), 15660 xmlSchemaGetComponentQName(&strBT, type->baseType)); 15661 FREE_AND_NULL(str) 15662 FREE_AND_NULL(strBMT) 15663 FREE_AND_NULL(strBT) 15664 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3); 15665 } 15666 member = member->next; 15667 if (baseMember != NULL) 15668 baseMember = baseMember->next; 15669 } 15670 } 15671 } 15672 /* 15673 * 3.3.2.4 Only pattern and enumeration facet components are 15674 * allowed among the {facets}. 15675 */ 15676 if (type->facets != NULL) { 15677 xmlSchemaFacetPtr facet; 15678 int ok = 1; 15679 15680 facet = type->facets; 15681 do { 15682 if ((facet->type != XML_SCHEMA_FACET_PATTERN) && 15683 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) { 15684 xmlSchemaPIllegalFacetListUnionErr(pctxt, 15685 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4, 15686 type, facet); 15687 ok = 0; 15688 } 15689 facet = facet->next; 15690 } while (facet != NULL); 15691 if (ok == 0) 15692 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4); 15693 15694 } 15695 /* 15696 * SPEC (3.3.2.5) (same as 1.3.2) 15697 * 15698 * NOTE (3.3.2.5) This is currently done in 15699 * xmlSchemaDeriveAndValidateFacets() 15700 */ 15701 } 15702 } 15703 15704 return (0); 15705} 15706 15707/** 15708 * xmlSchemaCheckSRCSimpleType: 15709 * @ctxt: the schema parser context 15710 * @type: the simple type definition 15711 * 15712 * Checks crc-simple-type constraints. 15713 * 15714 * Returns 0 if the constraints are satisfied, 15715 * if not a positive error code and -1 on internal 15716 * errors. 15717 */ 15718#if 0 15719static int 15720xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt, 15721 xmlSchemaTypePtr type) 15722{ 15723 /* 15724 * src-simple-type.1 The corresponding simple type definition, if any, 15725 * must satisfy the conditions set out in Constraints on Simple Type 15726 * Definition Schema Components (�3.14.6). 15727 */ 15728 if (WXS_IS_RESTRICTION(type)) { 15729 /* 15730 * src-simple-type.2 "If the <restriction> alternative is chosen, 15731 * either it must have a base [attribute] or a <simpleType> among its 15732 * [children], but not both." 15733 * NOTE: This is checked in the parse function of <restriction>. 15734 */ 15735 /* 15736 * 15737 */ 15738 } else if (WXS_IS_LIST(type)) { 15739 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have 15740 * an itemType [attribute] or a <simpleType> among its [children], 15741 * but not both." 15742 * 15743 * NOTE: This is checked in the parse function of <list>. 15744 */ 15745 } else if (WXS_IS_UNION(type)) { 15746 /* 15747 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular(). 15748 */ 15749 } 15750 return (0); 15751} 15752#endif 15753 15754static int 15755xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt) 15756{ 15757 if (ctxt->vctxt == NULL) { 15758 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL); 15759 if (ctxt->vctxt == NULL) { 15760 xmlSchemaPErr(ctxt, NULL, 15761 XML_SCHEMAP_INTERNAL, 15762 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, " 15763 "failed to create a temp. validation context.\n", 15764 NULL, NULL); 15765 return (-1); 15766 } 15767 /* TODO: Pass user data. */ 15768 xmlSchemaSetValidErrors(ctxt->vctxt, 15769 ctxt->error, ctxt->warning, ctxt->errCtxt); 15770 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, 15771 ctxt->serror, ctxt->errCtxt); 15772 } 15773 return (0); 15774} 15775 15776static int 15777xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt, 15778 xmlNodePtr node, 15779 xmlSchemaTypePtr type, 15780 const xmlChar *value, 15781 xmlSchemaValPtr *retVal, 15782 int fireErrors, 15783 int normalize, 15784 int isNormalized); 15785 15786/** 15787 * xmlSchemaParseCheckCOSValidDefault: 15788 * @pctxt: the schema parser context 15789 * @type: the simple type definition 15790 * @value: the default value 15791 * @node: an optional node (the holder of the value) 15792 * 15793 * Schema Component Constraint: Element Default Valid (Immediate) 15794 * (cos-valid-default) 15795 * This will be used by the parser only. For the validator there's 15796 * an other version. 15797 * 15798 * Returns 0 if the constraints are satisfied, 15799 * if not, a positive error code and -1 on internal 15800 * errors. 15801 */ 15802static int 15803xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt, 15804 xmlNodePtr node, 15805 xmlSchemaTypePtr type, 15806 const xmlChar *value, 15807 xmlSchemaValPtr *val) 15808{ 15809 int ret = 0; 15810 15811 /* 15812 * cos-valid-default: 15813 * Schema Component Constraint: Element Default Valid (Immediate) 15814 * For a string to be a valid default with respect to a type 15815 * definition the appropriate case among the following must be true: 15816 */ 15817 if WXS_IS_COMPLEX(type) { 15818 /* 15819 * Complex type. 15820 * 15821 * SPEC (2.1) "its {content type} must be a simple type definition 15822 * or mixed." 15823 * SPEC (2.2.2) "If the {content type} is mixed, then the {content 15824 * type}'s particle must be �emptiable� as defined by 15825 * Particle Emptiable (�3.9.6)." 15826 */ 15827 if ((! WXS_HAS_SIMPLE_CONTENT(type)) && 15828 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) { 15829 /* NOTE that this covers (2.2.2) as well. */ 15830 xmlSchemaPCustomErr(pctxt, 15831 XML_SCHEMAP_COS_VALID_DEFAULT_2_1, 15832 WXS_BASIC_CAST type, type->node, 15833 "For a string to be a valid default, the type definition " 15834 "must be a simple type or a complex type with mixed content " 15835 "and a particle emptiable", NULL); 15836 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1); 15837 } 15838 } 15839 /* 15840 * 1 If the type definition is a simple type definition, then the string 15841 * must be �valid� with respect to that definition as defined by String 15842 * Valid (�3.14.4). 15843 * 15844 * AND 15845 * 15846 * 2.2.1 If the {content type} is a simple type definition, then the 15847 * string must be �valid� with respect to that simple type definition 15848 * as defined by String Valid (�3.14.4). 15849 */ 15850 if (WXS_IS_SIMPLE(type)) 15851 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node, 15852 type, value, val, 1, 1, 0); 15853 else if (WXS_HAS_SIMPLE_CONTENT(type)) 15854 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node, 15855 type->contentTypeDef, value, val, 1, 1, 0); 15856 else 15857 return (ret); 15858 15859 if (ret < 0) { 15860 PERROR_INT("xmlSchemaParseCheckCOSValidDefault", 15861 "calling xmlSchemaVCheckCVCSimpleType()"); 15862 } 15863 15864 return (ret); 15865} 15866 15867/** 15868 * xmlSchemaCheckCTPropsCorrect: 15869 * @ctxt: the schema parser context 15870 * @type: the complex type definition 15871 * 15872 *.(4.6) Constraints on Complex Type Definition Schema Components 15873 * Schema Component Constraint: 15874 * Complex Type Definition Properties Correct (ct-props-correct) 15875 * STATUS: (seems) complete 15876 * 15877 * Returns 0 if the constraints are satisfied, a positive 15878 * error code if not and -1 if an internal error occured. 15879 */ 15880static int 15881xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt, 15882 xmlSchemaTypePtr type) 15883{ 15884 /* 15885 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily. 15886 * 15887 * SPEC (1) "The values of the properties of a complex type definition must 15888 * be as described in the property tableau in The Complex Type Definition 15889 * Schema Component (�3.4.1), modulo the impact of Missing 15890 * Sub-components (�5.3)." 15891 */ 15892 if ((type->baseType != NULL) && 15893 (WXS_IS_SIMPLE(type->baseType)) && 15894 (WXS_IS_EXTENSION(type) == 0)) { 15895 /* 15896 * SPEC (2) "If the {base type definition} is a simple type definition, 15897 * the {derivation method} must be extension." 15898 */ 15899 xmlSchemaCustomErr(ACTXT_CAST pctxt, 15900 XML_SCHEMAP_SRC_CT_1, 15901 NULL, WXS_BASIC_CAST type, 15902 "If the base type is a simple type, the derivation method must be " 15903 "'extension'", NULL, NULL); 15904 return (XML_SCHEMAP_SRC_CT_1); 15905 } 15906 /* 15907 * SPEC (3) "Circular definitions are disallowed, except for the �ur-type 15908 * definition�. That is, it must be possible to reach the �ur-type 15909 * definition by repeatedly following the {base type definition}." 15910 * 15911 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular(). 15912 */ 15913 /* 15914 * NOTE that (4) and (5) need the following: 15915 * - attribute uses need to be already inherited (apply attr. prohibitions) 15916 * - attribute group references need to be expanded already 15917 * - simple types need to be typefixed already 15918 */ 15919 if (type->attrUses && 15920 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1)) 15921 { 15922 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses; 15923 xmlSchemaAttributeUsePtr use, tmp; 15924 int i, j, hasId = 0; 15925 15926 for (i = uses->nbItems -1; i >= 0; i--) { 15927 use = uses->items[i]; 15928 15929 /* 15930 * SPEC ct-props-correct 15931 * (4) "Two distinct attribute declarations in the 15932 * {attribute uses} must not have identical {name}s and 15933 * {target namespace}s." 15934 */ 15935 if (i > 0) { 15936 for (j = i -1; j >= 0; j--) { 15937 tmp = uses->items[j]; 15938 if ((WXS_ATTRUSE_DECL_NAME(use) == 15939 WXS_ATTRUSE_DECL_NAME(tmp)) && 15940 (WXS_ATTRUSE_DECL_TNS(use) == 15941 WXS_ATTRUSE_DECL_TNS(tmp))) 15942 { 15943 xmlChar *str = NULL; 15944 15945 xmlSchemaCustomErr(ACTXT_CAST pctxt, 15946 XML_SCHEMAP_AG_PROPS_CORRECT, 15947 NULL, WXS_BASIC_CAST type, 15948 "Duplicate %s", 15949 xmlSchemaGetComponentDesignation(&str, use), 15950 NULL); 15951 FREE_AND_NULL(str); 15952 /* 15953 * Remove the duplicate. 15954 */ 15955 if (xmlSchemaItemListRemove(uses, i) == -1) 15956 goto exit_failure; 15957 goto next_use; 15958 } 15959 } 15960 } 15961 /* 15962 * SPEC ct-props-correct 15963 * (5) "Two distinct attribute declarations in the 15964 * {attribute uses} must not have {type definition}s which 15965 * are or are derived from ID." 15966 */ 15967 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) { 15968 if (xmlSchemaIsDerivedFromBuiltInType( 15969 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID)) 15970 { 15971 if (hasId) { 15972 xmlChar *str = NULL; 15973 15974 xmlSchemaCustomErr(ACTXT_CAST pctxt, 15975 XML_SCHEMAP_AG_PROPS_CORRECT, 15976 NULL, WXS_BASIC_CAST type, 15977 "There must not exist more than one attribute " 15978 "declaration of type 'xs:ID' " 15979 "(or derived from 'xs:ID'). The %s violates this " 15980 "constraint", 15981 xmlSchemaGetComponentDesignation(&str, use), 15982 NULL); 15983 FREE_AND_NULL(str); 15984 if (xmlSchemaItemListRemove(uses, i) == -1) 15985 goto exit_failure; 15986 } 15987 15988 hasId = 1; 15989 } 15990 } 15991next_use: {} 15992 } 15993 } 15994 return (0); 15995exit_failure: 15996 return(-1); 15997} 15998 15999static int 16000xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA, 16001 xmlSchemaTypePtr typeB) 16002{ 16003 /* 16004 * TODO: This should implement component-identity 16005 * in the future. 16006 */ 16007 if ((typeA == NULL) || (typeB == NULL)) 16008 return (0); 16009 return (typeA == typeB); 16010} 16011 16012/** 16013 * xmlSchemaCheckCOSCTDerivedOK: 16014 * @ctxt: the schema parser context 16015 * @type: the to-be derived complex type definition 16016 * @baseType: the base complex type definition 16017 * @set: the given set 16018 * 16019 * Schema Component Constraint: 16020 * Type Derivation OK (Complex) (cos-ct-derived-ok) 16021 * 16022 * STATUS: completed 16023 * 16024 * Returns 0 if the constraints are satisfied, or 1 16025 * if not. 16026 */ 16027static int 16028xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt, 16029 xmlSchemaTypePtr type, 16030 xmlSchemaTypePtr baseType, 16031 int set) 16032{ 16033 int equal = xmlSchemaAreEqualTypes(type, baseType); 16034 /* TODO: Error codes. */ 16035 /* 16036 * SPEC "For a complex type definition (call it D, for derived) 16037 * to be validly derived from a type definition (call this 16038 * B, for base) given a subset of {extension, restriction} 16039 * all of the following must be true:" 16040 */ 16041 if (! equal) { 16042 /* 16043 * SPEC (1) "If B and D are not the same type definition, then the 16044 * {derivation method} of D must not be in the subset." 16045 */ 16046 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) || 16047 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type)))) 16048 return (1); 16049 } else { 16050 /* 16051 * SPEC (2.1) "B and D must be the same type definition." 16052 */ 16053 return (0); 16054 } 16055 /* 16056 * SPEC (2.2) "B must be D's {base type definition}." 16057 */ 16058 if (type->baseType == baseType) 16059 return (0); 16060 /* 16061 * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type 16062 * definition�." 16063 */ 16064 if (WXS_IS_ANYTYPE(type->baseType)) 16065 return (1); 16066 16067 if (WXS_IS_COMPLEX(type->baseType)) { 16068 /* 16069 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it 16070 * must be validly derived from B given the subset as defined by this 16071 * constraint." 16072 */ 16073 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType, 16074 baseType, set)); 16075 } else { 16076 /* 16077 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it 16078 * must be validly derived from B given the subset as defined in Type 16079 * Derivation OK (Simple) (�3.14.6). 16080 */ 16081 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType, 16082 baseType, set)); 16083 } 16084} 16085 16086/** 16087 * xmlSchemaCheckCOSDerivedOK: 16088 * @type: the derived simple type definition 16089 * @baseType: the base type definition 16090 * 16091 * Calls: 16092 * Type Derivation OK (Simple) AND Type Derivation OK (Complex) 16093 * 16094 * Checks wheter @type can be validly derived from @baseType. 16095 * 16096 * Returns 0 on success, an positive error code otherwise. 16097 */ 16098static int 16099xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt, 16100 xmlSchemaTypePtr type, 16101 xmlSchemaTypePtr baseType, 16102 int set) 16103{ 16104 if (WXS_IS_SIMPLE(type)) 16105 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set)); 16106 else 16107 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set)); 16108} 16109 16110/** 16111 * xmlSchemaCheckCOSCTExtends: 16112 * @ctxt: the schema parser context 16113 * @type: the complex type definition 16114 * 16115 * (3.4.6) Constraints on Complex Type Definition Schema Components 16116 * Schema Component Constraint: 16117 * Derivation Valid (Extension) (cos-ct-extends) 16118 * 16119 * STATUS: 16120 * missing: 16121 * (1.5) 16122 * (1.4.3.2.2.2) "Particle Valid (Extension)" 16123 * 16124 * Returns 0 if the constraints are satisfied, a positive 16125 * error code if not and -1 if an internal error occured. 16126 */ 16127static int 16128xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt, 16129 xmlSchemaTypePtr type) 16130{ 16131 xmlSchemaTypePtr base = type->baseType; 16132 /* 16133 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used 16134 * temporarily only. 16135 */ 16136 /* 16137 * SPEC (1) "If the {base type definition} is a complex type definition, 16138 * then all of the following must be true:" 16139 */ 16140 if (WXS_IS_COMPLEX(base)) { 16141 /* 16142 * SPEC (1.1) "The {final} of the {base type definition} must not 16143 * contain extension." 16144 */ 16145 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) { 16146 xmlSchemaPCustomErr(ctxt, 16147 XML_SCHEMAP_COS_CT_EXTENDS_1_1, 16148 WXS_BASIC_CAST type, NULL, 16149 "The 'final' of the base type definition " 16150 "contains 'extension'", NULL); 16151 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); 16152 } 16153 16154 /* 16155 * ATTENTION: The constrains (1.2) and (1.3) are not applied, 16156 * since they are automatically satisfied through the 16157 * inheriting mechanism. 16158 * Note that even if redefining components, the inheriting mechanism 16159 * is used. 16160 */ 16161#if 0 16162 /* 16163 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute 16164 * uses} 16165 * of the complex type definition itself, that is, for every attribute 16166 * use in the {attribute uses} of the {base type definition}, there 16167 * must be an attribute use in the {attribute uses} of the complex 16168 * type definition itself whose {attribute declaration} has the same 16169 * {name}, {target namespace} and {type definition} as its attribute 16170 * declaration" 16171 */ 16172 if (base->attrUses != NULL) { 16173 int i, j, found; 16174 xmlSchemaAttributeUsePtr use, buse; 16175 16176 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) { 16177 buse = (WXS_LIST_CAST base->attrUses)->items[i]; 16178 found = 0; 16179 if (type->attrUses != NULL) { 16180 use = (WXS_LIST_CAST type->attrUses)->items[j]; 16181 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++) 16182 { 16183 if ((WXS_ATTRUSE_DECL_NAME(use) == 16184 WXS_ATTRUSE_DECL_NAME(buse)) && 16185 (WXS_ATTRUSE_DECL_TNS(use) == 16186 WXS_ATTRUSE_DECL_TNS(buse)) && 16187 (WXS_ATTRUSE_TYPEDEF(use) == 16188 WXS_ATTRUSE_TYPEDEF(buse)) 16189 { 16190 found = 1; 16191 break; 16192 } 16193 } 16194 } 16195 if (! found) { 16196 xmlChar *str = NULL; 16197 16198 xmlSchemaCustomErr(ACTXT_CAST ctxt, 16199 XML_SCHEMAP_COS_CT_EXTENDS_1_2, 16200 NULL, WXS_BASIC_CAST type, 16201 /* 16202 * TODO: The report does not indicate that also the 16203 * type needs to be the same. 16204 */ 16205 "This type is missing a matching correspondent " 16206 "for its {base type}'s %s in its {attribute uses}", 16207 xmlSchemaGetComponentDesignation(&str, 16208 buse->children), 16209 NULL); 16210 FREE_AND_NULL(str) 16211 } 16212 } 16213 } 16214 /* 16215 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type 16216 * definition must also have one, and the base type definition's 16217 * {attribute wildcard}'s {namespace constraint} must be a subset 16218 * of the complex type definition's {attribute wildcard}'s {namespace 16219 * constraint}, as defined by Wildcard Subset (�3.10.6)." 16220 */ 16221 16222 /* 16223 * MAYBE TODO: Enable if ever needed. But this will be needed only 16224 * if created the type via a schema construction API. 16225 */ 16226 if (base->attributeWildcard != NULL) { 16227 if (type->attributeWilcard == NULL) { 16228 xmlChar *str = NULL; 16229 16230 xmlSchemaCustomErr(ACTXT_CAST pctxt, 16231 XML_SCHEMAP_COS_CT_EXTENDS_1_3, 16232 NULL, type, 16233 "The base %s has an attribute wildcard, " 16234 "but this type is missing an attribute wildcard", 16235 xmlSchemaGetComponentDesignation(&str, base)); 16236 FREE_AND_NULL(str) 16237 16238 } else if (xmlSchemaCheckCOSNSSubset( 16239 base->attributeWildcard, type->attributeWildcard)) 16240 { 16241 xmlChar *str = NULL; 16242 16243 xmlSchemaCustomErr(ACTXT_CAST pctxt, 16244 XML_SCHEMAP_COS_CT_EXTENDS_1_3, 16245 NULL, type, 16246 "The attribute wildcard is not a valid " 16247 "superset of the one in the base %s", 16248 xmlSchemaGetComponentDesignation(&str, base)); 16249 FREE_AND_NULL(str) 16250 } 16251 } 16252#endif 16253 /* 16254 * SPEC (1.4) "One of the following must be true:" 16255 */ 16256 if ((type->contentTypeDef != NULL) && 16257 (type->contentTypeDef == base->contentTypeDef)) { 16258 /* 16259 * SPEC (1.4.1) "The {content type} of the {base type definition} 16260 * and the {content type} of the complex type definition itself 16261 * must be the same simple type definition" 16262 * PASS 16263 */ 16264 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) && 16265 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) { 16266 /* 16267 * SPEC (1.4.2) "The {content type} of both the {base type 16268 * definition} and the complex type definition itself must 16269 * be empty." 16270 * PASS 16271 */ 16272 } else { 16273 /* 16274 * SPEC (1.4.3) "All of the following must be true:" 16275 */ 16276 if (type->subtypes == NULL) { 16277 /* 16278 * SPEC 1.4.3.1 The {content type} of the complex type 16279 * definition itself must specify a particle. 16280 */ 16281 xmlSchemaPCustomErr(ctxt, 16282 XML_SCHEMAP_COS_CT_EXTENDS_1_1, 16283 WXS_BASIC_CAST type, NULL, 16284 "The content type must specify a particle", NULL); 16285 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); 16286 } 16287 /* 16288 * SPEC (1.4.3.2) "One of the following must be true:" 16289 */ 16290 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) { 16291 /* 16292 * SPEC (1.4.3.2.1) "The {content type} of the {base type 16293 * definition} must be empty. 16294 * PASS 16295 */ 16296 } else { 16297 /* 16298 * SPEC (1.4.3.2.2) "All of the following must be true:" 16299 */ 16300 if ((type->contentType != base->contentType) || 16301 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) && 16302 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) { 16303 /* 16304 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed 16305 * or both must be element-only." 16306 */ 16307 xmlSchemaPCustomErr(ctxt, 16308 XML_SCHEMAP_COS_CT_EXTENDS_1_1, 16309 WXS_BASIC_CAST type, NULL, 16310 "The content type of both, the type and its base " 16311 "type, must either 'mixed' or 'element-only'", NULL); 16312 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); 16313 } 16314 /* 16315 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the 16316 * complex type definition must be a �valid extension� 16317 * of the {base type definition}'s particle, as defined 16318 * in Particle Valid (Extension) (�3.9.6)." 16319 * 16320 * NOTE that we won't check "Particle Valid (Extension)", 16321 * since it is ensured by the derivation process in 16322 * xmlSchemaTypeFixup(). We need to implement this when heading 16323 * for a construction API 16324 * TODO: !! This is needed to be checked if redefining a type !! 16325 */ 16326 } 16327 /* 16328 * URGENT TODO (1.5) 16329 */ 16330 } 16331 } else { 16332 /* 16333 * SPEC (2) "If the {base type definition} is a simple type definition, 16334 * then all of the following must be true:" 16335 */ 16336 if (type->contentTypeDef != base) { 16337 /* 16338 * SPEC (2.1) "The {content type} must be the same simple type 16339 * definition." 16340 */ 16341 xmlSchemaPCustomErr(ctxt, 16342 XML_SCHEMAP_COS_CT_EXTENDS_1_1, 16343 WXS_BASIC_CAST type, NULL, 16344 "The content type must be the simple base type", NULL); 16345 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); 16346 } 16347 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) { 16348 /* 16349 * SPEC (2.2) "The {final} of the {base type definition} must not 16350 * contain extension" 16351 * NOTE that this is the same as (1.1). 16352 */ 16353 xmlSchemaPCustomErr(ctxt, 16354 XML_SCHEMAP_COS_CT_EXTENDS_1_1, 16355 WXS_BASIC_CAST type, NULL, 16356 "The 'final' of the base type definition " 16357 "contains 'extension'", NULL); 16358 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); 16359 } 16360 } 16361 return (0); 16362} 16363 16364/** 16365 * xmlSchemaCheckDerivationOKRestriction: 16366 * @ctxt: the schema parser context 16367 * @type: the complex type definition 16368 * 16369 * (3.4.6) Constraints on Complex Type Definition Schema Components 16370 * Schema Component Constraint: 16371 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction) 16372 * 16373 * STATUS: 16374 * missing: 16375 * (5.4.2) ??? 16376 * 16377 * ATTENTION: 16378 * In XML Schema 1.1 this will be: 16379 * Validation Rule: Checking complex type subsumption 16380 * 16381 * Returns 0 if the constraints are satisfied, a positive 16382 * error code if not and -1 if an internal error occured. 16383 */ 16384static int 16385xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt, 16386 xmlSchemaTypePtr type) 16387{ 16388 xmlSchemaTypePtr base; 16389 16390 /* 16391 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used 16392 * temporarily only. 16393 */ 16394 base = type->baseType; 16395 if (! WXS_IS_COMPLEX(base)) { 16396 xmlSchemaCustomErr(ACTXT_CAST ctxt, 16397 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, 16398 type->node, WXS_BASIC_CAST type, 16399 "The base type must be a complex type", NULL, NULL); 16400 return(ctxt->err); 16401 } 16402 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) { 16403 /* 16404 * SPEC (1) "The {base type definition} must be a complex type 16405 * definition whose {final} does not contain restriction." 16406 */ 16407 xmlSchemaCustomErr(ACTXT_CAST ctxt, 16408 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, 16409 type->node, WXS_BASIC_CAST type, 16410 "The 'final' of the base type definition " 16411 "contains 'restriction'", NULL, NULL); 16412 return (ctxt->err); 16413 } 16414 /* 16415 * SPEC (2), (3) and (4) 16416 * Those are handled in a separate function, since the 16417 * same constraints are needed for redefinition of 16418 * attribute groups as well. 16419 */ 16420 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt, 16421 XML_SCHEMA_ACTION_DERIVE, 16422 WXS_BASIC_CAST type, WXS_BASIC_CAST base, 16423 type->attrUses, base->attrUses, 16424 type->attributeWildcard, 16425 base->attributeWildcard) == -1) 16426 { 16427 return(-1); 16428 } 16429 /* 16430 * SPEC (5) "One of the following must be true:" 16431 */ 16432 if (base->builtInType == XML_SCHEMAS_ANYTYPE) { 16433 /* 16434 * SPEC (5.1) "The {base type definition} must be the 16435 * �ur-type definition�." 16436 * PASS 16437 */ 16438 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) || 16439 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) { 16440 /* 16441 * SPEC (5.2.1) "The {content type} of the complex type definition 16442 * must be a simple type definition" 16443 * 16444 * SPEC (5.2.2) "One of the following must be true:" 16445 */ 16446 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) || 16447 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) 16448 { 16449 int err; 16450 /* 16451 * SPEC (5.2.2.1) "The {content type} of the {base type 16452 * definition} must be a simple type definition from which 16453 * the {content type} is validly derived given the empty 16454 * set as defined in Type Derivation OK (Simple) (�3.14.6)." 16455 * 16456 * ATTENTION TODO: This seems not needed if the type implicitely 16457 * derived from the base type. 16458 * 16459 */ 16460 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt, 16461 type->contentTypeDef, base->contentTypeDef, 0); 16462 if (err != 0) { 16463 xmlChar *strA = NULL, *strB = NULL; 16464 16465 if (err == -1) 16466 return(-1); 16467 xmlSchemaCustomErr(ACTXT_CAST ctxt, 16468 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, 16469 NULL, WXS_BASIC_CAST type, 16470 "The {content type} %s is not validly derived from the " 16471 "base type's {content type} %s", 16472 xmlSchemaGetComponentDesignation(&strA, 16473 type->contentTypeDef), 16474 xmlSchemaGetComponentDesignation(&strB, 16475 base->contentTypeDef)); 16476 FREE_AND_NULL(strA); 16477 FREE_AND_NULL(strB); 16478 return(ctxt->err); 16479 } 16480 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) && 16481 (xmlSchemaIsParticleEmptiable( 16482 (xmlSchemaParticlePtr) base->subtypes))) { 16483 /* 16484 * SPEC (5.2.2.2) "The {base type definition} must be mixed 16485 * and have a particle which is �emptiable� as defined in 16486 * Particle Emptiable (�3.9.6)." 16487 * PASS 16488 */ 16489 } else { 16490 xmlSchemaPCustomErr(ctxt, 16491 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, 16492 WXS_BASIC_CAST type, NULL, 16493 "The content type of the base type must be either " 16494 "a simple type or 'mixed' and an emptiable particle", NULL); 16495 return (ctxt->err); 16496 } 16497 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) { 16498 /* 16499 * SPEC (5.3.1) "The {content type} of the complex type itself must 16500 * be empty" 16501 */ 16502 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) { 16503 /* 16504 * SPEC (5.3.2.1) "The {content type} of the {base type 16505 * definition} must also be empty." 16506 * PASS 16507 */ 16508 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) || 16509 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) && 16510 xmlSchemaIsParticleEmptiable( 16511 (xmlSchemaParticlePtr) base->subtypes)) { 16512 /* 16513 * SPEC (5.3.2.2) "The {content type} of the {base type 16514 * definition} must be elementOnly or mixed and have a particle 16515 * which is �emptiable� as defined in Particle Emptiable (�3.9.6)." 16516 * PASS 16517 */ 16518 } else { 16519 xmlSchemaPCustomErr(ctxt, 16520 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, 16521 WXS_BASIC_CAST type, NULL, 16522 "The content type of the base type must be either " 16523 "empty or 'mixed' (or 'elements-only') and an emptiable " 16524 "particle", NULL); 16525 return (ctxt->err); 16526 } 16527 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) || 16528 WXS_HAS_MIXED_CONTENT(type)) { 16529 /* 16530 * SPEC (5.4.1.1) "The {content type} of the complex type definition 16531 * itself must be element-only" 16532 */ 16533 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) { 16534 /* 16535 * SPEC (5.4.1.2) "The {content type} of the complex type 16536 * definition itself and of the {base type definition} must be 16537 * mixed" 16538 */ 16539 xmlSchemaPCustomErr(ctxt, 16540 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, 16541 WXS_BASIC_CAST type, NULL, 16542 "If the content type is 'mixed', then the content type of the " 16543 "base type must also be 'mixed'", NULL); 16544 return (ctxt->err); 16545 } 16546 /* 16547 * SPEC (5.4.2) "The particle of the complex type definition itself 16548 * must be a �valid restriction� of the particle of the {content 16549 * type} of the {base type definition} as defined in Particle Valid 16550 * (Restriction) (�3.9.6). 16551 * 16552 * URGENT TODO: (5.4.2) 16553 */ 16554 } else { 16555 xmlSchemaPCustomErr(ctxt, 16556 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, 16557 WXS_BASIC_CAST type, NULL, 16558 "The type is not a valid restriction of its base type", NULL); 16559 return (ctxt->err); 16560 } 16561 return (0); 16562} 16563 16564/** 16565 * xmlSchemaCheckCTComponent: 16566 * @ctxt: the schema parser context 16567 * @type: the complex type definition 16568 * 16569 * (3.4.6) Constraints on Complex Type Definition Schema Components 16570 * 16571 * Returns 0 if the constraints are satisfied, a positive 16572 * error code if not and -1 if an internal error occured. 16573 */ 16574static int 16575xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt, 16576 xmlSchemaTypePtr type) 16577{ 16578 int ret; 16579 /* 16580 * Complex Type Definition Properties Correct 16581 */ 16582 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type); 16583 if (ret != 0) 16584 return (ret); 16585 if (WXS_IS_EXTENSION(type)) 16586 ret = xmlSchemaCheckCOSCTExtends(ctxt, type); 16587 else 16588 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type); 16589 return (ret); 16590} 16591 16592/** 16593 * xmlSchemaCheckSRCCT: 16594 * @ctxt: the schema parser context 16595 * @type: the complex type definition 16596 * 16597 * (3.4.3) Constraints on XML Representations of Complex Type Definitions: 16598 * Schema Representation Constraint: 16599 * Complex Type Definition Representation OK (src-ct) 16600 * 16601 * Returns 0 if the constraints are satisfied, a positive 16602 * error code if not and -1 if an internal error occured. 16603 */ 16604static int 16605xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt, 16606 xmlSchemaTypePtr type) 16607{ 16608 xmlSchemaTypePtr base; 16609 int ret = 0; 16610 16611 /* 16612 * TODO: Adjust the error codes here, as I used 16613 * XML_SCHEMAP_SRC_CT_1 only yet. 16614 */ 16615 base = type->baseType; 16616 if (! WXS_HAS_SIMPLE_CONTENT(type)) { 16617 /* 16618 * 1 If the <complexContent> alternative is chosen, the type definition 16619 * �resolved� to by the �actual value� of the base [attribute] 16620 * must be a complex type definition; 16621 */ 16622 if (! WXS_IS_COMPLEX(base)) { 16623 xmlChar *str = NULL; 16624 xmlSchemaPCustomErr(ctxt, 16625 XML_SCHEMAP_SRC_CT_1, 16626 WXS_BASIC_CAST type, type->node, 16627 "If using <complexContent>, the base type is expected to be " 16628 "a complex type. The base type '%s' is a simple type", 16629 xmlSchemaFormatQName(&str, base->targetNamespace, 16630 base->name)); 16631 FREE_AND_NULL(str) 16632 return (XML_SCHEMAP_SRC_CT_1); 16633 } 16634 } else { 16635 /* 16636 * SPEC 16637 * 2 If the <simpleContent> alternative is chosen, all of the 16638 * following must be true: 16639 * 2.1 The type definition �resolved� to by the �actual value� of the 16640 * base [attribute] must be one of the following: 16641 */ 16642 if (WXS_IS_SIMPLE(base)) { 16643 if (WXS_IS_EXTENSION(type) == 0) { 16644 xmlChar *str = NULL; 16645 /* 16646 * 2.1.3 only if the <extension> alternative is also 16647 * chosen, a simple type definition. 16648 */ 16649 /* TODO: Change error code to ..._SRC_CT_2_1_3. */ 16650 xmlSchemaPCustomErr(ctxt, 16651 XML_SCHEMAP_SRC_CT_1, 16652 WXS_BASIC_CAST type, NULL, 16653 "If using <simpleContent> and <restriction>, the base " 16654 "type must be a complex type. The base type '%s' is " 16655 "a simple type", 16656 xmlSchemaFormatQName(&str, base->targetNamespace, 16657 base->name)); 16658 FREE_AND_NULL(str) 16659 return (XML_SCHEMAP_SRC_CT_1); 16660 } 16661 } else { 16662 /* Base type is a complex type. */ 16663 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) || 16664 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) { 16665 /* 16666 * 2.1.1 a complex type definition whose {content type} is a 16667 * simple type definition; 16668 * PASS 16669 */ 16670 if (base->contentTypeDef == NULL) { 16671 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, 16672 WXS_BASIC_CAST type, NULL, 16673 "Internal error: xmlSchemaCheckSRCCT, " 16674 "'%s', base type has no content type", 16675 type->name); 16676 return (-1); 16677 } 16678 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) && 16679 (WXS_IS_RESTRICTION(type))) { 16680 16681 /* 16682 * 2.1.2 only if the <restriction> alternative is also 16683 * chosen, a complex type definition whose {content type} 16684 * is mixed and a particle emptiable. 16685 */ 16686 if (! xmlSchemaIsParticleEmptiable( 16687 (xmlSchemaParticlePtr) base->subtypes)) { 16688 ret = XML_SCHEMAP_SRC_CT_1; 16689 } else 16690 /* 16691 * Attention: at this point the <simpleType> child is in 16692 * ->contentTypeDef (put there during parsing). 16693 */ 16694 if (type->contentTypeDef == NULL) { 16695 xmlChar *str = NULL; 16696 /* 16697 * 2.2 If clause 2.1.2 above is satisfied, then there 16698 * must be a <simpleType> among the [children] of 16699 * <restriction>. 16700 */ 16701 /* TODO: Change error code to ..._SRC_CT_2_2. */ 16702 xmlSchemaPCustomErr(ctxt, 16703 XML_SCHEMAP_SRC_CT_1, 16704 WXS_BASIC_CAST type, NULL, 16705 "A <simpleType> is expected among the children " 16706 "of <restriction>, if <simpleContent> is used and " 16707 "the base type '%s' is a complex type", 16708 xmlSchemaFormatQName(&str, base->targetNamespace, 16709 base->name)); 16710 FREE_AND_NULL(str) 16711 return (XML_SCHEMAP_SRC_CT_1); 16712 } 16713 } else { 16714 ret = XML_SCHEMAP_SRC_CT_1; 16715 } 16716 } 16717 if (ret > 0) { 16718 xmlChar *str = NULL; 16719 if (WXS_IS_RESTRICTION(type)) { 16720 xmlSchemaPCustomErr(ctxt, 16721 XML_SCHEMAP_SRC_CT_1, 16722 WXS_BASIC_CAST type, NULL, 16723 "If <simpleContent> and <restriction> is used, the " 16724 "base type must be a simple type or a complex type with " 16725 "mixed content and particle emptiable. The base type " 16726 "'%s' is none of those", 16727 xmlSchemaFormatQName(&str, base->targetNamespace, 16728 base->name)); 16729 } else { 16730 xmlSchemaPCustomErr(ctxt, 16731 XML_SCHEMAP_SRC_CT_1, 16732 WXS_BASIC_CAST type, NULL, 16733 "If <simpleContent> and <extension> is used, the " 16734 "base type must be a simple type. The base type '%s' " 16735 "is a complex type", 16736 xmlSchemaFormatQName(&str, base->targetNamespace, 16737 base->name)); 16738 } 16739 FREE_AND_NULL(str) 16740 } 16741 } 16742 /* 16743 * SPEC (3) "The corresponding complex type definition component must 16744 * satisfy the conditions set out in Constraints on Complex Type 16745 * Definition Schema Components (�3.4.6);" 16746 * NOTE (3) will be done in xmlSchemaTypeFixup(). 16747 */ 16748 /* 16749 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification 16750 * above for {attribute wildcard} is satisfied, the intensional 16751 * intersection must be expressible, as defined in Attribute Wildcard 16752 * Intersection (�3.10.6). 16753 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses(). 16754 */ 16755 return (ret); 16756} 16757 16758#ifdef ENABLE_PARTICLE_RESTRICTION 16759/** 16760 * xmlSchemaCheckParticleRangeOK: 16761 * @ctxt: the schema parser context 16762 * @type: the complex type definition 16763 * 16764 * (3.9.6) Constraints on Particle Schema Components 16765 * Schema Component Constraint: 16766 * Occurrence Range OK (range-ok) 16767 * 16768 * STATUS: complete 16769 * 16770 * Returns 0 if the constraints are satisfied, a positive 16771 * error code if not and -1 if an internal error occured. 16772 */ 16773static int 16774xmlSchemaCheckParticleRangeOK(int rmin, int rmax, 16775 int bmin, int bmax) 16776{ 16777 if (rmin < bmin) 16778 return (1); 16779 if ((bmax != UNBOUNDED) && 16780 (rmax > bmax)) 16781 return (1); 16782 return (0); 16783} 16784 16785/** 16786 * xmlSchemaCheckRCaseNameAndTypeOK: 16787 * @ctxt: the schema parser context 16788 * @r: the restricting element declaration particle 16789 * @b: the base element declaration particle 16790 * 16791 * (3.9.6) Constraints on Particle Schema Components 16792 * Schema Component Constraint: 16793 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK) 16794 * (rcase-NameAndTypeOK) 16795 * 16796 * STATUS: 16797 * MISSING (3.2.3) 16798 * CLARIFY: (3.2.2) 16799 * 16800 * Returns 0 if the constraints are satisfied, a positive 16801 * error code if not and -1 if an internal error occured. 16802 */ 16803static int 16804xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt, 16805 xmlSchemaParticlePtr r, 16806 xmlSchemaParticlePtr b) 16807{ 16808 xmlSchemaElementPtr elemR, elemB; 16809 16810 /* TODO: Error codes (rcase-NameAndTypeOK). */ 16811 elemR = (xmlSchemaElementPtr) r->children; 16812 elemB = (xmlSchemaElementPtr) b->children; 16813 /* 16814 * SPEC (1) "The declarations' {name}s and {target namespace}s are 16815 * the same." 16816 */ 16817 if ((elemR != elemB) && 16818 ((! xmlStrEqual(elemR->name, elemB->name)) || 16819 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace)))) 16820 return (1); 16821 /* 16822 * SPEC (2) "R's occurrence range is a valid restriction of B's 16823 * occurrence range as defined by Occurrence Range OK (�3.9.6)." 16824 */ 16825 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, 16826 b->minOccurs, b->maxOccurs) != 0) 16827 return (1); 16828 /* 16829 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's 16830 * {scope} are global." 16831 */ 16832 if (elemR == elemB) 16833 return (0); 16834 /* 16835 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false." 16836 */ 16837 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) && 16838 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE)) 16839 return (1); 16840 /* 16841 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent, 16842 * or is not fixed, or R's declaration's {value constraint} is fixed 16843 * with the same value." 16844 */ 16845 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) && 16846 ((elemR->value == NULL) || 16847 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) || 16848 /* TODO: Equality of the initial value or normalized or canonical? */ 16849 (! xmlStrEqual(elemR->value, elemB->value)))) 16850 return (1); 16851 /* 16852 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint 16853 * definitions} is a subset of B's declaration's {identity-constraint 16854 * definitions}, if any." 16855 */ 16856 if (elemB->idcs != NULL) { 16857 /* TODO */ 16858 } 16859 /* 16860 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a 16861 * superset of B's declaration's {disallowed substitutions}." 16862 */ 16863 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) && 16864 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) || 16865 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) && 16866 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) || 16867 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) && 16868 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0))) 16869 return (1); 16870 /* 16871 * SPEC (3.2.5) "R's {type definition} is validly derived given 16872 * {extension, list, union} from B's {type definition}" 16873 * 16874 * BADSPEC TODO: What's the point of adding "list" and "union" to the 16875 * set, if the corresponding constraints handle "restriction" and 16876 * "extension" only? 16877 * 16878 */ 16879 { 16880 int set = 0; 16881 16882 set |= SUBSET_EXTENSION; 16883 set |= SUBSET_LIST; 16884 set |= SUBSET_UNION; 16885 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes, 16886 elemB->subtypes, set) != 0) 16887 return (1); 16888 } 16889 return (0); 16890} 16891 16892/** 16893 * xmlSchemaCheckRCaseNSCompat: 16894 * @ctxt: the schema parser context 16895 * @r: the restricting element declaration particle 16896 * @b: the base wildcard particle 16897 * 16898 * (3.9.6) Constraints on Particle Schema Components 16899 * Schema Component Constraint: 16900 * Particle Derivation OK (Elt:Any -- NSCompat) 16901 * (rcase-NSCompat) 16902 * 16903 * STATUS: complete 16904 * 16905 * Returns 0 if the constraints are satisfied, a positive 16906 * error code if not and -1 if an internal error occured. 16907 */ 16908static int 16909xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt, 16910 xmlSchemaParticlePtr r, 16911 xmlSchemaParticlePtr b) 16912{ 16913 /* TODO:Error codes (rcase-NSCompat). */ 16914 /* 16915 * SPEC "For an element declaration particle to be a �valid restriction� 16916 * of a wildcard particle all of the following must be true:" 16917 * 16918 * SPEC (1) "The element declaration's {target namespace} is �valid� 16919 * with respect to the wildcard's {namespace constraint} as defined by 16920 * Wildcard allows Namespace Name (�3.10.4)." 16921 */ 16922 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children, 16923 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0) 16924 return (1); 16925 /* 16926 * SPEC (2) "R's occurrence range is a valid restriction of B's 16927 * occurrence range as defined by Occurrence Range OK (�3.9.6)." 16928 */ 16929 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, 16930 b->minOccurs, b->maxOccurs) != 0) 16931 return (1); 16932 16933 return (0); 16934} 16935 16936/** 16937 * xmlSchemaCheckRCaseRecurseAsIfGroup: 16938 * @ctxt: the schema parser context 16939 * @r: the restricting element declaration particle 16940 * @b: the base model group particle 16941 * 16942 * (3.9.6) Constraints on Particle Schema Components 16943 * Schema Component Constraint: 16944 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup) 16945 * (rcase-RecurseAsIfGroup) 16946 * 16947 * STATUS: TODO 16948 * 16949 * Returns 0 if the constraints are satisfied, a positive 16950 * error code if not and -1 if an internal error occured. 16951 */ 16952static int 16953xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt, 16954 xmlSchemaParticlePtr r, 16955 xmlSchemaParticlePtr b) 16956{ 16957 /* TODO: Error codes (rcase-RecurseAsIfGroup). */ 16958 TODO 16959 return (0); 16960} 16961 16962/** 16963 * xmlSchemaCheckRCaseNSSubset: 16964 * @ctxt: the schema parser context 16965 * @r: the restricting wildcard particle 16966 * @b: the base wildcard particle 16967 * 16968 * (3.9.6) Constraints on Particle Schema Components 16969 * Schema Component Constraint: 16970 * Particle Derivation OK (Any:Any -- NSSubset) 16971 * (rcase-NSSubset) 16972 * 16973 * STATUS: complete 16974 * 16975 * Returns 0 if the constraints are satisfied, a positive 16976 * error code if not and -1 if an internal error occured. 16977 */ 16978static int 16979xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt, 16980 xmlSchemaParticlePtr r, 16981 xmlSchemaParticlePtr b, 16982 int isAnyTypeBase) 16983{ 16984 /* TODO: Error codes (rcase-NSSubset). */ 16985 /* 16986 * SPEC (1) "R's occurrence range is a valid restriction of B's 16987 * occurrence range as defined by Occurrence Range OK (�3.9.6)." 16988 */ 16989 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, 16990 b->minOccurs, b->maxOccurs)) 16991 return (1); 16992 /* 16993 * SPEC (2) "R's {namespace constraint} must be an intensional subset 16994 * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)." 16995 */ 16996 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children, 16997 (xmlSchemaWildcardPtr) b->children)) 16998 return (1); 16999 /* 17000 * SPEC (3) "Unless B is the content model wildcard of the �ur-type 17001 * definition�, R's {process contents} must be identical to or stronger 17002 * than B's {process contents}, where strict is stronger than lax is 17003 * stronger than skip." 17004 */ 17005 if (! isAnyTypeBase) { 17006 if ( ((xmlSchemaWildcardPtr) r->children)->processContents < 17007 ((xmlSchemaWildcardPtr) b->children)->processContents) 17008 return (1); 17009 } 17010 17011 return (0); 17012} 17013 17014/** 17015 * xmlSchemaCheckCOSParticleRestrict: 17016 * @ctxt: the schema parser context 17017 * @type: the complex type definition 17018 * 17019 * (3.9.6) Constraints on Particle Schema Components 17020 * Schema Component Constraint: 17021 * Particle Valid (Restriction) (cos-particle-restrict) 17022 * 17023 * STATUS: TODO 17024 * 17025 * Returns 0 if the constraints are satisfied, a positive 17026 * error code if not and -1 if an internal error occured. 17027 */ 17028static int 17029xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt, 17030 xmlSchemaParticlePtr r, 17031 xmlSchemaParticlePtr b) 17032{ 17033 int ret = 0; 17034 17035 /*part = WXS_TYPE_PARTICLE(type); 17036 basePart = WXS_TYPE_PARTICLE(base); 17037 */ 17038 17039 TODO 17040 17041 /* 17042 * SPEC (1) "They are the same particle." 17043 */ 17044 if (r == b) 17045 return (0); 17046 17047 17048 return (0); 17049} 17050 17051#if 0 17052/** 17053 * xmlSchemaCheckRCaseNSRecurseCheckCardinality: 17054 * @ctxt: the schema parser context 17055 * @r: the model group particle 17056 * @b: the base wildcard particle 17057 * 17058 * (3.9.6) Constraints on Particle Schema Components 17059 * Schema Component Constraint: 17060 * Particle Derivation OK (All/Choice/Sequence:Any -- 17061 * NSRecurseCheckCardinality) 17062 * (rcase-NSRecurseCheckCardinality) 17063 * 17064 * STATUS: TODO: subst-groups 17065 * 17066 * Returns 0 if the constraints are satisfied, a positive 17067 * error code if not and -1 if an internal error occured. 17068 */ 17069static int 17070xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt, 17071 xmlSchemaParticlePtr r, 17072 xmlSchemaParticlePtr b) 17073{ 17074 xmlSchemaParticlePtr part; 17075 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */ 17076 if ((r->children == NULL) || (r->children->children == NULL)) 17077 return (-1); 17078 /* 17079 * SPEC "For a group particle to be a �valid restriction� of a 17080 * wildcard particle..." 17081 * 17082 * SPEC (1) "Every member of the {particles} of the group is a �valid 17083 * restriction� of the wildcard as defined by 17084 * Particle Valid (Restriction) (�3.9.6)." 17085 */ 17086 part = (xmlSchemaParticlePtr) r->children->children; 17087 do { 17088 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b)) 17089 return (1); 17090 part = (xmlSchemaParticlePtr) part->next; 17091 } while (part != NULL); 17092 /* 17093 * SPEC (2) "The effective total range of the group [...] is a 17094 * valid restriction of B's occurrence range as defined by 17095 * Occurrence Range OK (�3.9.6)." 17096 */ 17097 if (xmlSchemaCheckParticleRangeOK( 17098 xmlSchemaGetParticleTotalRangeMin(r), 17099 xmlSchemaGetParticleTotalRangeMax(r), 17100 b->minOccurs, b->maxOccurs) != 0) 17101 return (1); 17102 return (0); 17103} 17104#endif 17105 17106/** 17107 * xmlSchemaCheckRCaseRecurse: 17108 * @ctxt: the schema parser context 17109 * @r: the <all> or <sequence> model group particle 17110 * @b: the base <all> or <sequence> model group particle 17111 * 17112 * (3.9.6) Constraints on Particle Schema Components 17113 * Schema Component Constraint: 17114 * Particle Derivation OK (All:All,Sequence:Sequence -- 17115 Recurse) 17116 * (rcase-Recurse) 17117 * 17118 * STATUS: ? 17119 * TODO: subst-groups 17120 * 17121 * Returns 0 if the constraints are satisfied, a positive 17122 * error code if not and -1 if an internal error occured. 17123 */ 17124static int 17125xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt, 17126 xmlSchemaParticlePtr r, 17127 xmlSchemaParticlePtr b) 17128{ 17129 /* xmlSchemaParticlePtr part; */ 17130 /* TODO: Error codes (rcase-Recurse). */ 17131 if ((r->children == NULL) || (b->children == NULL) || 17132 (r->children->type != b->children->type)) 17133 return (-1); 17134 /* 17135 * SPEC "For an all or sequence group particle to be a �valid 17136 * restriction� of another group particle with the same {compositor}..." 17137 * 17138 * SPEC (1) "R's occurrence range is a valid restriction of B's 17139 * occurrence range as defined by Occurrence Range OK (�3.9.6)." 17140 */ 17141 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, 17142 b->minOccurs, b->maxOccurs)) 17143 return (1); 17144 17145 17146 return (0); 17147} 17148 17149#endif 17150 17151#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \ 17152 xmlSchemaPCustomErrExt(pctxt, \ 17153 XML_SCHEMAP_INVALID_FACET_VALUE, \ 17154 WXS_BASIC_CAST fac1, fac1->node, \ 17155 "It is an error for both '%s' and '%s' to be specified on the "\ 17156 "same type definition", \ 17157 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \ 17158 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL); 17159 17160#define FACET_RESTR_ERR(fac1, msg) \ 17161 xmlSchemaPCustomErr(pctxt, \ 17162 XML_SCHEMAP_INVALID_FACET_VALUE, \ 17163 WXS_BASIC_CAST fac1, fac1->node, \ 17164 msg, NULL); 17165 17166#define FACET_RESTR_FIXED_ERR(fac) \ 17167 xmlSchemaPCustomErr(pctxt, \ 17168 XML_SCHEMAP_INVALID_FACET_VALUE, \ 17169 WXS_BASIC_CAST fac, fac->node, \ 17170 "The base type's facet is 'fixed', thus the value must not " \ 17171 "differ", NULL); 17172 17173static void 17174xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt, 17175 xmlSchemaFacetPtr facet1, 17176 xmlSchemaFacetPtr facet2, 17177 int lessGreater, 17178 int orEqual, 17179 int ofBase) 17180{ 17181 xmlChar *msg = NULL; 17182 17183 msg = xmlStrdup(BAD_CAST "'"); 17184 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type)); 17185 msg = xmlStrcat(msg, BAD_CAST "' has to be"); 17186 if (lessGreater == 0) 17187 msg = xmlStrcat(msg, BAD_CAST " equal to"); 17188 if (lessGreater == 1) 17189 msg = xmlStrcat(msg, BAD_CAST " greater than"); 17190 else 17191 msg = xmlStrcat(msg, BAD_CAST " less than"); 17192 17193 if (orEqual) 17194 msg = xmlStrcat(msg, BAD_CAST " or equal to"); 17195 msg = xmlStrcat(msg, BAD_CAST " '"); 17196 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type)); 17197 if (ofBase) 17198 msg = xmlStrcat(msg, BAD_CAST "' of the base type"); 17199 else 17200 msg = xmlStrcat(msg, BAD_CAST "'"); 17201 17202 xmlSchemaPCustomErr(pctxt, 17203 XML_SCHEMAP_INVALID_FACET_VALUE, 17204 WXS_BASIC_CAST facet1, NULL, 17205 (const char *) msg, NULL); 17206 17207 if (msg != NULL) 17208 xmlFree(msg); 17209} 17210 17211/* 17212* xmlSchemaDeriveAndValidateFacets: 17213* 17214* Schema Component Constraint: Simple Type Restriction (Facets) 17215* (st-restrict-facets) 17216*/ 17217static int 17218xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt, 17219 xmlSchemaTypePtr type) 17220{ 17221 xmlSchemaTypePtr base = type->baseType; 17222 xmlSchemaFacetLinkPtr link, cur, last = NULL; 17223 xmlSchemaFacetPtr facet, bfacet, 17224 flength = NULL, ftotdig = NULL, ffracdig = NULL, 17225 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */ 17226 fmininc = NULL, fmaxinc = NULL, 17227 fminexc = NULL, fmaxexc = NULL, 17228 bflength = NULL, bftotdig = NULL, bffracdig = NULL, 17229 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */ 17230 bfmininc = NULL, bfmaxinc = NULL, 17231 bfminexc = NULL, bfmaxexc = NULL; 17232 int res; /* err = 0, fixedErr; */ 17233 17234 /* 17235 * SPEC st-restrict-facets 1: 17236 * "The {variety} of R is the same as that of B." 17237 */ 17238 /* 17239 * SPEC st-restrict-facets 2: 17240 * "If {variety} is atomic, the {primitive type definition} 17241 * of R is the same as that of B." 17242 * 17243 * NOTE: we leave 1 & 2 out for now, since this will be 17244 * satisfied by the derivation process. 17245 * CONSTRUCTION TODO: Maybe needed if using a construction API. 17246 */ 17247 /* 17248 * SPEC st-restrict-facets 3: 17249 * "The {facets} of R are the union of S and the {facets} 17250 * of B, eliminating duplicates. To eliminate duplicates, 17251 * when a facet of the same kind occurs in both S and the 17252 * {facets} of B, the one in the {facets} of B is not 17253 * included, with the exception of enumeration and pattern 17254 * facets, for which multiple occurrences with distinct values 17255 * are allowed." 17256 */ 17257 17258 if ((type->facetSet == NULL) && (base->facetSet == NULL)) 17259 return (0); 17260 17261 last = type->facetSet; 17262 if (last != NULL) 17263 while (last->next != NULL) 17264 last = last->next; 17265 17266 for (cur = type->facetSet; cur != NULL; cur = cur->next) { 17267 facet = cur->facet; 17268 switch (facet->type) { 17269 case XML_SCHEMA_FACET_LENGTH: 17270 flength = facet; break; 17271 case XML_SCHEMA_FACET_MINLENGTH: 17272 fminlen = facet; break; 17273 case XML_SCHEMA_FACET_MININCLUSIVE: 17274 fmininc = facet; break; 17275 case XML_SCHEMA_FACET_MINEXCLUSIVE: 17276 fminexc = facet; break; 17277 case XML_SCHEMA_FACET_MAXLENGTH: 17278 fmaxlen = facet; break; 17279 case XML_SCHEMA_FACET_MAXINCLUSIVE: 17280 fmaxinc = facet; break; 17281 case XML_SCHEMA_FACET_MAXEXCLUSIVE: 17282 fmaxexc = facet; break; 17283 case XML_SCHEMA_FACET_TOTALDIGITS: 17284 ftotdig = facet; break; 17285 case XML_SCHEMA_FACET_FRACTIONDIGITS: 17286 ffracdig = facet; break; 17287 default: 17288 break; 17289 } 17290 } 17291 for (cur = base->facetSet; cur != NULL; cur = cur->next) { 17292 facet = cur->facet; 17293 switch (facet->type) { 17294 case XML_SCHEMA_FACET_LENGTH: 17295 bflength = facet; break; 17296 case XML_SCHEMA_FACET_MINLENGTH: 17297 bfminlen = facet; break; 17298 case XML_SCHEMA_FACET_MININCLUSIVE: 17299 bfmininc = facet; break; 17300 case XML_SCHEMA_FACET_MINEXCLUSIVE: 17301 bfminexc = facet; break; 17302 case XML_SCHEMA_FACET_MAXLENGTH: 17303 bfmaxlen = facet; break; 17304 case XML_SCHEMA_FACET_MAXINCLUSIVE: 17305 bfmaxinc = facet; break; 17306 case XML_SCHEMA_FACET_MAXEXCLUSIVE: 17307 bfmaxexc = facet; break; 17308 case XML_SCHEMA_FACET_TOTALDIGITS: 17309 bftotdig = facet; break; 17310 case XML_SCHEMA_FACET_FRACTIONDIGITS: 17311 bffracdig = facet; break; 17312 default: 17313 break; 17314 } 17315 } 17316 /* 17317 * length and minLength or maxLength (2.2) + (3.2) 17318 */ 17319 if (flength && (fminlen || fmaxlen)) { 17320 FACET_RESTR_ERR(flength, "It is an error for both 'length' and " 17321 "either of 'minLength' or 'maxLength' to be specified on " 17322 "the same type definition") 17323 } 17324 /* 17325 * Mutual exclusions in the same derivation step. 17326 */ 17327 if ((fmaxinc) && (fmaxexc)) { 17328 /* 17329 * SCC "maxInclusive and maxExclusive" 17330 */ 17331 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc) 17332 } 17333 if ((fmininc) && (fminexc)) { 17334 /* 17335 * SCC "minInclusive and minExclusive" 17336 */ 17337 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc) 17338 } 17339 17340 if (flength && bflength) { 17341 /* 17342 * SCC "length valid restriction" 17343 * The values have to be equal. 17344 */ 17345 res = xmlSchemaCompareValues(flength->val, bflength->val); 17346 if (res == -2) 17347 goto internal_error; 17348 if (res != 0) 17349 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1); 17350 if ((res != 0) && (bflength->fixed)) { 17351 FACET_RESTR_FIXED_ERR(flength) 17352 } 17353 17354 } 17355 if (fminlen && bfminlen) { 17356 /* 17357 * SCC "minLength valid restriction" 17358 * minLength >= BASE minLength 17359 */ 17360 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val); 17361 if (res == -2) 17362 goto internal_error; 17363 if (res == -1) 17364 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1); 17365 if ((res != 0) && (bfminlen->fixed)) { 17366 FACET_RESTR_FIXED_ERR(fminlen) 17367 } 17368 } 17369 if (fmaxlen && bfmaxlen) { 17370 /* 17371 * SCC "maxLength valid restriction" 17372 * maxLength <= BASE minLength 17373 */ 17374 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val); 17375 if (res == -2) 17376 goto internal_error; 17377 if (res == 1) 17378 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1); 17379 if ((res != 0) && (bfmaxlen->fixed)) { 17380 FACET_RESTR_FIXED_ERR(fmaxlen) 17381 } 17382 } 17383 /* 17384 * SCC "length and minLength or maxLength" 17385 */ 17386 if (! flength) 17387 flength = bflength; 17388 if (flength) { 17389 if (! fminlen) 17390 fminlen = bfminlen; 17391 if (fminlen) { 17392 /* (1.1) length >= minLength */ 17393 res = xmlSchemaCompareValues(flength->val, fminlen->val); 17394 if (res == -2) 17395 goto internal_error; 17396 if (res == -1) 17397 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0); 17398 } 17399 if (! fmaxlen) 17400 fmaxlen = bfmaxlen; 17401 if (fmaxlen) { 17402 /* (2.1) length <= maxLength */ 17403 res = xmlSchemaCompareValues(flength->val, fmaxlen->val); 17404 if (res == -2) 17405 goto internal_error; 17406 if (res == 1) 17407 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0); 17408 } 17409 } 17410 if (fmaxinc) { 17411 /* 17412 * "maxInclusive" 17413 */ 17414 if (fmininc) { 17415 /* SCC "maxInclusive >= minInclusive" */ 17416 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val); 17417 if (res == -2) 17418 goto internal_error; 17419 if (res == -1) { 17420 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0); 17421 } 17422 } 17423 /* 17424 * SCC "maxInclusive valid restriction" 17425 */ 17426 if (bfmaxinc) { 17427 /* maxInclusive <= BASE maxInclusive */ 17428 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val); 17429 if (res == -2) 17430 goto internal_error; 17431 if (res == 1) 17432 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1); 17433 if ((res != 0) && (bfmaxinc->fixed)) { 17434 FACET_RESTR_FIXED_ERR(fmaxinc) 17435 } 17436 } 17437 if (bfmaxexc) { 17438 /* maxInclusive < BASE maxExclusive */ 17439 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val); 17440 if (res == -2) 17441 goto internal_error; 17442 if (res != -1) { 17443 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1); 17444 } 17445 } 17446 if (bfmininc) { 17447 /* maxInclusive >= BASE minInclusive */ 17448 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val); 17449 if (res == -2) 17450 goto internal_error; 17451 if (res == -1) { 17452 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1); 17453 } 17454 } 17455 if (bfminexc) { 17456 /* maxInclusive > BASE minExclusive */ 17457 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val); 17458 if (res == -2) 17459 goto internal_error; 17460 if (res != 1) { 17461 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1); 17462 } 17463 } 17464 } 17465 if (fmaxexc) { 17466 /* 17467 * "maxExclusive >= minExclusive" 17468 */ 17469 if (fminexc) { 17470 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val); 17471 if (res == -2) 17472 goto internal_error; 17473 if (res == -1) { 17474 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0); 17475 } 17476 } 17477 /* 17478 * "maxExclusive valid restriction" 17479 */ 17480 if (bfmaxexc) { 17481 /* maxExclusive <= BASE maxExclusive */ 17482 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val); 17483 if (res == -2) 17484 goto internal_error; 17485 if (res == 1) { 17486 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1); 17487 } 17488 if ((res != 0) && (bfmaxexc->fixed)) { 17489 FACET_RESTR_FIXED_ERR(fmaxexc) 17490 } 17491 } 17492 if (bfmaxinc) { 17493 /* maxExclusive <= BASE maxInclusive */ 17494 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val); 17495 if (res == -2) 17496 goto internal_error; 17497 if (res == 1) { 17498 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1); 17499 } 17500 } 17501 if (bfmininc) { 17502 /* maxExclusive > BASE minInclusive */ 17503 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val); 17504 if (res == -2) 17505 goto internal_error; 17506 if (res != 1) { 17507 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1); 17508 } 17509 } 17510 if (bfminexc) { 17511 /* maxExclusive > BASE minExclusive */ 17512 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val); 17513 if (res == -2) 17514 goto internal_error; 17515 if (res != 1) { 17516 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1); 17517 } 17518 } 17519 } 17520 if (fminexc) { 17521 /* 17522 * "minExclusive < maxInclusive" 17523 */ 17524 if (fmaxinc) { 17525 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val); 17526 if (res == -2) 17527 goto internal_error; 17528 if (res != -1) { 17529 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0); 17530 } 17531 } 17532 /* 17533 * "minExclusive valid restriction" 17534 */ 17535 if (bfminexc) { 17536 /* minExclusive >= BASE minExclusive */ 17537 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val); 17538 if (res == -2) 17539 goto internal_error; 17540 if (res == -1) { 17541 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1); 17542 } 17543 if ((res != 0) && (bfminexc->fixed)) { 17544 FACET_RESTR_FIXED_ERR(fminexc) 17545 } 17546 } 17547 if (bfmaxinc) { 17548 /* minExclusive <= BASE maxInclusive */ 17549 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val); 17550 if (res == -2) 17551 goto internal_error; 17552 if (res == 1) { 17553 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1); 17554 } 17555 } 17556 if (bfmininc) { 17557 /* minExclusive >= BASE minInclusive */ 17558 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val); 17559 if (res == -2) 17560 goto internal_error; 17561 if (res == -1) { 17562 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1); 17563 } 17564 } 17565 if (bfmaxexc) { 17566 /* minExclusive < BASE maxExclusive */ 17567 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val); 17568 if (res == -2) 17569 goto internal_error; 17570 if (res != -1) { 17571 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1); 17572 } 17573 } 17574 } 17575 if (fmininc) { 17576 /* 17577 * "minInclusive < maxExclusive" 17578 */ 17579 if (fmaxexc) { 17580 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val); 17581 if (res == -2) 17582 goto internal_error; 17583 if (res != -1) { 17584 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0); 17585 } 17586 } 17587 /* 17588 * "minExclusive valid restriction" 17589 */ 17590 if (bfmininc) { 17591 /* minInclusive >= BASE minInclusive */ 17592 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val); 17593 if (res == -2) 17594 goto internal_error; 17595 if (res == -1) { 17596 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1); 17597 } 17598 if ((res != 0) && (bfmininc->fixed)) { 17599 FACET_RESTR_FIXED_ERR(fmininc) 17600 } 17601 } 17602 if (bfmaxinc) { 17603 /* minInclusive <= BASE maxInclusive */ 17604 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val); 17605 if (res == -2) 17606 goto internal_error; 17607 if (res == 1) { 17608 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1); 17609 } 17610 } 17611 if (bfminexc) { 17612 /* minInclusive > BASE minExclusive */ 17613 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val); 17614 if (res == -2) 17615 goto internal_error; 17616 if (res != 1) 17617 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1); 17618 } 17619 if (bfmaxexc) { 17620 /* minInclusive < BASE maxExclusive */ 17621 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val); 17622 if (res == -2) 17623 goto internal_error; 17624 if (res != -1) 17625 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1); 17626 } 17627 } 17628 if (ftotdig && bftotdig) { 17629 /* 17630 * SCC " totalDigits valid restriction" 17631 * totalDigits <= BASE totalDigits 17632 */ 17633 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val); 17634 if (res == -2) 17635 goto internal_error; 17636 if (res == 1) 17637 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig, 17638 -1, 1, 1); 17639 if ((res != 0) && (bftotdig->fixed)) { 17640 FACET_RESTR_FIXED_ERR(ftotdig) 17641 } 17642 } 17643 if (ffracdig && bffracdig) { 17644 /* 17645 * SCC "fractionDigits valid restriction" 17646 * fractionDigits <= BASE fractionDigits 17647 */ 17648 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val); 17649 if (res == -2) 17650 goto internal_error; 17651 if (res == 1) 17652 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig, 17653 -1, 1, 1); 17654 if ((res != 0) && (bffracdig->fixed)) { 17655 FACET_RESTR_FIXED_ERR(ffracdig) 17656 } 17657 } 17658 /* 17659 * SCC "fractionDigits less than or equal to totalDigits" 17660 */ 17661 if (! ftotdig) 17662 ftotdig = bftotdig; 17663 if (! ffracdig) 17664 ffracdig = bffracdig; 17665 if (ftotdig && ffracdig) { 17666 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val); 17667 if (res == -2) 17668 goto internal_error; 17669 if (res == 1) 17670 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig, 17671 -1, 1, 0); 17672 } 17673 /* 17674 * *Enumerations* won' be added here, since only the first set 17675 * of enumerations in the ancestor-or-self axis is used 17676 * for validation, plus we need to use the base type of those 17677 * enumerations for whitespace. 17678 * 17679 * *Patterns*: won't be add here, since they are ORed at 17680 * type level and ANDed at ancestor level. This will 17681 * happed during validation by walking the base axis 17682 * of the type. 17683 */ 17684 for (cur = base->facetSet; cur != NULL; cur = cur->next) { 17685 bfacet = cur->facet; 17686 /* 17687 * Special handling of enumerations and patterns. 17688 * TODO: hmm, they should not appear in the set, so remove this. 17689 */ 17690 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) || 17691 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION)) 17692 continue; 17693 /* 17694 * Search for a duplicate facet in the current type. 17695 */ 17696 link = type->facetSet; 17697 /* err = 0; */ 17698 /* fixedErr = 0; */ 17699 while (link != NULL) { 17700 facet = link->facet; 17701 if (facet->type == bfacet->type) { 17702 switch (facet->type) { 17703 case XML_SCHEMA_FACET_WHITESPACE: 17704 /* 17705 * The whitespace must be stronger. 17706 */ 17707 if (facet->whitespace < bfacet->whitespace) { 17708 FACET_RESTR_ERR(facet, 17709 "The 'whitespace' value has to be equal to " 17710 "or stronger than the 'whitespace' value of " 17711 "the base type") 17712 } 17713 if ((bfacet->fixed) && 17714 (facet->whitespace != bfacet->whitespace)) { 17715 FACET_RESTR_FIXED_ERR(facet) 17716 } 17717 break; 17718 default: 17719 break; 17720 } 17721 /* Duplicate found. */ 17722 break; 17723 } 17724 link = link->next; 17725 } 17726 /* 17727 * If no duplicate was found: add the base types's facet 17728 * to the set. 17729 */ 17730 if (link == NULL) { 17731 link = (xmlSchemaFacetLinkPtr) 17732 xmlMalloc(sizeof(xmlSchemaFacetLink)); 17733 if (link == NULL) { 17734 xmlSchemaPErrMemory(pctxt, 17735 "deriving facets, creating a facet link", NULL); 17736 return (-1); 17737 } 17738 link->facet = cur->facet; 17739 link->next = NULL; 17740 if (last == NULL) 17741 type->facetSet = link; 17742 else 17743 last->next = link; 17744 last = link; 17745 } 17746 17747 } 17748 17749 return (0); 17750internal_error: 17751 PERROR_INT("xmlSchemaDeriveAndValidateFacets", 17752 "an error occured"); 17753 return (-1); 17754} 17755 17756static int 17757xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt, 17758 xmlSchemaTypePtr type) 17759{ 17760 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink; 17761 /* 17762 * The actual value is then formed by replacing any union type 17763 * definition in the �explicit members� with the members of their 17764 * {member type definitions}, in order. 17765 * 17766 * TODO: There's a bug entry at 17767 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html" 17768 * which indicates that we'll keep the union types the future. 17769 */ 17770 link = type->memberTypes; 17771 while (link != NULL) { 17772 17773 if (WXS_IS_TYPE_NOT_FIXED(link->type)) 17774 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt); 17775 17776 if (WXS_IS_UNION(link->type)) { 17777 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type); 17778 if (subLink != NULL) { 17779 link->type = subLink->type; 17780 if (subLink->next != NULL) { 17781 lastLink = link->next; 17782 subLink = subLink->next; 17783 prevLink = link; 17784 while (subLink != NULL) { 17785 newLink = (xmlSchemaTypeLinkPtr) 17786 xmlMalloc(sizeof(xmlSchemaTypeLink)); 17787 if (newLink == NULL) { 17788 xmlSchemaPErrMemory(pctxt, "allocating a type link", 17789 NULL); 17790 return (-1); 17791 } 17792 newLink->type = subLink->type; 17793 prevLink->next = newLink; 17794 prevLink = newLink; 17795 newLink->next = lastLink; 17796 17797 subLink = subLink->next; 17798 } 17799 } 17800 } 17801 } 17802 link = link->next; 17803 } 17804 return (0); 17805} 17806 17807static void 17808xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type) 17809{ 17810 int has = 0, needVal = 0, normVal = 0; 17811 17812 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0; 17813 if (has) { 17814 needVal = (type->baseType->flags & 17815 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0; 17816 normVal = (type->baseType->flags & 17817 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0; 17818 } 17819 if (type->facets != NULL) { 17820 xmlSchemaFacetPtr fac; 17821 17822 for (fac = type->facets; fac != NULL; fac = fac->next) { 17823 switch (fac->type) { 17824 case XML_SCHEMA_FACET_WHITESPACE: 17825 break; 17826 case XML_SCHEMA_FACET_PATTERN: 17827 normVal = 1; 17828 has = 1; 17829 break; 17830 case XML_SCHEMA_FACET_ENUMERATION: 17831 needVal = 1; 17832 normVal = 1; 17833 has = 1; 17834 break; 17835 default: 17836 has = 1; 17837 break; 17838 } 17839 } 17840 } 17841 if (normVal) 17842 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED; 17843 if (needVal) 17844 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE; 17845 if (has) 17846 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS; 17847 17848 if (has && (! needVal) && WXS_IS_ATOMIC(type)) { 17849 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type); 17850 /* 17851 * OPTIMIZE VAL TODO: Some facets need a computed value. 17852 */ 17853 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) && 17854 (prim->builtInType != XML_SCHEMAS_STRING)) { 17855 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE; 17856 } 17857 } 17858} 17859 17860static int 17861xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type) 17862{ 17863 17864 17865 /* 17866 * Evaluate the whitespace-facet value. 17867 */ 17868 if (WXS_IS_LIST(type)) { 17869 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE; 17870 return (0); 17871 } else if (WXS_IS_UNION(type)) 17872 return (0); 17873 17874 if (type->facetSet != NULL) { 17875 xmlSchemaFacetLinkPtr lin; 17876 17877 for (lin = type->facetSet; lin != NULL; lin = lin->next) { 17878 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) { 17879 switch (lin->facet->whitespace) { 17880 case XML_SCHEMAS_FACET_PRESERVE: 17881 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE; 17882 break; 17883 case XML_SCHEMAS_FACET_REPLACE: 17884 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE; 17885 break; 17886 case XML_SCHEMAS_FACET_COLLAPSE: 17887 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE; 17888 break; 17889 default: 17890 return (-1); 17891 } 17892 return (0); 17893 } 17894 } 17895 } 17896 /* 17897 * For all �atomic� datatypes other than string (and types �derived� 17898 * by �restriction� from it) the value of whiteSpace is fixed to 17899 * collapse 17900 */ 17901 { 17902 xmlSchemaTypePtr anc; 17903 17904 for (anc = type->baseType; anc != NULL && 17905 anc->builtInType != XML_SCHEMAS_ANYTYPE; 17906 anc = anc->baseType) { 17907 17908 if (anc->type == XML_SCHEMA_TYPE_BASIC) { 17909 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) { 17910 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE; 17911 17912 } else if ((anc->builtInType == XML_SCHEMAS_STRING) || 17913 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) { 17914 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE; 17915 17916 } else 17917 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE; 17918 break; 17919 } 17920 } 17921 } 17922 return (0); 17923} 17924 17925static int 17926xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt, 17927 xmlSchemaTypePtr type) 17928{ 17929 if (type->type != XML_SCHEMA_TYPE_SIMPLE) 17930 return(0); 17931 if (! WXS_IS_TYPE_NOT_FIXED_1(type)) 17932 return(0); 17933 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1; 17934 17935 if (WXS_IS_LIST(type)) { 17936 /* 17937 * Corresponds to <simpleType><list>... 17938 */ 17939 if (type->subtypes == NULL) { 17940 /* 17941 * This one is really needed, so get out. 17942 */ 17943 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne", 17944 "list type has no item-type assigned"); 17945 return(-1); 17946 } 17947 } else if (WXS_IS_UNION(type)) { 17948 /* 17949 * Corresponds to <simpleType><union>... 17950 */ 17951 if (type->memberTypes == NULL) { 17952 /* 17953 * This one is really needed, so get out. 17954 */ 17955 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne", 17956 "union type has no member-types assigned"); 17957 return(-1); 17958 } 17959 } else { 17960 /* 17961 * Corresponds to <simpleType><restriction>... 17962 */ 17963 if (type->baseType == NULL) { 17964 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne", 17965 "type has no base-type assigned"); 17966 return(-1); 17967 } 17968 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType)) 17969 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1) 17970 return(-1); 17971 /* 17972 * Variety 17973 * If the <restriction> alternative is chosen, then the 17974 * {variety} of the {base type definition}. 17975 */ 17976 if (WXS_IS_ATOMIC(type->baseType)) 17977 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC; 17978 else if (WXS_IS_LIST(type->baseType)) { 17979 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST; 17980 /* 17981 * Inherit the itemType. 17982 */ 17983 type->subtypes = type->baseType->subtypes; 17984 } else if (WXS_IS_UNION(type->baseType)) { 17985 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION; 17986 /* 17987 * NOTE that we won't assign the memberTypes of the base, 17988 * since this will make trouble when freeing them; we will 17989 * use a lookup function to access them instead. 17990 */ 17991 } 17992 } 17993 return(0); 17994} 17995 17996#ifdef DEBUG_TYPE 17997static void 17998xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt, 17999 xmlSchemaTypePtr type) 18000{ 18001 if (type->node != NULL) { 18002 xmlGenericError(xmlGenericErrorContext, 18003 "Type of %s : %s:%d :", name, 18004 type->node->doc->URL, 18005 xmlGetLineNo(type->node)); 18006 } else { 18007 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name); 18008 } 18009 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) { 18010 switch (type->contentType) { 18011 case XML_SCHEMA_CONTENT_SIMPLE: 18012 xmlGenericError(xmlGenericErrorContext, "simple\n"); 18013 break; 18014 case XML_SCHEMA_CONTENT_ELEMENTS: 18015 xmlGenericError(xmlGenericErrorContext, "elements\n"); 18016 break; 18017 case XML_SCHEMA_CONTENT_UNKNOWN: 18018 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n"); 18019 break; 18020 case XML_SCHEMA_CONTENT_EMPTY: 18021 xmlGenericError(xmlGenericErrorContext, "empty\n"); 18022 break; 18023 case XML_SCHEMA_CONTENT_MIXED: 18024 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) 18025 type->subtypes)) 18026 xmlGenericError(xmlGenericErrorContext, 18027 "mixed as emptiable particle\n"); 18028 else 18029 xmlGenericError(xmlGenericErrorContext, "mixed\n"); 18030 break; 18031 /* Removed, since not used. */ 18032 /* 18033 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS: 18034 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n"); 18035 break; 18036 */ 18037 case XML_SCHEMA_CONTENT_BASIC: 18038 xmlGenericError(xmlGenericErrorContext, "basic\n"); 18039 break; 18040 default: 18041 xmlGenericError(xmlGenericErrorContext, 18042 "not registered !!!\n"); 18043 break; 18044 } 18045 } 18046} 18047#endif 18048 18049/* 18050* 3.14.6 Constraints on Simple Type Definition Schema Components 18051*/ 18052static int 18053xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt, 18054 xmlSchemaTypePtr type) 18055{ 18056 int res, olderrs = pctxt->nberrors; 18057 18058 if (type->type != XML_SCHEMA_TYPE_SIMPLE) 18059 return(-1); 18060 18061 if (! WXS_IS_TYPE_NOT_FIXED(type)) 18062 return(0); 18063 18064 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED; 18065 type->contentType = XML_SCHEMA_CONTENT_SIMPLE; 18066 18067 if (type->baseType == NULL) { 18068 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo", 18069 "missing baseType"); 18070 goto exit_failure; 18071 } 18072 if (WXS_IS_TYPE_NOT_FIXED(type->baseType)) 18073 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt); 18074 /* 18075 * If a member type of a union is a union itself, we need to substitute 18076 * that member type for its member types. 18077 * NOTE that this might change in WXS 1.1; i.e. we will keep the union 18078 * types in WXS 1.1. 18079 */ 18080 if ((type->memberTypes != NULL) && 18081 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)) 18082 return(-1); 18083 /* 18084 * SPEC src-simple-type 1 18085 * "The corresponding simple type definition, if any, must satisfy 18086 * the conditions set out in Constraints on Simple Type Definition 18087 * Schema Components (�3.14.6)." 18088 */ 18089 /* 18090 * Schema Component Constraint: Simple Type Definition Properties Correct 18091 * (st-props-correct) 18092 */ 18093 res = xmlSchemaCheckSTPropsCorrect(pctxt, type); 18094 HFAILURE HERROR 18095 /* 18096 * Schema Component Constraint: Derivation Valid (Restriction, Simple) 18097 * (cos-st-restricts) 18098 */ 18099 res = xmlSchemaCheckCOSSTRestricts(pctxt, type); 18100 HFAILURE HERROR 18101 /* 18102 * TODO: Removed the error report, since it got annoying to get an 18103 * extra error report, if anything failed until now. 18104 * Enable this if needed. 18105 * 18106 * xmlSchemaPErr(ctxt, type->node, 18107 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1, 18108 * "Simple type '%s' does not satisfy the constraints " 18109 * "on simple type definitions.\n", 18110 * type->name, NULL); 18111 */ 18112 /* 18113 * Schema Component Constraint: Simple Type Restriction (Facets) 18114 * (st-restrict-facets) 18115 */ 18116 res = xmlSchemaCheckFacetValues(type, pctxt); 18117 HFAILURE HERROR 18118 if ((type->facetSet != NULL) || 18119 (type->baseType->facetSet != NULL)) { 18120 res = xmlSchemaDeriveAndValidateFacets(pctxt, type); 18121 HFAILURE HERROR 18122 } 18123 /* 18124 * Whitespace value. 18125 */ 18126 res = xmlSchemaTypeFixupWhitespace(type); 18127 HFAILURE HERROR 18128 xmlSchemaTypeFixupOptimFacets(type); 18129 18130exit_error: 18131#ifdef DEBUG_TYPE 18132 xmlSchemaDebugFixedType(pctxt, type); 18133#endif 18134 if (olderrs != pctxt->nberrors) 18135 return(pctxt->err); 18136 return(0); 18137 18138exit_failure: 18139#ifdef DEBUG_TYPE 18140 xmlSchemaDebugFixedType(pctxt, type); 18141#endif 18142 return(-1); 18143} 18144 18145static int 18146xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt, 18147 xmlSchemaTypePtr type) 18148{ 18149 int res = 0, olderrs = pctxt->nberrors; 18150 xmlSchemaTypePtr baseType = type->baseType; 18151 18152 if (! WXS_IS_TYPE_NOT_FIXED(type)) 18153 return(0); 18154 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED; 18155 if (baseType == NULL) { 18156 PERROR_INT("xmlSchemaFixupComplexType", 18157 "missing baseType"); 18158 goto exit_failure; 18159 } 18160 /* 18161 * Fixup the base type. 18162 */ 18163 if (WXS_IS_TYPE_NOT_FIXED(baseType)) 18164 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt); 18165 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) { 18166 /* 18167 * Skip fixup if the base type is invalid. 18168 * TODO: Generate a warning! 18169 */ 18170 return(0); 18171 } 18172 /* 18173 * This basically checks if the base type can be derived. 18174 */ 18175 res = xmlSchemaCheckSRCCT(pctxt, type); 18176 HFAILURE HERROR 18177 /* 18178 * Fixup the content type. 18179 */ 18180 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) { 18181 /* 18182 * Corresponds to <complexType><simpleContent>... 18183 */ 18184 if ((WXS_IS_COMPLEX(baseType)) && 18185 (baseType->contentTypeDef != NULL) && 18186 (WXS_IS_RESTRICTION(type))) { 18187 xmlSchemaTypePtr contentBase, content; 18188#ifdef ENABLE_NAMED_LOCALS 18189 char buf[30]; 18190 const xmlChar *tmpname; 18191#endif 18192 /* 18193 * SPEC (1) If <restriction> + base type is <complexType>, 18194 * "whose own {content type} is a simple type..." 18195 */ 18196 if (type->contentTypeDef != NULL) { 18197 /* 18198 * SPEC (1.1) "the simple type definition corresponding to the 18199 * <simpleType> among the [children] of <restriction> if there 18200 * is one;" 18201 * Note that this "<simpleType> among the [children]" was put 18202 * into ->contentTypeDef during parsing. 18203 */ 18204 contentBase = type->contentTypeDef; 18205 type->contentTypeDef = NULL; 18206 } else { 18207 /* 18208 * (1.2) "...otherwise (<restriction> has no <simpleType> 18209 * among its [children]), the simple type definition which 18210 * is the {content type} of the ... base type." 18211 */ 18212 contentBase = baseType->contentTypeDef; 18213 } 18214 /* 18215 * SPEC 18216 * "... a simple type definition which restricts the simple 18217 * type definition identified in clause 1.1 or clause 1.2 18218 * with a set of facet components" 18219 * 18220 * Create the anonymous simple type, which will be the content 18221 * type of the complex type. 18222 */ 18223#ifdef ENABLE_NAMED_LOCALS 18224 snprintf(buf, 29, "#scST%d", ++(pctxt->counter)); 18225 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1); 18226 content = xmlSchemaAddType(pctxt, pctxt->schema, 18227 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace, 18228 type->node, 0); 18229#else 18230 content = xmlSchemaAddType(pctxt, pctxt->schema, 18231 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace, 18232 type->node, 0); 18233#endif 18234 if (content == NULL) 18235 goto exit_failure; 18236 /* 18237 * We will use the same node as for the <complexType> 18238 * to have it somehow anchored in the schema doc. 18239 */ 18240 content->type = XML_SCHEMA_TYPE_SIMPLE; 18241 content->baseType = contentBase; 18242 /* 18243 * Move the facets, previously anchored on the 18244 * complexType during parsing. 18245 */ 18246 content->facets = type->facets; 18247 type->facets = NULL; 18248 content->facetSet = type->facetSet; 18249 type->facetSet = NULL; 18250 18251 type->contentTypeDef = content; 18252 if (WXS_IS_TYPE_NOT_FIXED(contentBase)) 18253 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt); 18254 /* 18255 * Fixup the newly created type. We don't need to check 18256 * for circularity here. 18257 */ 18258 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content); 18259 HFAILURE HERROR 18260 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content); 18261 HFAILURE HERROR 18262 18263 } else if ((WXS_IS_COMPLEX(baseType)) && 18264 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) && 18265 (WXS_IS_RESTRICTION(type))) { 18266 /* 18267 * SPEC (2) If <restriction> + base is a mixed <complexType> with 18268 * an emptiable particle, then a simple type definition which 18269 * restricts the <restriction>'s <simpleType> child. 18270 */ 18271 if ((type->contentTypeDef == NULL) || 18272 (type->contentTypeDef->baseType == NULL)) { 18273 /* 18274 * TODO: Check if this ever happens. 18275 */ 18276 xmlSchemaPCustomErr(pctxt, 18277 XML_SCHEMAP_INTERNAL, 18278 WXS_BASIC_CAST type, NULL, 18279 "Internal error: xmlSchemaTypeFixup, " 18280 "complex type '%s': the <simpleContent><restriction> " 18281 "is missing a <simpleType> child, but was not catched " 18282 "by xmlSchemaCheckSRCCT()", type->name); 18283 goto exit_failure; 18284 } 18285 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) { 18286 /* 18287 * SPEC (3) If <extension> + base is <complexType> with 18288 * <simpleType> content, "...then the {content type} of that 18289 * complex type definition" 18290 */ 18291 if (baseType->contentTypeDef == NULL) { 18292 /* 18293 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT 18294 * should have catched this already. 18295 */ 18296 xmlSchemaPCustomErr(pctxt, 18297 XML_SCHEMAP_INTERNAL, 18298 WXS_BASIC_CAST type, NULL, 18299 "Internal error: xmlSchemaTypeFixup, " 18300 "complex type '%s': the <extension>ed base type is " 18301 "a complex type with no simple content type", 18302 type->name); 18303 goto exit_failure; 18304 } 18305 type->contentTypeDef = baseType->contentTypeDef; 18306 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) { 18307 /* 18308 * SPEC (4) <extension> + base is <simpleType> 18309 * "... then that simple type definition" 18310 */ 18311 type->contentTypeDef = baseType; 18312 } else { 18313 /* 18314 * TODO: Check if this ever happens. 18315 */ 18316 xmlSchemaPCustomErr(pctxt, 18317 XML_SCHEMAP_INTERNAL, 18318 WXS_BASIC_CAST type, NULL, 18319 "Internal error: xmlSchemaTypeFixup, " 18320 "complex type '%s' with <simpleContent>: unhandled " 18321 "derivation case", type->name); 18322 goto exit_failure; 18323 } 18324 } else { 18325 int dummySequence = 0; 18326 xmlSchemaParticlePtr particle = 18327 (xmlSchemaParticlePtr) type->subtypes; 18328 /* 18329 * Corresponds to <complexType><complexContent>... 18330 * 18331 * NOTE that the effective mixed was already set during parsing of 18332 * <complexType> and <complexContent>; its flag value is 18333 * XML_SCHEMAS_TYPE_MIXED. 18334 * 18335 * Compute the "effective content": 18336 * (2.1.1) + (2.1.2) + (2.1.3) 18337 */ 18338 if ((particle == NULL) || 18339 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) && 18340 ((particle->children->type == XML_SCHEMA_TYPE_ALL) || 18341 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) || 18342 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) && 18343 (particle->minOccurs == 0))) && 18344 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) { 18345 if (type->flags & XML_SCHEMAS_TYPE_MIXED) { 18346 /* 18347 * SPEC (2.1.4) "If the �effective mixed� is true, then 18348 * a particle whose properties are as follows:..." 18349 * 18350 * Empty sequence model group with 18351 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable"). 18352 * NOTE that we sill assign it the <complexType> node to 18353 * somehow anchor it in the doc. 18354 */ 18355 if ((particle == NULL) || 18356 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) { 18357 /* 18358 * Create the particle. 18359 */ 18360 particle = xmlSchemaAddParticle(pctxt, 18361 type->node, 1, 1); 18362 if (particle == NULL) 18363 goto exit_failure; 18364 /* 18365 * Create the model group. 18366 */ /* URGENT TODO: avoid adding to pending items. */ 18367 particle->children = (xmlSchemaTreeItemPtr) 18368 xmlSchemaAddModelGroup(pctxt, pctxt->schema, 18369 XML_SCHEMA_TYPE_SEQUENCE, type->node); 18370 if (particle->children == NULL) 18371 goto exit_failure; 18372 18373 type->subtypes = (xmlSchemaTypePtr) particle; 18374 } 18375 dummySequence = 1; 18376 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS; 18377 } else { 18378 /* 18379 * SPEC (2.1.5) "otherwise empty" 18380 */ 18381 type->contentType = XML_SCHEMA_CONTENT_EMPTY; 18382 } 18383 } else { 18384 /* 18385 * SPEC (2.2) "otherwise the particle corresponding to the 18386 * <all>, <choice>, <group> or <sequence> among the 18387 * [children]." 18388 */ 18389 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS; 18390 } 18391 /* 18392 * Compute the "content type". 18393 */ 18394 if (WXS_IS_RESTRICTION(type)) { 18395 /* 18396 * SPEC (3.1) "If <restriction>..." 18397 * (3.1.1) + (3.1.2) */ 18398 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) { 18399 if (type->flags & XML_SCHEMAS_TYPE_MIXED) 18400 type->contentType = XML_SCHEMA_CONTENT_MIXED; 18401 } 18402 } else { 18403 /* 18404 * SPEC (3.2) "If <extension>..." 18405 */ 18406 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) { 18407 /* 18408 * SPEC (3.2.1) 18409 * "If the �effective content� is empty, then the 18410 * {content type} of the [...] base ..." 18411 */ 18412 type->contentType = baseType->contentType; 18413 type->subtypes = baseType->subtypes; 18414 /* 18415 * Fixes bug #347316: 18416 * This is the case when the base type has a simple 18417 * type definition as content. 18418 */ 18419 type->contentTypeDef = baseType->contentTypeDef; 18420 /* 18421 * NOTE that the effective mixed is ignored here. 18422 */ 18423 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) { 18424 /* 18425 * SPEC (3.2.2) 18426 */ 18427 if (type->flags & XML_SCHEMAS_TYPE_MIXED) 18428 type->contentType = XML_SCHEMA_CONTENT_MIXED; 18429 } else { 18430 /* 18431 * SPEC (3.2.3) 18432 */ 18433 if (type->flags & XML_SCHEMAS_TYPE_MIXED) 18434 type->contentType = XML_SCHEMA_CONTENT_MIXED; 18435 /* 18436 * "A model group whose {compositor} is sequence and whose 18437 * {particles} are..." 18438 */ 18439 if ((WXS_TYPE_PARTICLE(type) != NULL) && 18440 (WXS_TYPE_PARTICLE_TERM(type) != NULL) && 18441 ((WXS_TYPE_PARTICLE_TERM(type))->type == 18442 XML_SCHEMA_TYPE_ALL)) 18443 { 18444 /* 18445 * SPEC cos-all-limited (1) 18446 */ 18447 xmlSchemaCustomErr(ACTXT_CAST pctxt, 18448 /* TODO: error code */ 18449 XML_SCHEMAP_COS_ALL_LIMITED, 18450 WXS_ITEM_NODE(type), NULL, 18451 "The type has an 'all' model group in its " 18452 "{content type} and thus cannot be derived from " 18453 "a non-empty type, since this would produce a " 18454 "'sequence' model group containing the 'all' " 18455 "model group; 'all' model groups are not " 18456 "allowed to appear inside other model groups", 18457 NULL, NULL); 18458 18459 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) && 18460 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) && 18461 ((WXS_TYPE_PARTICLE_TERM(baseType))->type == 18462 XML_SCHEMA_TYPE_ALL)) 18463 { 18464 /* 18465 * SPEC cos-all-limited (1) 18466 */ 18467 xmlSchemaCustomErr(ACTXT_CAST pctxt, 18468 /* TODO: error code */ 18469 XML_SCHEMAP_COS_ALL_LIMITED, 18470 WXS_ITEM_NODE(type), NULL, 18471 "A type cannot be derived by extension from a type " 18472 "which has an 'all' model group in its " 18473 "{content type}, since this would produce a " 18474 "'sequence' model group containing the 'all' " 18475 "model group; 'all' model groups are not " 18476 "allowed to appear inside other model groups", 18477 NULL, NULL); 18478 18479 } else if (! dummySequence) { 18480 xmlSchemaTreeItemPtr effectiveContent = 18481 (xmlSchemaTreeItemPtr) type->subtypes; 18482 /* 18483 * Create the particle. 18484 */ 18485 particle = xmlSchemaAddParticle(pctxt, 18486 type->node, 1, 1); 18487 if (particle == NULL) 18488 goto exit_failure; 18489 /* 18490 * Create the "sequence" model group. 18491 */ 18492 particle->children = (xmlSchemaTreeItemPtr) 18493 xmlSchemaAddModelGroup(pctxt, pctxt->schema, 18494 XML_SCHEMA_TYPE_SEQUENCE, type->node); 18495 if (particle->children == NULL) 18496 goto exit_failure; 18497 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle; 18498 /* 18499 * SPEC "the particle of the {content type} of 18500 * the ... base ..." 18501 * Create a duplicate of the base type's particle 18502 * and assign its "term" to it. 18503 */ 18504 particle->children->children = 18505 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt, 18506 type->node, 18507 ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs, 18508 ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs); 18509 if (particle->children->children == NULL) 18510 goto exit_failure; 18511 particle = (xmlSchemaParticlePtr) 18512 particle->children->children; 18513 particle->children = 18514 ((xmlSchemaParticlePtr) baseType->subtypes)->children; 18515 /* 18516 * SPEC "followed by the �effective content�." 18517 */ 18518 particle->next = effectiveContent; 18519 /* 18520 * This all will result in: 18521 * new-particle 18522 * --> new-sequence( 18523 * new-particle 18524 * --> base-model, 18525 * this-particle 18526 * --> this-model 18527 * ) 18528 */ 18529 } else { 18530 /* 18531 * This is the case when there is already an empty 18532 * <sequence> with minOccurs==maxOccurs==1. 18533 * Just add the base types's content type. 18534 * NOTE that, although we miss to add an intermediate 18535 * <sequence>, this should produce no difference to 18536 * neither the regex compilation of the content model, 18537 * nor to the complex type contraints. 18538 */ 18539 particle->children->children = 18540 (xmlSchemaTreeItemPtr) baseType->subtypes; 18541 } 18542 } 18543 } 18544 } 18545 /* 18546 * Now fixup attribute uses: 18547 * - expand attr. group references 18548 * - intersect attribute wildcards 18549 * - inherit attribute uses of the base type 18550 * - inherit or union attr. wildcards if extending 18551 * - apply attr. use prohibitions if restricting 18552 */ 18553 res = xmlSchemaFixupTypeAttributeUses(pctxt, type); 18554 HFAILURE HERROR 18555 /* 18556 * Apply the complex type component constraints; this will not 18557 * check attributes, since this is done in 18558 * xmlSchemaFixupTypeAttributeUses(). 18559 */ 18560 res = xmlSchemaCheckCTComponent(pctxt, type); 18561 HFAILURE HERROR 18562 18563#ifdef DEBUG_TYPE 18564 xmlSchemaDebugFixedType(pctxt, type); 18565#endif 18566 if (olderrs != pctxt->nberrors) 18567 return(pctxt->err); 18568 else 18569 return(0); 18570 18571exit_error: 18572 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID; 18573#ifdef DEBUG_TYPE 18574 xmlSchemaDebugFixedType(pctxt, type); 18575#endif 18576 return(pctxt->err); 18577 18578exit_failure: 18579 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID; 18580#ifdef DEBUG_TYPE 18581 xmlSchemaDebugFixedType(pctxt, type); 18582#endif 18583 return(-1); 18584} 18585 18586 18587/** 18588 * xmlSchemaTypeFixup: 18589 * @typeDecl: the schema type definition 18590 * @ctxt: the schema parser context 18591 * 18592 * Fixes the content model of the type. 18593 * URGENT TODO: We need an int result! 18594 */ 18595static int 18596xmlSchemaTypeFixup(xmlSchemaTypePtr type, 18597 xmlSchemaAbstractCtxtPtr actxt) 18598{ 18599 if (type == NULL) 18600 return(0); 18601 if (actxt->type != XML_SCHEMA_CTXT_PARSER) { 18602 AERROR_INT("xmlSchemaTypeFixup", 18603 "this function needs a parser context"); 18604 return(-1); 18605 } 18606 if (! WXS_IS_TYPE_NOT_FIXED(type)) 18607 return(0); 18608 if (type->type == XML_SCHEMA_TYPE_COMPLEX) 18609 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type)); 18610 else if (type->type == XML_SCHEMA_TYPE_SIMPLE) 18611 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type)); 18612 return(0); 18613} 18614 18615/** 18616 * xmlSchemaCheckFacet: 18617 * @facet: the facet 18618 * @typeDecl: the schema type definition 18619 * @pctxt: the schema parser context or NULL 18620 * @name: the optional name of the type 18621 * 18622 * Checks and computes the values of facets. 18623 * 18624 * Returns 0 if valid, a positive error code if not valid and 18625 * -1 in case of an internal or API error. 18626 */ 18627int 18628xmlSchemaCheckFacet(xmlSchemaFacetPtr facet, 18629 xmlSchemaTypePtr typeDecl, 18630 xmlSchemaParserCtxtPtr pctxt, 18631 const xmlChar * name ATTRIBUTE_UNUSED) 18632{ 18633 int ret = 0, ctxtGiven; 18634 18635 if ((facet == NULL) || (typeDecl == NULL)) 18636 return(-1); 18637 /* 18638 * TODO: will the parser context be given if used from 18639 * the relaxNG module? 18640 */ 18641 if (pctxt == NULL) 18642 ctxtGiven = 0; 18643 else 18644 ctxtGiven = 1; 18645 18646 switch (facet->type) { 18647 case XML_SCHEMA_FACET_MININCLUSIVE: 18648 case XML_SCHEMA_FACET_MINEXCLUSIVE: 18649 case XML_SCHEMA_FACET_MAXINCLUSIVE: 18650 case XML_SCHEMA_FACET_MAXEXCLUSIVE: 18651 case XML_SCHEMA_FACET_ENUMERATION: { 18652 /* 18653 * Okay we need to validate the value 18654 * at that point. 18655 */ 18656 xmlSchemaTypePtr base; 18657 18658 /* 4.3.5.5 Constraints on enumeration Schema Components 18659 * Schema Component Constraint: enumeration valid restriction 18660 * It is an �error� if any member of {value} is not in the 18661 * �value space� of {base type definition}. 18662 * 18663 * minInclusive, maxInclusive, minExclusive, maxExclusive: 18664 * The value �must� be in the 18665 * �value space� of the �base type�. 18666 */ 18667 /* 18668 * This function is intended to deliver a compiled value 18669 * on the facet. In this implementation of XML Schemata the 18670 * type holding a facet, won't be a built-in type. 18671 * Thus to ensure that other API 18672 * calls (relaxng) do work, if the given type is a built-in 18673 * type, we will assume that the given built-in type *is 18674 * already* the base type. 18675 */ 18676 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) { 18677 base = typeDecl->baseType; 18678 if (base == NULL) { 18679 PERROR_INT("xmlSchemaCheckFacet", 18680 "a type user derived type has no base type"); 18681 return (-1); 18682 } 18683 } else 18684 base = typeDecl; 18685 18686 if (! ctxtGiven) { 18687 /* 18688 * A context is needed if called from RelaxNG. 18689 */ 18690 pctxt = xmlSchemaNewParserCtxt("*"); 18691 if (pctxt == NULL) 18692 return (-1); 18693 } 18694 /* 18695 * NOTE: This call does not check the content nodes, 18696 * since they are not available: 18697 * facet->node is just the node holding the facet 18698 * definition, *not* the attribute holding the *value* 18699 * of the facet. 18700 */ 18701 ret = xmlSchemaVCheckCVCSimpleType( 18702 ACTXT_CAST pctxt, facet->node, base, 18703 facet->value, &(facet->val), 1, 1, 0); 18704 if (ret != 0) { 18705 if (ret < 0) { 18706 /* No error message for RelaxNG. */ 18707 if (ctxtGiven) { 18708 xmlSchemaCustomErr(ACTXT_CAST pctxt, 18709 XML_SCHEMAP_INTERNAL, facet->node, NULL, 18710 "Internal error: xmlSchemaCheckFacet, " 18711 "failed to validate the value '%s' of the " 18712 "facet '%s' against the base type", 18713 facet->value, xmlSchemaFacetTypeToString(facet->type)); 18714 } 18715 goto internal_error; 18716 } 18717 ret = XML_SCHEMAP_INVALID_FACET_VALUE; 18718 /* No error message for RelaxNG. */ 18719 if (ctxtGiven) { 18720 xmlChar *str = NULL; 18721 18722 xmlSchemaCustomErr(ACTXT_CAST pctxt, 18723 ret, facet->node, WXS_BASIC_CAST facet, 18724 "The value '%s' of the facet does not validate " 18725 "against the base type '%s'", 18726 facet->value, 18727 xmlSchemaFormatQName(&str, 18728 base->targetNamespace, base->name)); 18729 FREE_AND_NULL(str); 18730 } 18731 goto exit; 18732 } else if (facet->val == NULL) { 18733 if (ctxtGiven) { 18734 PERROR_INT("xmlSchemaCheckFacet", 18735 "value was not computed"); 18736 } 18737 TODO 18738 } 18739 break; 18740 } 18741 case XML_SCHEMA_FACET_PATTERN: 18742 facet->regexp = xmlRegexpCompile(facet->value); 18743 if (facet->regexp == NULL) { 18744 ret = XML_SCHEMAP_REGEXP_INVALID; 18745 /* No error message for RelaxNG. */ 18746 if (ctxtGiven) { 18747 xmlSchemaCustomErr(ACTXT_CAST pctxt, 18748 ret, facet->node, WXS_BASIC_CAST typeDecl, 18749 "The value '%s' of the facet 'pattern' is not a " 18750 "valid regular expression", 18751 facet->value, NULL); 18752 } 18753 } 18754 break; 18755 case XML_SCHEMA_FACET_TOTALDIGITS: 18756 case XML_SCHEMA_FACET_FRACTIONDIGITS: 18757 case XML_SCHEMA_FACET_LENGTH: 18758 case XML_SCHEMA_FACET_MAXLENGTH: 18759 case XML_SCHEMA_FACET_MINLENGTH: 18760 18761 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) { 18762 ret = xmlSchemaValidatePredefinedType( 18763 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER), 18764 facet->value, &(facet->val)); 18765 } else { 18766 ret = xmlSchemaValidatePredefinedType( 18767 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER), 18768 facet->value, &(facet->val)); 18769 } 18770 if (ret != 0) { 18771 if (ret < 0) { 18772 /* No error message for RelaxNG. */ 18773 if (ctxtGiven) { 18774 PERROR_INT("xmlSchemaCheckFacet", 18775 "validating facet value"); 18776 } 18777 goto internal_error; 18778 } 18779 ret = XML_SCHEMAP_INVALID_FACET_VALUE; 18780 /* No error message for RelaxNG. */ 18781 if (ctxtGiven) { 18782 /* error code */ 18783 xmlSchemaCustomErr4(ACTXT_CAST pctxt, 18784 ret, facet->node, WXS_BASIC_CAST typeDecl, 18785 "The value '%s' of the facet '%s' is not a valid '%s'", 18786 facet->value, 18787 xmlSchemaFacetTypeToString(facet->type), 18788 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ? 18789 BAD_CAST "nonNegativeInteger" : 18790 BAD_CAST "positiveInteger", 18791 NULL); 18792 } 18793 } 18794 break; 18795 18796 case XML_SCHEMA_FACET_WHITESPACE:{ 18797 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) { 18798 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE; 18799 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) { 18800 facet->whitespace = XML_SCHEMAS_FACET_REPLACE; 18801 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) { 18802 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE; 18803 } else { 18804 ret = XML_SCHEMAP_INVALID_FACET_VALUE; 18805 /* No error message for RelaxNG. */ 18806 if (ctxtGiven) { 18807 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */ 18808 xmlSchemaCustomErr(ACTXT_CAST pctxt, 18809 ret, facet->node, WXS_BASIC_CAST typeDecl, 18810 "The value '%s' of the facet 'whitespace' is not " 18811 "valid", facet->value, NULL); 18812 } 18813 } 18814 } 18815 default: 18816 break; 18817 } 18818exit: 18819 if ((! ctxtGiven) && (pctxt != NULL)) 18820 xmlSchemaFreeParserCtxt(pctxt); 18821 return (ret); 18822internal_error: 18823 if ((! ctxtGiven) && (pctxt != NULL)) 18824 xmlSchemaFreeParserCtxt(pctxt); 18825 return (-1); 18826} 18827 18828/** 18829 * xmlSchemaCheckFacetValues: 18830 * @typeDecl: the schema type definition 18831 * @ctxt: the schema parser context 18832 * 18833 * Checks the default values types, especially for facets 18834 */ 18835static int 18836xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl, 18837 xmlSchemaParserCtxtPtr pctxt) 18838{ 18839 int res, olderrs = pctxt->nberrors; 18840 const xmlChar *name = typeDecl->name; 18841 /* 18842 * NOTE: It is intended to use the facets list, instead 18843 * of facetSet. 18844 */ 18845 if (typeDecl->facets != NULL) { 18846 xmlSchemaFacetPtr facet = typeDecl->facets; 18847 18848 /* 18849 * Temporarily assign the "schema" to the validation context 18850 * of the parser context. This is needed for NOTATION validation. 18851 */ 18852 if (pctxt->vctxt == NULL) { 18853 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1) 18854 return(-1); 18855 } 18856 pctxt->vctxt->schema = pctxt->schema; 18857 while (facet != NULL) { 18858 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name); 18859 HFAILURE 18860 facet = facet->next; 18861 } 18862 pctxt->vctxt->schema = NULL; 18863 } 18864 if (olderrs != pctxt->nberrors) 18865 return(pctxt->err); 18866 return(0); 18867exit_failure: 18868 return(-1); 18869} 18870 18871/** 18872 * xmlSchemaGetCircModelGrDefRef: 18873 * @ctxtMGroup: the searched model group 18874 * @selfMGroup: the second searched model group 18875 * @particle: the first particle 18876 * 18877 * This one is intended to be used by 18878 * xmlSchemaCheckGroupDefCircular only. 18879 * 18880 * Returns the particle with the circular model group definition reference, 18881 * otherwise NULL. 18882 */ 18883static xmlSchemaTreeItemPtr 18884xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef, 18885 xmlSchemaTreeItemPtr particle) 18886{ 18887 xmlSchemaTreeItemPtr circ = NULL; 18888 xmlSchemaTreeItemPtr term; 18889 xmlSchemaModelGroupDefPtr gdef; 18890 18891 for (; particle != NULL; particle = particle->next) { 18892 term = particle->children; 18893 if (term == NULL) 18894 continue; 18895 switch (term->type) { 18896 case XML_SCHEMA_TYPE_GROUP: 18897 gdef = (xmlSchemaModelGroupDefPtr) term; 18898 if (gdef == groupDef) 18899 return (particle); 18900 /* 18901 * Mark this model group definition to avoid infinite 18902 * recursion on circular references not yet examined. 18903 */ 18904 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED) 18905 continue; 18906 if (gdef->children != NULL) { 18907 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED; 18908 circ = xmlSchemaGetCircModelGrDefRef(groupDef, 18909 gdef->children->children); 18910 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED; 18911 if (circ != NULL) 18912 return (circ); 18913 } 18914 break; 18915 case XML_SCHEMA_TYPE_SEQUENCE: 18916 case XML_SCHEMA_TYPE_CHOICE: 18917 case XML_SCHEMA_TYPE_ALL: 18918 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children); 18919 if (circ != NULL) 18920 return (circ); 18921 break; 18922 default: 18923 break; 18924 } 18925 } 18926 return (NULL); 18927} 18928 18929/** 18930 * xmlSchemaCheckGroupDefCircular: 18931 * @item: the model group definition 18932 * @ctxt: the parser context 18933 * @name: the name 18934 * 18935 * Checks for circular references to model group definitions. 18936 */ 18937static void 18938xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item, 18939 xmlSchemaParserCtxtPtr ctxt) 18940{ 18941 /* 18942 * Schema Component Constraint: Model Group Correct 18943 * 2 Circular groups are disallowed. That is, within the {particles} 18944 * of a group there must not be at any depth a particle whose {term} 18945 * is the group itself. 18946 */ 18947 if ((item == NULL) || 18948 (item->type != XML_SCHEMA_TYPE_GROUP) || 18949 (item->children == NULL)) 18950 return; 18951 { 18952 xmlSchemaTreeItemPtr circ; 18953 18954 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children); 18955 if (circ != NULL) { 18956 xmlChar *str = NULL; 18957 /* 18958 * TODO: The error report is not adequate: this constraint 18959 * is defined for model groups but not definitions, but since 18960 * there cannot be any circular model groups without a model group 18961 * definition (if not using a construction API), we check those 18962 * defintions only. 18963 */ 18964 xmlSchemaPCustomErr(ctxt, 18965 XML_SCHEMAP_MG_PROPS_CORRECT_2, 18966 NULL, WXS_ITEM_NODE(circ), 18967 "Circular reference to the model group definition '%s' " 18968 "defined", xmlSchemaFormatQName(&str, 18969 item->targetNamespace, item->name)); 18970 FREE_AND_NULL(str) 18971 /* 18972 * NOTE: We will cut the reference to avoid further 18973 * confusion of the processor. This is a fatal error. 18974 */ 18975 circ->children = NULL; 18976 } 18977 } 18978} 18979 18980/** 18981 * xmlSchemaModelGroupToModelGroupDefFixup: 18982 * @ctxt: the parser context 18983 * @mg: the model group 18984 * 18985 * Assigns the model group of model group definitions to the "term" 18986 * of the referencing particle. 18987 * In xmlSchemaResolveModelGroupParticleReferences the model group 18988 * definitions were assigned to the "term", since needed for the 18989 * circularity check. 18990 * 18991 * Schema Component Constraint: 18992 * All Group Limited (cos-all-limited) (1.2) 18993 */ 18994static void 18995xmlSchemaModelGroupToModelGroupDefFixup( 18996 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED, 18997 xmlSchemaModelGroupPtr mg) 18998{ 18999 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg); 19000 19001 while (particle != NULL) { 19002 if ((WXS_PARTICLE_TERM(particle) == NULL) || 19003 ((WXS_PARTICLE_TERM(particle))->type != 19004 XML_SCHEMA_TYPE_GROUP)) 19005 { 19006 particle = WXS_PTC_CAST particle->next; 19007 continue; 19008 } 19009 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) { 19010 /* 19011 * TODO: Remove the particle. 19012 */ 19013 WXS_PARTICLE_TERM(particle) = NULL; 19014 particle = WXS_PTC_CAST particle->next; 19015 continue; 19016 } 19017 /* 19018 * Assign the model group to the {term} of the particle. 19019 */ 19020 WXS_PARTICLE_TERM(particle) = 19021 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)); 19022 19023 particle = WXS_PTC_CAST particle->next; 19024 } 19025} 19026 19027/** 19028 * xmlSchemaCheckAttrGroupCircularRecur: 19029 * @ctxtGr: the searched attribute group 19030 * @attr: the current attribute list to be processed 19031 * 19032 * This one is intended to be used by 19033 * xmlSchemaCheckAttrGroupCircular only. 19034 * 19035 * Returns the circular attribute grou reference, otherwise NULL. 19036 */ 19037static xmlSchemaQNameRefPtr 19038xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr, 19039 xmlSchemaItemListPtr list) 19040{ 19041 xmlSchemaAttributeGroupPtr gr; 19042 xmlSchemaQNameRefPtr ref, circ; 19043 int i; 19044 /* 19045 * We will search for an attribute group reference which 19046 * references the context attribute group. 19047 */ 19048 for (i = 0; i < list->nbItems; i++) { 19049 ref = list->items[i]; 19050 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) && 19051 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) && 19052 (ref->item != NULL)) 19053 { 19054 gr = WXS_ATTR_GROUP_CAST ref->item; 19055 if (gr == ctxtGr) 19056 return(ref); 19057 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED) 19058 continue; 19059 /* 19060 * Mark as visited to avoid infinite recursion on 19061 * circular references not yet examined. 19062 */ 19063 if ((gr->attrUses) && 19064 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)) 19065 { 19066 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED; 19067 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr, 19068 (xmlSchemaItemListPtr) gr->attrUses); 19069 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED; 19070 if (circ != NULL) 19071 return (circ); 19072 } 19073 19074 } 19075 } 19076 return (NULL); 19077} 19078 19079/** 19080 * xmlSchemaCheckAttrGroupCircular: 19081 * attrGr: the attribute group definition 19082 * @ctxt: the parser context 19083 * @name: the name 19084 * 19085 * Checks for circular references of attribute groups. 19086 */ 19087static int 19088xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr, 19089 xmlSchemaParserCtxtPtr ctxt) 19090{ 19091 /* 19092 * Schema Representation Constraint: 19093 * Attribute Group Definition Representation OK 19094 * 3 Circular group reference is disallowed outside <redefine>. 19095 * That is, unless this element information item's parent is 19096 * <redefine>, then among the [children], if any, there must 19097 * not be an <attributeGroup> with ref [attribute] which resolves 19098 * to the component corresponding to this <attributeGroup>. Indirect 19099 * circularity is also ruled out. That is, when QName resolution 19100 * (Schema Document) (�3.15.3) is applied to a �QName� arising from 19101 * any <attributeGroup>s with a ref [attribute] among the [children], 19102 * it must not be the case that a �QName� is encountered at any depth 19103 * which resolves to the component corresponding to this <attributeGroup>. 19104 */ 19105 if (attrGr->attrUses == NULL) 19106 return(0); 19107 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0) 19108 return(0); 19109 else { 19110 xmlSchemaQNameRefPtr circ; 19111 19112 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr, 19113 (xmlSchemaItemListPtr) attrGr->attrUses); 19114 if (circ != NULL) { 19115 xmlChar *str = NULL; 19116 /* 19117 * TODO: Report the referenced attr group as QName. 19118 */ 19119 xmlSchemaPCustomErr(ctxt, 19120 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3, 19121 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ), 19122 "Circular reference to the attribute group '%s' " 19123 "defined", xmlSchemaGetComponentQName(&str, attrGr)); 19124 FREE_AND_NULL(str); 19125 /* 19126 * NOTE: We will cut the reference to avoid further 19127 * confusion of the processor. 19128 * BADSPEC TODO: The spec should define how to process in this case. 19129 */ 19130 circ->item = NULL; 19131 return(ctxt->err); 19132 } 19133 } 19134 return(0); 19135} 19136 19137static int 19138xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt, 19139 xmlSchemaAttributeGroupPtr attrGr); 19140 19141/** 19142 * xmlSchemaExpandAttributeGroupRefs: 19143 * @pctxt: the parser context 19144 * @node: the node of the component holding the attribute uses 19145 * @completeWild: the intersected wildcard to be returned 19146 * @list: the attribute uses 19147 * 19148 * Substitutes contained attribute group references 19149 * for their attribute uses. Wilcards are intersected. 19150 * Attribute use prohibitions are removed from the list 19151 * and returned via the @prohibs list. 19152 * Pointlessness of attr. prohibs, if a matching attr. decl 19153 * is existent a well, are checked. 19154 */ 19155static int 19156xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt, 19157 xmlSchemaBasicItemPtr item, 19158 xmlSchemaWildcardPtr *completeWild, 19159 xmlSchemaItemListPtr list, 19160 xmlSchemaItemListPtr prohibs) 19161{ 19162 xmlSchemaAttributeGroupPtr gr; 19163 xmlSchemaAttributeUsePtr use; 19164 xmlSchemaItemListPtr sublist; 19165 int i, j; 19166 int created = (*completeWild == NULL) ? 0 : 1; 19167 19168 if (prohibs) 19169 prohibs->nbItems = 0; 19170 19171 for (i = 0; i < list->nbItems; i++) { 19172 use = list->items[i]; 19173 19174 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) { 19175 if (prohibs == NULL) { 19176 PERROR_INT("xmlSchemaExpandAttributeGroupRefs", 19177 "unexpected attr prohibition found"); 19178 return(-1); 19179 } 19180 /* 19181 * Remove from attribute uses. 19182 */ 19183 if (xmlSchemaItemListRemove(list, i) == -1) 19184 return(-1); 19185 i--; 19186 /* 19187 * Note that duplicate prohibitions were already 19188 * handled at parsing time. 19189 */ 19190 /* 19191 * Add to list of prohibitions. 19192 */ 19193 xmlSchemaItemListAddSize(prohibs, 2, use); 19194 continue; 19195 } 19196 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) && 19197 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)) 19198 { 19199 if ((WXS_QNAME_CAST use)->item == NULL) 19200 return(-1); 19201 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item; 19202 /* 19203 * Expand the referenced attr. group. 19204 * TODO: remove this, this is done in a previous step, so 19205 * already done here. 19206 */ 19207 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) { 19208 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1) 19209 return(-1); 19210 } 19211 /* 19212 * Build the 'complete' wildcard; i.e. intersect multiple 19213 * wildcards. 19214 */ 19215 if (gr->attributeWildcard != NULL) { 19216 if (*completeWild == NULL) { 19217 *completeWild = gr->attributeWildcard; 19218 } else { 19219 if (! created) { 19220 xmlSchemaWildcardPtr tmpWild; 19221 19222 /* 19223 * Copy the first encountered wildcard as context, 19224 * except for the annotation. 19225 * 19226 * Although the complete wildcard might not correspond 19227 * to any node in the schema, we will anchor it on 19228 * the node of the owner component. 19229 */ 19230 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema, 19231 XML_SCHEMA_TYPE_ANY_ATTRIBUTE, 19232 WXS_ITEM_NODE(item)); 19233 if (tmpWild == NULL) 19234 return(-1); 19235 if (xmlSchemaCloneWildcardNsConstraints(pctxt, 19236 tmpWild, *completeWild) == -1) 19237 return (-1); 19238 tmpWild->processContents = (*completeWild)->processContents; 19239 *completeWild = tmpWild; 19240 created = 1; 19241 } 19242 19243 if (xmlSchemaIntersectWildcards(pctxt, *completeWild, 19244 gr->attributeWildcard) == -1) 19245 return(-1); 19246 } 19247 } 19248 /* 19249 * Just remove the reference if the referenced group does not 19250 * contain any attribute uses. 19251 */ 19252 sublist = ((xmlSchemaItemListPtr) gr->attrUses); 19253 if ((sublist == NULL) || sublist->nbItems == 0) { 19254 if (xmlSchemaItemListRemove(list, i) == -1) 19255 return(-1); 19256 i--; 19257 continue; 19258 } 19259 /* 19260 * Add the attribute uses. 19261 */ 19262 list->items[i] = sublist->items[0]; 19263 if (sublist->nbItems != 1) { 19264 for (j = 1; j < sublist->nbItems; j++) { 19265 i++; 19266 if (xmlSchemaItemListInsert(list, 19267 sublist->items[j], i) == -1) 19268 return(-1); 19269 } 19270 } 19271 } 19272 19273 } 19274 /* 19275 * Handle pointless prohibitions of declared attributes. 19276 */ 19277 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) { 19278 xmlSchemaAttributeUseProhibPtr prohib; 19279 19280 for (i = prohibs->nbItems -1; i >= 0; i--) { 19281 prohib = prohibs->items[i]; 19282 for (j = 0; j < list->nbItems; j++) { 19283 use = list->items[j]; 19284 19285 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) && 19286 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use))) 19287 { 19288 xmlChar *str = NULL; 19289 19290 xmlSchemaCustomWarning(ACTXT_CAST pctxt, 19291 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, 19292 prohib->node, NULL, 19293 "Skipping pointless attribute use prohibition " 19294 "'%s', since a corresponding attribute use " 19295 "exists already in the type definition", 19296 xmlSchemaFormatQName(&str, 19297 prohib->targetNamespace, prohib->name), 19298 NULL, NULL); 19299 FREE_AND_NULL(str); 19300 /* 19301 * Remove the prohibition. 19302 */ 19303 if (xmlSchemaItemListRemove(prohibs, i) == -1) 19304 return(-1); 19305 break; 19306 } 19307 } 19308 } 19309 } 19310 return(0); 19311} 19312 19313/** 19314 * xmlSchemaAttributeGroupExpandRefs: 19315 * @pctxt: the parser context 19316 * @attrGr: the attribute group definition 19317 * 19318 * Computation of: 19319 * {attribute uses} property 19320 * {attribute wildcard} property 19321 * 19322 * Substitutes contained attribute group references 19323 * for their attribute uses. Wilcards are intersected. 19324 */ 19325static int 19326xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt, 19327 xmlSchemaAttributeGroupPtr attrGr) 19328{ 19329 if ((attrGr->attrUses == NULL) || 19330 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)) 19331 return(0); 19332 19333 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED; 19334 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr, 19335 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1) 19336 return(-1); 19337 return(0); 19338} 19339 19340/** 19341 * xmlSchemaAttributeGroupExpandRefs: 19342 * @pctxt: the parser context 19343 * @attrGr: the attribute group definition 19344 * 19345 * Substitutes contained attribute group references 19346 * for their attribute uses. Wilcards are intersected. 19347 * 19348 * Schema Component Constraint: 19349 * Attribute Group Definition Properties Correct (ag-props-correct) 19350 */ 19351static int 19352xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt, 19353 xmlSchemaAttributeGroupPtr attrGr) 19354{ 19355 /* 19356 * SPEC ag-props-correct 19357 * (1) "The values of the properties of an attribute group definition 19358 * must be as described in the property tableau in The Attribute 19359 * Group Definition Schema Component (�3.6.1), modulo the impact of 19360 * Missing Sub-components (�5.3);" 19361 */ 19362 19363 if ((attrGr->attrUses != NULL) && 19364 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1) 19365 { 19366 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses; 19367 xmlSchemaAttributeUsePtr use, tmp; 19368 int i, j, hasId = 0; 19369 19370 for (i = uses->nbItems -1; i >= 0; i--) { 19371 use = uses->items[i]; 19372 /* 19373 * SPEC ag-props-correct 19374 * (2) "Two distinct members of the {attribute uses} must not have 19375 * {attribute declaration}s both of whose {name}s match and whose 19376 * {target namespace}s are identical." 19377 */ 19378 if (i > 0) { 19379 for (j = i -1; j >= 0; j--) { 19380 tmp = uses->items[j]; 19381 if ((WXS_ATTRUSE_DECL_NAME(use) == 19382 WXS_ATTRUSE_DECL_NAME(tmp)) && 19383 (WXS_ATTRUSE_DECL_TNS(use) == 19384 WXS_ATTRUSE_DECL_TNS(tmp))) 19385 { 19386 xmlChar *str = NULL; 19387 19388 xmlSchemaCustomErr(ACTXT_CAST pctxt, 19389 XML_SCHEMAP_AG_PROPS_CORRECT, 19390 attrGr->node, WXS_BASIC_CAST attrGr, 19391 "Duplicate %s", 19392 xmlSchemaGetComponentDesignation(&str, use), 19393 NULL); 19394 FREE_AND_NULL(str); 19395 /* 19396 * Remove the duplicate. 19397 */ 19398 if (xmlSchemaItemListRemove(uses, i) == -1) 19399 return(-1); 19400 goto next_use; 19401 } 19402 } 19403 } 19404 /* 19405 * SPEC ag-props-correct 19406 * (3) "Two distinct members of the {attribute uses} must not have 19407 * {attribute declaration}s both of whose {type definition}s are or 19408 * are derived from ID." 19409 * TODO: Does 'derived' include member-types of unions? 19410 */ 19411 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) { 19412 if (xmlSchemaIsDerivedFromBuiltInType( 19413 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID)) 19414 { 19415 if (hasId) { 19416 xmlChar *str = NULL; 19417 19418 xmlSchemaCustomErr(ACTXT_CAST pctxt, 19419 XML_SCHEMAP_AG_PROPS_CORRECT, 19420 attrGr->node, WXS_BASIC_CAST attrGr, 19421 "There must not exist more than one attribute " 19422 "declaration of type 'xs:ID' " 19423 "(or derived from 'xs:ID'). The %s violates this " 19424 "constraint", 19425 xmlSchemaGetComponentDesignation(&str, use), 19426 NULL); 19427 FREE_AND_NULL(str); 19428 if (xmlSchemaItemListRemove(uses, i) == -1) 19429 return(-1); 19430 } 19431 hasId = 1; 19432 } 19433 } 19434next_use: {} 19435 } 19436 } 19437 return(0); 19438} 19439 19440/** 19441 * xmlSchemaResolveAttrGroupReferences: 19442 * @attrgrpDecl: the schema attribute definition 19443 * @ctxt: the schema parser context 19444 * @name: the attribute name 19445 * 19446 * Resolves references to attribute group definitions. 19447 */ 19448static int 19449xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref, 19450 xmlSchemaParserCtxtPtr ctxt) 19451{ 19452 xmlSchemaAttributeGroupPtr group; 19453 19454 if (ref->item != NULL) 19455 return(0); 19456 group = xmlSchemaGetAttributeGroup(ctxt->schema, 19457 ref->name, 19458 ref->targetNamespace); 19459 if (group == NULL) { 19460 xmlSchemaPResCompAttrErr(ctxt, 19461 XML_SCHEMAP_SRC_RESOLVE, 19462 NULL, ref->node, 19463 "ref", ref->name, ref->targetNamespace, 19464 ref->itemType, NULL); 19465 return(ctxt->err); 19466 } 19467 ref->item = WXS_BASIC_CAST group; 19468 return(0); 19469} 19470 19471/** 19472 * xmlSchemaCheckAttrPropsCorrect: 19473 * @item: an schema attribute declaration/use 19474 * @ctxt: a schema parser context 19475 * @name: the name of the attribute 19476 * 19477 * 19478 * Schema Component Constraint: 19479 * Attribute Declaration Properties Correct (a-props-correct) 19480 * 19481 * Validates the value constraints of an attribute declaration/use. 19482 * NOTE that this needs the simle type definitions to be already 19483 * builded and checked. 19484 */ 19485static int 19486xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt, 19487 xmlSchemaAttributePtr attr) 19488{ 19489 19490 /* 19491 * SPEC a-props-correct (1) 19492 * "The values of the properties of an attribute declaration must 19493 * be as described in the property tableau in The Attribute 19494 * Declaration Schema Component (�3.2.1), modulo the impact of 19495 * Missing Sub-components (�5.3)." 19496 */ 19497 19498 if (WXS_ATTR_TYPEDEF(attr) == NULL) 19499 return(0); 19500 19501 if (attr->defValue != NULL) { 19502 int ret; 19503 19504 /* 19505 * SPEC a-props-correct (3) 19506 * "If the {type definition} is or is derived from ID then there 19507 * must not be a {value constraint}." 19508 */ 19509 if (xmlSchemaIsDerivedFromBuiltInType( 19510 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID)) 19511 { 19512 xmlSchemaCustomErr(ACTXT_CAST pctxt, 19513 XML_SCHEMAP_A_PROPS_CORRECT_3, 19514 NULL, WXS_BASIC_CAST attr, 19515 "Value constraints are not allowed if the type definition " 19516 "is or is derived from xs:ID", 19517 NULL, NULL); 19518 return(pctxt->err); 19519 } 19520 /* 19521 * SPEC a-props-correct (2) 19522 * "if there is a {value constraint}, the canonical lexical 19523 * representation of its value must be �valid� with respect 19524 * to the {type definition} as defined in String Valid (�3.14.4)." 19525 * TODO: Don't care about the *cononical* stuff here, this requirement 19526 * will be removed in WXS 1.1 anyway. 19527 */ 19528 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, 19529 attr->node, WXS_ATTR_TYPEDEF(attr), 19530 attr->defValue, &(attr->defVal), 19531 1, 1, 0); 19532 if (ret != 0) { 19533 if (ret < 0) { 19534 PERROR_INT("xmlSchemaCheckAttrPropsCorrect", 19535 "calling xmlSchemaVCheckCVCSimpleType()"); 19536 return(-1); 19537 } 19538 xmlSchemaCustomErr(ACTXT_CAST pctxt, 19539 XML_SCHEMAP_A_PROPS_CORRECT_2, 19540 NULL, WXS_BASIC_CAST attr, 19541 "The value of the value constraint is not valid", 19542 NULL, NULL); 19543 return(pctxt->err); 19544 } 19545 } 19546 19547 return(0); 19548} 19549 19550static xmlSchemaElementPtr 19551xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl, 19552 xmlSchemaElementPtr ancestor) 19553{ 19554 xmlSchemaElementPtr ret; 19555 19556 if (WXS_SUBST_HEAD(ancestor) == NULL) 19557 return (NULL); 19558 if (WXS_SUBST_HEAD(ancestor) == elemDecl) 19559 return (ancestor); 19560 19561 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR) 19562 return (NULL); 19563 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR; 19564 ret = xmlSchemaCheckSubstGroupCircular(elemDecl, 19565 WXS_SUBST_HEAD(ancestor)); 19566 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR; 19567 19568 return (ret); 19569} 19570 19571/** 19572 * xmlSchemaCheckElemPropsCorrect: 19573 * @ctxt: a schema parser context 19574 * @decl: the element declaration 19575 * @name: the name of the attribute 19576 * 19577 * Schema Component Constraint: 19578 * Element Declaration Properties Correct (e-props-correct) 19579 * 19580 * STATUS: 19581 * missing: (6) 19582 */ 19583static int 19584xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt, 19585 xmlSchemaElementPtr elemDecl) 19586{ 19587 int ret = 0; 19588 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl); 19589 /* 19590 * SPEC (1) "The values of the properties of an element declaration 19591 * must be as described in the property tableau in The Element 19592 * Declaration Schema Component (�3.3.1), modulo the impact of Missing 19593 * Sub-components (�5.3)." 19594 */ 19595 if (WXS_SUBST_HEAD(elemDecl) != NULL) { 19596 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ; 19597 19598 xmlSchemaCheckElementDeclComponent(head, pctxt); 19599 /* 19600 * SPEC (3) "If there is a non-�absent� {substitution group 19601 * affiliation}, then {scope} must be global." 19602 */ 19603 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) { 19604 xmlSchemaPCustomErr(pctxt, 19605 XML_SCHEMAP_E_PROPS_CORRECT_3, 19606 WXS_BASIC_CAST elemDecl, NULL, 19607 "Only global element declarations can have a " 19608 "substitution group affiliation", NULL); 19609 ret = XML_SCHEMAP_E_PROPS_CORRECT_3; 19610 } 19611 /* 19612 * TODO: SPEC (6) "Circular substitution groups are disallowed. 19613 * That is, it must not be possible to return to an element declaration 19614 * by repeatedly following the {substitution group affiliation} 19615 * property." 19616 */ 19617 if (head == elemDecl) 19618 circ = head; 19619 else if (WXS_SUBST_HEAD(head) != NULL) 19620 circ = xmlSchemaCheckSubstGroupCircular(head, head); 19621 else 19622 circ = NULL; 19623 if (circ != NULL) { 19624 xmlChar *strA = NULL, *strB = NULL; 19625 19626 xmlSchemaPCustomErrExt(pctxt, 19627 XML_SCHEMAP_E_PROPS_CORRECT_6, 19628 WXS_BASIC_CAST circ, NULL, 19629 "The element declaration '%s' defines a circular " 19630 "substitution group to element declaration '%s'", 19631 xmlSchemaGetComponentQName(&strA, circ), 19632 xmlSchemaGetComponentQName(&strB, head), 19633 NULL); 19634 FREE_AND_NULL(strA) 19635 FREE_AND_NULL(strB) 19636 ret = XML_SCHEMAP_E_PROPS_CORRECT_6; 19637 } 19638 /* 19639 * SPEC (4) "If there is a {substitution group affiliation}, 19640 * the {type definition} 19641 * of the element declaration must be validly derived from the {type 19642 * definition} of the {substitution group affiliation}, given the value 19643 * of the {substitution group exclusions} of the {substitution group 19644 * affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6) 19645 * (if the {type definition} is complex) or as defined in 19646 * Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is 19647 * simple)." 19648 * 19649 * NOTE: {substitution group exclusions} means the values of the 19650 * attribute "final". 19651 */ 19652 19653 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) { 19654 int set = 0; 19655 19656 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION) 19657 set |= SUBSET_EXTENSION; 19658 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION) 19659 set |= SUBSET_RESTRICTION; 19660 19661 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef, 19662 WXS_ELEM_TYPEDEF(head), set) != 0) { 19663 xmlChar *strA = NULL, *strB = NULL, *strC = NULL; 19664 19665 ret = XML_SCHEMAP_E_PROPS_CORRECT_4; 19666 xmlSchemaPCustomErrExt(pctxt, 19667 XML_SCHEMAP_E_PROPS_CORRECT_4, 19668 WXS_BASIC_CAST elemDecl, NULL, 19669 "The type definition '%s' was " 19670 "either rejected by the substitution group " 19671 "affiliation '%s', or not validly derived from its type " 19672 "definition '%s'", 19673 xmlSchemaGetComponentQName(&strA, typeDef), 19674 xmlSchemaGetComponentQName(&strB, head), 19675 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head))); 19676 FREE_AND_NULL(strA) 19677 FREE_AND_NULL(strB) 19678 FREE_AND_NULL(strC) 19679 } 19680 } 19681 } 19682 /* 19683 * SPEC (5) "If the {type definition} or {type definition}'s 19684 * {content type} 19685 * is or is derived from ID then there must not be a {value constraint}. 19686 * Note: The use of ID as a type definition for elements goes beyond 19687 * XML 1.0, and should be avoided if backwards compatibility is desired" 19688 */ 19689 if ((elemDecl->value != NULL) && 19690 ((WXS_IS_SIMPLE(typeDef) && 19691 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) || 19692 (WXS_IS_COMPLEX(typeDef) && 19693 WXS_HAS_SIMPLE_CONTENT(typeDef) && 19694 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef, 19695 XML_SCHEMAS_ID)))) { 19696 19697 ret = XML_SCHEMAP_E_PROPS_CORRECT_5; 19698 xmlSchemaPCustomErr(pctxt, 19699 XML_SCHEMAP_E_PROPS_CORRECT_5, 19700 WXS_BASIC_CAST elemDecl, NULL, 19701 "The type definition (or type definition's content type) is or " 19702 "is derived from ID; value constraints are not allowed in " 19703 "conjunction with such a type definition", NULL); 19704 } else if (elemDecl->value != NULL) { 19705 int vcret; 19706 xmlNodePtr node = NULL; 19707 19708 /* 19709 * SPEC (2) "If there is a {value constraint}, the canonical lexical 19710 * representation of its value must be �valid� with respect to the 19711 * {type definition} as defined in Element Default Valid (Immediate) 19712 * (�3.3.6)." 19713 */ 19714 if (typeDef == NULL) { 19715 xmlSchemaPErr(pctxt, elemDecl->node, 19716 XML_SCHEMAP_INTERNAL, 19717 "Internal error: xmlSchemaCheckElemPropsCorrect, " 19718 "type is missing... skipping validation of " 19719 "the value constraint", NULL, NULL); 19720 return (-1); 19721 } 19722 if (elemDecl->node != NULL) { 19723 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) 19724 node = (xmlNodePtr) xmlHasProp(elemDecl->node, 19725 BAD_CAST "fixed"); 19726 else 19727 node = (xmlNodePtr) xmlHasProp(elemDecl->node, 19728 BAD_CAST "default"); 19729 } 19730 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node, 19731 typeDef, elemDecl->value, &(elemDecl->defVal)); 19732 if (vcret != 0) { 19733 if (vcret < 0) { 19734 PERROR_INT("xmlSchemaElemCheckValConstr", 19735 "failed to validate the value constraint of an " 19736 "element declaration"); 19737 return (-1); 19738 } 19739 return (vcret); 19740 } 19741 } 19742 19743 return (ret); 19744} 19745 19746/** 19747 * xmlSchemaCheckElemSubstGroup: 19748 * @ctxt: a schema parser context 19749 * @decl: the element declaration 19750 * @name: the name of the attribute 19751 * 19752 * Schema Component Constraint: 19753 * Substitution Group (cos-equiv-class) 19754 * 19755 * In Libxml2 the subst. groups will be precomputed, in terms of that 19756 * a list will be built for each subst. group head, holding all direct 19757 * referents to this head. 19758 * NOTE that this function needs: 19759 * 1. circular subst. groups to be checked beforehand 19760 * 2. the declaration's type to be derived from the head's type 19761 * 19762 * STATUS: 19763 * 19764 */ 19765static void 19766xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt, 19767 xmlSchemaElementPtr elemDecl) 19768{ 19769 if ((WXS_SUBST_HEAD(elemDecl) == NULL) || 19770 /* SPEC (1) "Its {abstract} is false." */ 19771 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)) 19772 return; 19773 { 19774 xmlSchemaElementPtr head; 19775 xmlSchemaTypePtr headType, type; 19776 int set, methSet; 19777 /* 19778 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's 19779 * {disallowed substitutions} as the blocking constraint, as defined in 19780 * Substitution Group OK (Transitive) (�3.3.6)." 19781 */ 19782 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL; 19783 head = WXS_SUBST_HEAD(head)) { 19784 set = 0; 19785 methSet = 0; 19786 /* 19787 * The blocking constraints. 19788 */ 19789 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) 19790 continue; 19791 headType = head->subtypes; 19792 type = elemDecl->subtypes; 19793 if (headType == type) 19794 goto add_member; 19795 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) 19796 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; 19797 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) 19798 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; 19799 /* 19800 * SPEC: Substitution Group OK (Transitive) (2.3) 19801 * "The set of all {derivation method}s involved in the 19802 * derivation of D's {type definition} from C's {type definition} 19803 * does not intersect with the union of the blocking constraint, 19804 * C's {prohibited substitutions} (if C is complex, otherwise the 19805 * empty set) and the {prohibited substitutions} (respectively the 19806 * empty set) of any intermediate {type definition}s in the 19807 * derivation of D's {type definition} from C's {type definition}." 19808 */ 19809 /* 19810 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the 19811 * subst.head axis, the methSet does not need to be computed for 19812 * the full depth over and over. 19813 */ 19814 /* 19815 * The set of all {derivation method}s involved in the derivation 19816 */ 19817 while ((type != NULL) && (type != headType)) { 19818 if ((WXS_IS_EXTENSION(type)) && 19819 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0)) 19820 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; 19821 19822 if (WXS_IS_RESTRICTION(type) && 19823 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0)) 19824 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; 19825 19826 type = type->baseType; 19827 } 19828 /* 19829 * The {prohibited substitutions} of all intermediate types + 19830 * the head's type. 19831 */ 19832 type = elemDecl->subtypes->baseType; 19833 while (type != NULL) { 19834 if (WXS_IS_COMPLEX(type)) { 19835 if ((type->flags & 19836 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) && 19837 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0)) 19838 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; 19839 if ((type->flags & 19840 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) && 19841 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0)) 19842 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; 19843 } else 19844 break; 19845 if (type == headType) 19846 break; 19847 type = type->baseType; 19848 } 19849 if ((set != 0) && 19850 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) && 19851 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) || 19852 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) && 19853 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) { 19854 continue; 19855 } 19856add_member: 19857 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl); 19858 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0) 19859 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD; 19860 } 19861 } 19862} 19863 19864#ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */ 19865/** 19866 * xmlSchemaCheckElementDeclComponent 19867 * @pctxt: the schema parser context 19868 * @ctxtComponent: the context component (an element declaration) 19869 * @ctxtParticle: the first particle of the context component 19870 * @searchParticle: the element declaration particle to be analysed 19871 * 19872 * Schema Component Constraint: Element Declarations Consistent 19873 */ 19874static int 19875xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt, 19876 xmlSchemaBasicItemPtr ctxtComponent, 19877 xmlSchemaParticlePtr ctxtParticle, 19878 xmlSchemaParticlePtr searchParticle, 19879 xmlSchemaParticlePtr curParticle, 19880 int search) 19881{ 19882 return(0); 19883 19884 int ret = 0; 19885 xmlSchemaParticlePtr cur = curParticle; 19886 if (curParticle == NULL) { 19887 return(0); 19888 } 19889 if (WXS_PARTICLE_TERM(curParticle) == NULL) { 19890 /* 19891 * Just return in this case. A missing "term" of the particle 19892 * might arise due to an invalid "term" component. 19893 */ 19894 return(0); 19895 } 19896 while (cur != NULL) { 19897 switch (WXS_PARTICLE_TERM(cur)->type) { 19898 case XML_SCHEMA_TYPE_ANY: 19899 break; 19900 case XML_SCHEMA_TYPE_ELEMENT: 19901 if (search == 0) { 19902 ret = xmlSchemaCheckElementDeclConsistent(pctxt, 19903 ctxtComponent, ctxtParticle, cur, ctxtParticle, 1); 19904 if (ret != 0) 19905 return(ret); 19906 } else { 19907 xmlSchemaElementPtr elem = 19908 WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur)); 19909 /* 19910 * SPEC Element Declarations Consistent: 19911 * "If the {particles} contains, either directly, 19912 * indirectly (that is, within the {particles} of a 19913 * contained model group, recursively) or �implicitly� 19914 * two or more element declaration particles with 19915 * the same {name} and {target namespace}, then 19916 * all their type definitions must be the same 19917 * top-level definition [...]" 19918 */ 19919 if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name, 19920 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) && 19921 xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace, 19922 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace)) 19923 { 19924 xmlChar *strA = NULL, *strB = NULL; 19925 19926 xmlSchemaCustomErr(ACTXT_CAST pctxt, 19927 /* TODO: error code */ 19928 XML_SCHEMAP_COS_NONAMBIG, 19929 WXS_ITEM_NODE(cur), NULL, 19930 "In the content model of %s, there are multiple " 19931 "element declarations for '%s' with different " 19932 "type definitions", 19933 xmlSchemaGetComponentDesignation(&strA, 19934 ctxtComponent), 19935 xmlSchemaFormatQName(&strB, 19936 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace, 19937 WXS_PARTICLE_TERM_AS_ELEM(cur)->name)); 19938 FREE_AND_NULL(strA); 19939 FREE_AND_NULL(strB); 19940 return(XML_SCHEMAP_COS_NONAMBIG); 19941 } 19942 } 19943 break; 19944 case XML_SCHEMA_TYPE_SEQUENCE: { 19945 break; 19946 } 19947 case XML_SCHEMA_TYPE_CHOICE:{ 19948 /* 19949 xmlSchemaTreeItemPtr sub; 19950 19951 sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr) 19952 while (sub != NULL) { 19953 ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent, 19954 ctxtParticle, ctxtElem); 19955 if (ret != 0) 19956 return(ret); 19957 sub = sub->next; 19958 } 19959 */ 19960 break; 19961 } 19962 case XML_SCHEMA_TYPE_ALL: 19963 break; 19964 case XML_SCHEMA_TYPE_GROUP: 19965 break; 19966 default: 19967 xmlSchemaInternalErr2(ACTXT_CAST pctxt, 19968 "xmlSchemaCheckElementDeclConsistent", 19969 "found unexpected term of type '%s' in content model", 19970 WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL); 19971 return(-1); 19972 } 19973 cur = (xmlSchemaParticlePtr) cur->next; 19974 } 19975 19976exit: 19977 return(ret); 19978} 19979#endif 19980 19981/** 19982 * xmlSchemaCheckElementDeclComponent 19983 * @item: an schema element declaration/particle 19984 * @ctxt: a schema parser context 19985 * @name: the name of the attribute 19986 * 19987 * Validates the value constraints of an element declaration. 19988 * Adds substitution group members. 19989 */ 19990static void 19991xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl, 19992 xmlSchemaParserCtxtPtr ctxt) 19993{ 19994 if (elemDecl == NULL) 19995 return; 19996 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) 19997 return; 19998 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED; 19999 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) { 20000 /* 20001 * Adds substitution group members. 20002 */ 20003 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl); 20004 } 20005} 20006 20007/** 20008 * xmlSchemaResolveModelGroupParticleReferences: 20009 * @particle: a particle component 20010 * @ctxt: a parser context 20011 * 20012 * Resolves references of a model group's {particles} to 20013 * model group definitions and to element declarations. 20014 */ 20015static void 20016xmlSchemaResolveModelGroupParticleReferences( 20017 xmlSchemaParserCtxtPtr ctxt, 20018 xmlSchemaModelGroupPtr mg) 20019{ 20020 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg); 20021 xmlSchemaQNameRefPtr ref; 20022 xmlSchemaBasicItemPtr refItem; 20023 20024 /* 20025 * URGENT TODO: Test this. 20026 */ 20027 while (particle != NULL) { 20028 if ((WXS_PARTICLE_TERM(particle) == NULL) || 20029 ((WXS_PARTICLE_TERM(particle))->type != 20030 XML_SCHEMA_EXTRA_QNAMEREF)) 20031 { 20032 goto next_particle; 20033 } 20034 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle); 20035 /* 20036 * Resolve the reference. 20037 * NULL the {term} by default. 20038 */ 20039 particle->children = NULL; 20040 20041 refItem = xmlSchemaGetNamedComponent(ctxt->schema, 20042 ref->itemType, ref->name, ref->targetNamespace); 20043 if (refItem == NULL) { 20044 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE, 20045 NULL, WXS_ITEM_NODE(particle), "ref", ref->name, 20046 ref->targetNamespace, ref->itemType, NULL); 20047 /* TODO: remove the particle. */ 20048 goto next_particle; 20049 } 20050 if (refItem->type == XML_SCHEMA_TYPE_GROUP) { 20051 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL) 20052 /* TODO: remove the particle. */ 20053 goto next_particle; 20054 /* 20055 * NOTE that we will assign the model group definition 20056 * itself to the "term" of the particle. This will ease 20057 * the check for circular model group definitions. After 20058 * that the "term" will be assigned the model group of the 20059 * model group definition. 20060 */ 20061 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type == 20062 XML_SCHEMA_TYPE_ALL) { 20063 /* 20064 * SPEC cos-all-limited (1) 20065 * SPEC cos-all-limited (1.2) 20066 * "It appears only as the value of one or both of the 20067 * following properties:" 20068 * (1.1) "the {model group} property of a model group 20069 * definition." 20070 * (1.2) "the {term} property of a particle [... of] the " 20071 * {content type} of a complex type definition." 20072 */ 20073 xmlSchemaCustomErr(ACTXT_CAST ctxt, 20074 /* TODO: error code */ 20075 XML_SCHEMAP_COS_ALL_LIMITED, 20076 WXS_ITEM_NODE(particle), NULL, 20077 "A model group definition is referenced, but " 20078 "it contains an 'all' model group, which " 20079 "cannot be contained by model groups", 20080 NULL, NULL); 20081 /* TODO: remove the particle. */ 20082 goto next_particle; 20083 } 20084 particle->children = (xmlSchemaTreeItemPtr) refItem; 20085 } else { 20086 /* 20087 * TODO: Are referenced element declarations the only 20088 * other components we expect here? 20089 */ 20090 particle->children = (xmlSchemaTreeItemPtr) refItem; 20091 } 20092next_particle: 20093 particle = WXS_PTC_CAST particle->next; 20094 } 20095} 20096 20097static int 20098xmlSchemaAreValuesEqual(xmlSchemaValPtr x, 20099 xmlSchemaValPtr y) 20100{ 20101 xmlSchemaTypePtr tx, ty, ptx, pty; 20102 int ret; 20103 20104 while (x != NULL) { 20105 /* Same types. */ 20106 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x)); 20107 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y)); 20108 ptx = xmlSchemaGetPrimitiveType(tx); 20109 pty = xmlSchemaGetPrimitiveType(ty); 20110 /* 20111 * (1) if a datatype T' is �derived� by �restriction� from an 20112 * atomic datatype T then the �value space� of T' is a subset of 20113 * the �value space� of T. */ 20114 /* 20115 * (2) if datatypes T' and T'' are �derived� by �restriction� 20116 * from a common atomic ancestor T then the �value space�s of T' 20117 * and T'' may overlap. 20118 */ 20119 if (ptx != pty) 20120 return(0); 20121 /* 20122 * We assume computed values to be normalized, so do a fast 20123 * string comparison for string based types. 20124 */ 20125 if ((ptx->builtInType == XML_SCHEMAS_STRING) || 20126 WXS_IS_ANY_SIMPLE_TYPE(ptx)) { 20127 if (! xmlStrEqual( 20128 xmlSchemaValueGetAsString(x), 20129 xmlSchemaValueGetAsString(y))) 20130 return (0); 20131 } else { 20132 ret = xmlSchemaCompareValuesWhtsp( 20133 x, XML_SCHEMA_WHITESPACE_PRESERVE, 20134 y, XML_SCHEMA_WHITESPACE_PRESERVE); 20135 if (ret == -2) 20136 return(-1); 20137 if (ret != 0) 20138 return(0); 20139 } 20140 /* 20141 * Lists. 20142 */ 20143 x = xmlSchemaValueGetNext(x); 20144 if (x != NULL) { 20145 y = xmlSchemaValueGetNext(y); 20146 if (y == NULL) 20147 return (0); 20148 } else if (xmlSchemaValueGetNext(y) != NULL) 20149 return (0); 20150 else 20151 return (1); 20152 } 20153 return (0); 20154} 20155 20156/** 20157 * xmlSchemaResolveAttrUseReferences: 20158 * @item: an attribute use 20159 * @ctxt: a parser context 20160 * 20161 * Resolves the referenced attribute declaration. 20162 */ 20163static int 20164xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause, 20165 xmlSchemaParserCtxtPtr ctxt) 20166{ 20167 if ((ctxt == NULL) || (ause == NULL)) 20168 return(-1); 20169 if ((ause->attrDecl == NULL) || 20170 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF)) 20171 return(0); 20172 20173 { 20174 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl; 20175 20176 /* 20177 * TODO: Evaluate, what errors could occur if the declaration is not 20178 * found. 20179 */ 20180 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema, 20181 ref->name, ref->targetNamespace); 20182 if (ause->attrDecl == NULL) { 20183 xmlSchemaPResCompAttrErr(ctxt, 20184 XML_SCHEMAP_SRC_RESOLVE, 20185 WXS_BASIC_CAST ause, ause->node, 20186 "ref", ref->name, ref->targetNamespace, 20187 XML_SCHEMA_TYPE_ATTRIBUTE, NULL); 20188 return(ctxt->err);; 20189 } 20190 } 20191 return(0); 20192} 20193 20194/** 20195 * xmlSchemaCheckAttrUsePropsCorrect: 20196 * @ctxt: a parser context 20197 * @use: an attribute use 20198 * 20199 * Schema Component Constraint: 20200 * Attribute Use Correct (au-props-correct) 20201 * 20202 */ 20203static int 20204xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt, 20205 xmlSchemaAttributeUsePtr use) 20206{ 20207 if ((ctxt == NULL) || (use == NULL)) 20208 return(-1); 20209 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) || 20210 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE)) 20211 return(0); 20212 20213 /* 20214 * SPEC au-props-correct (1) 20215 * "The values of the properties of an attribute use must be as 20216 * described in the property tableau in The Attribute Use Schema 20217 * Component (�3.5.1), modulo the impact of Missing 20218 * Sub-components (�5.3)." 20219 */ 20220 20221 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) && 20222 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) && 20223 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0)) 20224 { 20225 xmlSchemaPCustomErr(ctxt, 20226 XML_SCHEMAP_AU_PROPS_CORRECT_2, 20227 WXS_BASIC_CAST use, NULL, 20228 "The attribute declaration has a 'fixed' value constraint " 20229 ", thus the attribute use must also have a 'fixed' value " 20230 "constraint", 20231 NULL); 20232 return(ctxt->err); 20233 } 20234 /* 20235 * Compute and check the value constraint's value. 20236 */ 20237 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) { 20238 int ret; 20239 /* 20240 * TODO: The spec seems to be missing a check of the 20241 * value constraint of the attribute use. We will do it here. 20242 */ 20243 /* 20244 * SPEC a-props-correct (3) 20245 */ 20246 if (xmlSchemaIsDerivedFromBuiltInType( 20247 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID)) 20248 { 20249 xmlSchemaCustomErr(ACTXT_CAST ctxt, 20250 XML_SCHEMAP_AU_PROPS_CORRECT, 20251 NULL, WXS_BASIC_CAST use, 20252 "Value constraints are not allowed if the type definition " 20253 "is or is derived from xs:ID", 20254 NULL, NULL); 20255 return(ctxt->err); 20256 } 20257 20258 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt, 20259 use->node, WXS_ATTRUSE_TYPEDEF(use), 20260 use->defValue, &(use->defVal), 20261 1, 1, 0); 20262 if (ret != 0) { 20263 if (ret < 0) { 20264 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect", 20265 "calling xmlSchemaVCheckCVCSimpleType()"); 20266 return(-1); 20267 } 20268 xmlSchemaCustomErr(ACTXT_CAST ctxt, 20269 XML_SCHEMAP_AU_PROPS_CORRECT, 20270 NULL, WXS_BASIC_CAST use, 20271 "The value of the value constraint is not valid", 20272 NULL, NULL); 20273 return(ctxt->err); 20274 } 20275 } 20276 /* 20277 * SPEC au-props-correct (2) 20278 * "If the {attribute declaration} has a fixed 20279 * {value constraint}, then if the attribute use itself has a 20280 * {value constraint}, it must also be fixed and its value must match 20281 * that of the {attribute declaration}'s {value constraint}." 20282 */ 20283 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) && 20284 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0)) 20285 { 20286 if (! xmlSchemaAreValuesEqual(use->defVal, 20287 (WXS_ATTRUSE_DECL(use))->defVal)) 20288 { 20289 xmlSchemaPCustomErr(ctxt, 20290 XML_SCHEMAP_AU_PROPS_CORRECT_2, 20291 WXS_BASIC_CAST use, NULL, 20292 "The 'fixed' value constraint of the attribute use " 20293 "must match the attribute declaration's value " 20294 "constraint '%s'", 20295 (WXS_ATTRUSE_DECL(use))->defValue); 20296 } 20297 return(ctxt->err); 20298 } 20299 return(0); 20300} 20301 20302 20303 20304 20305/** 20306 * xmlSchemaResolveAttrTypeReferences: 20307 * @item: an attribute declaration 20308 * @ctxt: a parser context 20309 * 20310 * Resolves the referenced type definition component. 20311 */ 20312static int 20313xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item, 20314 xmlSchemaParserCtxtPtr ctxt) 20315{ 20316 /* 20317 * The simple type definition corresponding to the <simpleType> element 20318 * information item in the [children], if present, otherwise the simple 20319 * type definition �resolved� to by the �actual value� of the type 20320 * [attribute], if present, otherwise the �simple ur-type definition�. 20321 */ 20322 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED) 20323 return(0); 20324 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED; 20325 if (item->subtypes != NULL) 20326 return(0); 20327 if (item->typeName != NULL) { 20328 xmlSchemaTypePtr type; 20329 20330 type = xmlSchemaGetType(ctxt->schema, item->typeName, 20331 item->typeNs); 20332 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) { 20333 xmlSchemaPResCompAttrErr(ctxt, 20334 XML_SCHEMAP_SRC_RESOLVE, 20335 WXS_BASIC_CAST item, item->node, 20336 "type", item->typeName, item->typeNs, 20337 XML_SCHEMA_TYPE_SIMPLE, NULL); 20338 return(ctxt->err); 20339 } else 20340 item->subtypes = type; 20341 20342 } else { 20343 /* 20344 * The type defaults to the xs:anySimpleType. 20345 */ 20346 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE); 20347 } 20348 return(0); 20349} 20350 20351/** 20352 * xmlSchemaResolveIDCKeyReferences: 20353 * @idc: the identity-constraint definition 20354 * @ctxt: the schema parser context 20355 * @name: the attribute name 20356 * 20357 * Resolve keyRef references to key/unique IDCs. 20358 * Schema Component Constraint: 20359 * Identity-constraint Definition Properties Correct (c-props-correct) 20360 */ 20361static int 20362xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc, 20363 xmlSchemaParserCtxtPtr pctxt) 20364{ 20365 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) 20366 return(0); 20367 if (idc->ref->name != NULL) { 20368 idc->ref->item = (xmlSchemaBasicItemPtr) 20369 xmlSchemaGetIDC(pctxt->schema, idc->ref->name, 20370 idc->ref->targetNamespace); 20371 if (idc->ref->item == NULL) { 20372 /* 20373 * TODO: It is actually not an error to fail to resolve 20374 * at this stage. BUT we need to be that strict! 20375 */ 20376 xmlSchemaPResCompAttrErr(pctxt, 20377 XML_SCHEMAP_SRC_RESOLVE, 20378 WXS_BASIC_CAST idc, idc->node, 20379 "refer", idc->ref->name, 20380 idc->ref->targetNamespace, 20381 XML_SCHEMA_TYPE_IDC_KEY, NULL); 20382 return(pctxt->err); 20383 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) { 20384 /* 20385 * SPEC c-props-correct (1) 20386 */ 20387 xmlSchemaCustomErr(ACTXT_CAST pctxt, 20388 XML_SCHEMAP_C_PROPS_CORRECT, 20389 NULL, WXS_BASIC_CAST idc, 20390 "The keyref references a keyref", 20391 NULL, NULL); 20392 idc->ref->item = NULL; 20393 return(pctxt->err); 20394 } else { 20395 if (idc->nbFields != 20396 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) { 20397 xmlChar *str = NULL; 20398 xmlSchemaIDCPtr refer; 20399 20400 refer = (xmlSchemaIDCPtr) idc->ref->item; 20401 /* 20402 * SPEC c-props-correct(2) 20403 * "If the {identity-constraint category} is keyref, 20404 * the cardinality of the {fields} must equal that of 20405 * the {fields} of the {referenced key}. 20406 */ 20407 xmlSchemaCustomErr(ACTXT_CAST pctxt, 20408 XML_SCHEMAP_C_PROPS_CORRECT, 20409 NULL, WXS_BASIC_CAST idc, 20410 "The cardinality of the keyref differs from the " 20411 "cardinality of the referenced key/unique '%s'", 20412 xmlSchemaFormatQName(&str, refer->targetNamespace, 20413 refer->name), 20414 NULL); 20415 FREE_AND_NULL(str) 20416 return(pctxt->err); 20417 } 20418 } 20419 } 20420 return(0); 20421} 20422 20423static int 20424xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib, 20425 xmlSchemaParserCtxtPtr pctxt) 20426{ 20427 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name, 20428 prohib->targetNamespace) == NULL) { 20429 20430 xmlSchemaPResCompAttrErr(pctxt, 20431 XML_SCHEMAP_SRC_RESOLVE, 20432 NULL, prohib->node, 20433 "ref", prohib->name, prohib->targetNamespace, 20434 XML_SCHEMA_TYPE_ATTRIBUTE, NULL); 20435 return(XML_SCHEMAP_SRC_RESOLVE); 20436 } 20437 return(0); 20438} 20439 20440#define WXS_REDEFINED_TYPE(c) \ 20441(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED) 20442 20443#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \ 20444(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED) 20445 20446#define WXS_REDEFINED_ATTR_GROUP(c) \ 20447(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED) 20448 20449static int 20450xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt) 20451{ 20452 int err = 0; 20453 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs; 20454 xmlSchemaBasicItemPtr prev, item; 20455 int wasRedefined; 20456 20457 if (redef == NULL) 20458 return(0); 20459 20460 do { 20461 item = redef->item; 20462 /* 20463 * First try to locate the redefined component in the 20464 * schema graph starting with the redefined schema. 20465 * NOTE: According to this schema bug entry: 20466 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html 20467 * it's not clear if the referenced component needs to originate 20468 * from the <redefine>d schema _document_ or the schema; the latter 20469 * would include all imported and included sub-schemas of the 20470 * <redefine>d schema. Currenlty we latter approach is used. 20471 * SUPPLEMENT: It seems that the WG moves towards the latter 20472 * approach, so we are doing it right. 20473 * 20474 */ 20475 prev = xmlSchemaFindRedefCompInGraph( 20476 redef->targetBucket, item->type, 20477 redef->refName, redef->refTargetNs); 20478 if (prev == NULL) { 20479 xmlChar *str = NULL; 20480 xmlNodePtr node; 20481 20482 /* 20483 * SPEC src-redefine: 20484 * (6.2.1) "The �actual value� of its own name attribute plus 20485 * target namespace must successfully �resolve� to a model 20486 * group definition in I." 20487 * (7.2.1) "The �actual value� of its own name attribute plus 20488 * target namespace must successfully �resolve� to an attribute 20489 * group definition in I." 20490 20491 * 20492 * Note that, if we are redefining with the use of references 20493 * to components, the spec assumes the src-resolve to be used; 20494 * but this won't assure that we search only *inside* the 20495 * redefined schema. 20496 */ 20497 if (redef->reference) 20498 node = WXS_ITEM_NODE(redef->reference); 20499 else 20500 node = WXS_ITEM_NODE(item); 20501 xmlSchemaCustomErr(ACTXT_CAST pctxt, 20502 /* 20503 * TODO: error code. 20504 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the 20505 * reference kind. 20506 */ 20507 XML_SCHEMAP_SRC_REDEFINE, node, NULL, 20508 "The %s '%s' to be redefined could not be found in " 20509 "the redefined schema", 20510 WXS_ITEM_TYPE_NAME(item), 20511 xmlSchemaFormatQName(&str, redef->refTargetNs, 20512 redef->refName)); 20513 FREE_AND_NULL(str); 20514 err = pctxt->err; 20515 redef = redef->next; 20516 continue; 20517 } 20518 /* 20519 * TODO: Obtaining and setting the redefinition state is really 20520 * clumsy. 20521 */ 20522 wasRedefined = 0; 20523 switch (item->type) { 20524 case XML_SCHEMA_TYPE_COMPLEX: 20525 case XML_SCHEMA_TYPE_SIMPLE: 20526 if ((WXS_TYPE_CAST prev)->flags & 20527 XML_SCHEMAS_TYPE_REDEFINED) 20528 { 20529 wasRedefined = 1; 20530 break; 20531 } 20532 /* Mark it as redefined. */ 20533 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED; 20534 /* 20535 * Assign the redefined type to the 20536 * base type of the redefining type. 20537 * TODO: How 20538 */ 20539 ((xmlSchemaTypePtr) item)->baseType = 20540 (xmlSchemaTypePtr) prev; 20541 break; 20542 case XML_SCHEMA_TYPE_GROUP: 20543 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags & 20544 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED) 20545 { 20546 wasRedefined = 1; 20547 break; 20548 } 20549 /* Mark it as redefined. */ 20550 (WXS_MODEL_GROUPDEF_CAST prev)->flags |= 20551 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED; 20552 if (redef->reference != NULL) { 20553 /* 20554 * Overwrite the QName-reference with the 20555 * referenced model group def. 20556 */ 20557 (WXS_PTC_CAST redef->reference)->children = 20558 WXS_TREE_CAST prev; 20559 } 20560 redef->target = prev; 20561 break; 20562 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: 20563 if ((WXS_ATTR_GROUP_CAST prev)->flags & 20564 XML_SCHEMAS_ATTRGROUP_REDEFINED) 20565 { 20566 wasRedefined = 1; 20567 break; 20568 } 20569 (WXS_ATTR_GROUP_CAST prev)->flags |= 20570 XML_SCHEMAS_ATTRGROUP_REDEFINED; 20571 if (redef->reference != NULL) { 20572 /* 20573 * Assign the redefined attribute group to the 20574 * QName-reference component. 20575 * This is the easy case, since we will just 20576 * expand the redefined group. 20577 */ 20578 (WXS_QNAME_CAST redef->reference)->item = prev; 20579 redef->target = NULL; 20580 } else { 20581 /* 20582 * This is the complicated case: we need 20583 * to apply src-redefine (7.2.2) at a later 20584 * stage, i.e. when attribute group references 20585 * have beed expanded and simple types have 20586 * beed fixed. 20587 */ 20588 redef->target = prev; 20589 } 20590 break; 20591 default: 20592 PERROR_INT("xmlSchemaResolveRedefReferences", 20593 "Unexpected redefined component type"); 20594 return(-1); 20595 } 20596 if (wasRedefined) { 20597 xmlChar *str = NULL; 20598 xmlNodePtr node; 20599 20600 if (redef->reference) 20601 node = WXS_ITEM_NODE(redef->reference); 20602 else 20603 node = WXS_ITEM_NODE(redef->item); 20604 20605 xmlSchemaCustomErr(ACTXT_CAST pctxt, 20606 /* TODO: error code. */ 20607 XML_SCHEMAP_SRC_REDEFINE, 20608 node, NULL, 20609 "The referenced %s was already redefined. Multiple " 20610 "redefinition of the same component is not supported", 20611 xmlSchemaGetComponentDesignation(&str, prev), 20612 NULL); 20613 FREE_AND_NULL(str) 20614 err = pctxt->err; 20615 redef = redef->next; 20616 continue; 20617 } 20618 redef = redef->next; 20619 } while (redef != NULL); 20620 20621 return(err); 20622} 20623 20624static int 20625xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt) 20626{ 20627 int err = 0; 20628 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs; 20629 xmlSchemaBasicItemPtr item; 20630 20631 if (redef == NULL) 20632 return(0); 20633 20634 do { 20635 if (redef->target == NULL) { 20636 redef = redef->next; 20637 continue; 20638 } 20639 item = redef->item; 20640 20641 switch (item->type) { 20642 case XML_SCHEMA_TYPE_SIMPLE: 20643 case XML_SCHEMA_TYPE_COMPLEX: 20644 /* 20645 * Since the spec wants the {name} of the redefined 20646 * type to be 'absent', we'll NULL it. 20647 */ 20648 (WXS_TYPE_CAST redef->target)->name = NULL; 20649 20650 /* 20651 * TODO: Seems like there's nothing more to do. The normal 20652 * inheritance mechanism is used. But not 100% sure. 20653 */ 20654 break; 20655 case XML_SCHEMA_TYPE_GROUP: 20656 /* 20657 * URGENT TODO: 20658 * SPEC src-redefine: 20659 * (6.2.2) "The {model group} of the model group definition 20660 * which corresponds to it per XML Representation of Model 20661 * Group Definition Schema Components (�3.7.2) must be a 20662 * �valid restriction� of the {model group} of that model 20663 * group definition in I, as defined in Particle Valid 20664 * (Restriction) (�3.9.6)." 20665 */ 20666 break; 20667 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: 20668 /* 20669 * SPEC src-redefine: 20670 * (7.2.2) "The {attribute uses} and {attribute wildcard} of 20671 * the attribute group definition which corresponds to it 20672 * per XML Representation of Attribute Group Definition Schema 20673 * Components (�3.6.2) must be �valid restrictions� of the 20674 * {attribute uses} and {attribute wildcard} of that attribute 20675 * group definition in I, as defined in clause 2, clause 3 and 20676 * clause 4 of Derivation Valid (Restriction, Complex) 20677 * (�3.4.6) (where references to the base type definition are 20678 * understood as references to the attribute group definition 20679 * in I)." 20680 */ 20681 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt, 20682 XML_SCHEMA_ACTION_REDEFINE, 20683 item, redef->target, 20684 (WXS_ATTR_GROUP_CAST item)->attrUses, 20685 (WXS_ATTR_GROUP_CAST redef->target)->attrUses, 20686 (WXS_ATTR_GROUP_CAST item)->attributeWildcard, 20687 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard); 20688 if (err == -1) 20689 return(-1); 20690 break; 20691 default: 20692 break; 20693 } 20694 redef = redef->next; 20695 } while (redef != NULL); 20696 return(0); 20697} 20698 20699 20700static int 20701xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt, 20702 xmlSchemaBucketPtr bucket) 20703{ 20704 xmlSchemaBasicItemPtr item; 20705 int err; 20706 xmlHashTablePtr *table; 20707 const xmlChar *name; 20708 int i; 20709 20710#define WXS_GET_GLOBAL_HASH(c, slot) { \ 20711 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \ 20712 table = &(WXS_IMPBUCKET((c))->schema->slot); \ 20713 else \ 20714 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); } 20715 20716 /* 20717 * Add global components to the schema's hash tables. 20718 * This is the place where duplicate components will be 20719 * detected. 20720 * TODO: I think normally we should support imports of the 20721 * same namespace from multiple locations. We don't do currently, 20722 * but if we do then according to: 20723 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224 20724 * we would need, if imported directly, to import redefined 20725 * components as well to be able to catch clashing components. 20726 * (I hope I'll still know what this means after some months :-() 20727 */ 20728 if (bucket == NULL) 20729 return(-1); 20730 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) 20731 return(0); 20732 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED; 20733 20734 for (i = 0; i < bucket->globals->nbItems; i++) { 20735 item = bucket->globals->items[i]; 20736 table = NULL; 20737 switch (item->type) { 20738 case XML_SCHEMA_TYPE_COMPLEX: 20739 case XML_SCHEMA_TYPE_SIMPLE: 20740 if (WXS_REDEFINED_TYPE(item)) 20741 continue; 20742 name = (WXS_TYPE_CAST item)->name; 20743 WXS_GET_GLOBAL_HASH(bucket, typeDecl) 20744 break; 20745 case XML_SCHEMA_TYPE_ELEMENT: 20746 name = (WXS_ELEM_CAST item)->name; 20747 WXS_GET_GLOBAL_HASH(bucket, elemDecl) 20748 break; 20749 case XML_SCHEMA_TYPE_ATTRIBUTE: 20750 name = (WXS_ATTR_CAST item)->name; 20751 WXS_GET_GLOBAL_HASH(bucket, attrDecl) 20752 break; 20753 case XML_SCHEMA_TYPE_GROUP: 20754 if (WXS_REDEFINED_MODEL_GROUP_DEF(item)) 20755 continue; 20756 name = (WXS_MODEL_GROUPDEF_CAST item)->name; 20757 WXS_GET_GLOBAL_HASH(bucket, groupDecl) 20758 break; 20759 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: 20760 if (WXS_REDEFINED_ATTR_GROUP(item)) 20761 continue; 20762 name = (WXS_ATTR_GROUP_CAST item)->name; 20763 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl) 20764 break; 20765 case XML_SCHEMA_TYPE_IDC_KEY: 20766 case XML_SCHEMA_TYPE_IDC_UNIQUE: 20767 case XML_SCHEMA_TYPE_IDC_KEYREF: 20768 name = (WXS_IDC_CAST item)->name; 20769 WXS_GET_GLOBAL_HASH(bucket, idcDef) 20770 break; 20771 case XML_SCHEMA_TYPE_NOTATION: 20772 name = ((xmlSchemaNotationPtr) item)->name; 20773 WXS_GET_GLOBAL_HASH(bucket, notaDecl) 20774 break; 20775 default: 20776 PERROR_INT("xmlSchemaAddComponents", 20777 "Unexpected global component type"); 20778 continue; 20779 } 20780 if (*table == NULL) { 20781 *table = xmlHashCreateDict(10, pctxt->dict); 20782 if (*table == NULL) { 20783 PERROR_INT("xmlSchemaAddComponents", 20784 "failed to create a component hash table"); 20785 return(-1); 20786 } 20787 } 20788 err = xmlHashAddEntry(*table, name, item); 20789 if (err != 0) { 20790 xmlChar *str = NULL; 20791 20792 xmlSchemaCustomErr(ACTXT_CAST pctxt, 20793 XML_SCHEMAP_REDEFINED_TYPE, 20794 WXS_ITEM_NODE(item), 20795 WXS_BASIC_CAST item, 20796 "A global %s '%s' does already exist", 20797 WXS_ITEM_TYPE_NAME(item), 20798 xmlSchemaGetComponentQName(&str, item)); 20799 FREE_AND_NULL(str); 20800 } 20801 } 20802 /* 20803 * Process imported/included schemas. 20804 */ 20805 if (bucket->relations != NULL) { 20806 xmlSchemaSchemaRelationPtr rel = bucket->relations; 20807 do { 20808 if ((rel->bucket != NULL) && 20809 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) { 20810 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1) 20811 return(-1); 20812 } 20813 rel = rel->next; 20814 } while (rel != NULL); 20815 } 20816 return(0); 20817} 20818 20819static int 20820xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt, 20821 xmlSchemaBucketPtr rootBucket) 20822{ 20823 xmlSchemaConstructionCtxtPtr con = pctxt->constructor; 20824 xmlSchemaTreeItemPtr item, *items; 20825 int nbItems, i, ret = 0; 20826 xmlSchemaBucketPtr oldbucket = con->bucket; 20827 xmlSchemaElementPtr elemDecl; 20828 20829#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure; 20830 20831 if ((con->pending == NULL) || 20832 (con->pending->nbItems == 0)) 20833 return(0); 20834 20835 /* 20836 * Since xmlSchemaFixupComplexType() will create new particles 20837 * (local components), and those particle components need a bucket 20838 * on the constructor, we'll assure here that the constructor has 20839 * a bucket. 20840 * TODO: Think about storing locals _only_ on the main bucket. 20841 */ 20842 if (con->bucket == NULL) 20843 con->bucket = rootBucket; 20844 20845 /* TODO: 20846 * SPEC (src-redefine): 20847 * (6.2) "If it has no such self-reference, then all of the 20848 * following must be true:" 20849 20850 * (6.2.2) The {model group} of the model group definition which 20851 * corresponds to it per XML Representation of Model Group 20852 * Definition Schema Components (�3.7.2) must be a �valid 20853 * restriction� of the {model group} of that model group definition 20854 * in I, as defined in Particle Valid (Restriction) (�3.9.6)." 20855 */ 20856 xmlSchemaCheckSRCRedefineFirst(pctxt); 20857 20858 /* 20859 * Add global components to the schemata's hash tables. 20860 */ 20861 xmlSchemaAddComponents(pctxt, rootBucket); 20862 20863 pctxt->ctxtType = NULL; 20864 items = (xmlSchemaTreeItemPtr *) con->pending->items; 20865 nbItems = con->pending->nbItems; 20866 /* 20867 * Now that we have parsed *all* the schema document(s) and converted 20868 * them to schema components, we can resolve references, apply component 20869 * constraints, create the FSA from the content model, etc. 20870 */ 20871 /* 20872 * Resolve references of.. 20873 * 20874 * 1. element declarations: 20875 * - the type definition 20876 * - the substitution group affiliation 20877 * 2. simple/complex types: 20878 * - the base type definition 20879 * - the memberTypes of union types 20880 * - the itemType of list types 20881 * 3. attributes declarations and attribute uses: 20882 * - the type definition 20883 * - if an attribute use, then the attribute declaration 20884 * 4. attribute group references: 20885 * - the attribute group definition 20886 * 5. particles: 20887 * - the term of the particle (e.g. a model group) 20888 * 6. IDC key-references: 20889 * - the referenced IDC 'key' or 'unique' definition 20890 * 7. Attribute prohibitions which had a "ref" attribute. 20891 */ 20892 for (i = 0; i < nbItems; i++) { 20893 item = items[i]; 20894 switch (item->type) { 20895 case XML_SCHEMA_TYPE_ELEMENT: 20896 xmlSchemaResolveElementReferences( 20897 (xmlSchemaElementPtr) item, pctxt); 20898 FIXHFAILURE; 20899 break; 20900 case XML_SCHEMA_TYPE_COMPLEX: 20901 case XML_SCHEMA_TYPE_SIMPLE: 20902 xmlSchemaResolveTypeReferences( 20903 (xmlSchemaTypePtr) item, pctxt); 20904 FIXHFAILURE; 20905 break; 20906 case XML_SCHEMA_TYPE_ATTRIBUTE: 20907 xmlSchemaResolveAttrTypeReferences( 20908 (xmlSchemaAttributePtr) item, pctxt); 20909 FIXHFAILURE; 20910 break; 20911 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: 20912 xmlSchemaResolveAttrUseReferences( 20913 (xmlSchemaAttributeUsePtr) item, pctxt); 20914 FIXHFAILURE; 20915 break; 20916 case XML_SCHEMA_EXTRA_QNAMEREF: 20917 if ((WXS_QNAME_CAST item)->itemType == 20918 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) 20919 { 20920 xmlSchemaResolveAttrGroupReferences( 20921 WXS_QNAME_CAST item, pctxt); 20922 } 20923 FIXHFAILURE; 20924 break; 20925 case XML_SCHEMA_TYPE_SEQUENCE: 20926 case XML_SCHEMA_TYPE_CHOICE: 20927 case XML_SCHEMA_TYPE_ALL: 20928 xmlSchemaResolveModelGroupParticleReferences(pctxt, 20929 WXS_MODEL_GROUP_CAST item); 20930 FIXHFAILURE; 20931 break; 20932 case XML_SCHEMA_TYPE_IDC_KEY: 20933 case XML_SCHEMA_TYPE_IDC_UNIQUE: 20934 case XML_SCHEMA_TYPE_IDC_KEYREF: 20935 xmlSchemaResolveIDCKeyReferences( 20936 (xmlSchemaIDCPtr) item, pctxt); 20937 FIXHFAILURE; 20938 break; 20939 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB: 20940 /* 20941 * Handle attribue prohibition which had a 20942 * "ref" attribute. 20943 */ 20944 xmlSchemaResolveAttrUseProhibReferences( 20945 WXS_ATTR_PROHIB_CAST item, pctxt); 20946 FIXHFAILURE; 20947 break; 20948 default: 20949 break; 20950 } 20951 } 20952 if (pctxt->nberrors != 0) 20953 goto exit_error; 20954 20955 /* 20956 * Now that all references are resolved we 20957 * can check for circularity of... 20958 * 1. the base axis of type definitions 20959 * 2. nested model group definitions 20960 * 3. nested attribute group definitions 20961 * TODO: check for circual substitution groups. 20962 */ 20963 for (i = 0; i < nbItems; i++) { 20964 item = items[i]; 20965 /* 20966 * Let's better stop on the first error here. 20967 */ 20968 switch (item->type) { 20969 case XML_SCHEMA_TYPE_COMPLEX: 20970 case XML_SCHEMA_TYPE_SIMPLE: 20971 xmlSchemaCheckTypeDefCircular( 20972 (xmlSchemaTypePtr) item, pctxt); 20973 FIXHFAILURE; 20974 if (pctxt->nberrors != 0) 20975 goto exit_error; 20976 break; 20977 case XML_SCHEMA_TYPE_GROUP: 20978 xmlSchemaCheckGroupDefCircular( 20979 (xmlSchemaModelGroupDefPtr) item, pctxt); 20980 FIXHFAILURE; 20981 if (pctxt->nberrors != 0) 20982 goto exit_error; 20983 break; 20984 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: 20985 xmlSchemaCheckAttrGroupCircular( 20986 (xmlSchemaAttributeGroupPtr) item, pctxt); 20987 FIXHFAILURE; 20988 if (pctxt->nberrors != 0) 20989 goto exit_error; 20990 break; 20991 default: 20992 break; 20993 } 20994 } 20995 if (pctxt->nberrors != 0) 20996 goto exit_error; 20997 /* 20998 * Model group definition references: 20999 * Such a reference is reflected by a particle at the component 21000 * level. Until now the 'term' of such particles pointed 21001 * to the model group definition; this was done, in order to 21002 * ease circularity checks. Now we need to set the 'term' of 21003 * such particles to the model group of the model group definition. 21004 */ 21005 for (i = 0; i < nbItems; i++) { 21006 item = items[i]; 21007 switch (item->type) { 21008 case XML_SCHEMA_TYPE_SEQUENCE: 21009 case XML_SCHEMA_TYPE_CHOICE: 21010 xmlSchemaModelGroupToModelGroupDefFixup(pctxt, 21011 WXS_MODEL_GROUP_CAST item); 21012 break; 21013 default: 21014 break; 21015 } 21016 } 21017 if (pctxt->nberrors != 0) 21018 goto exit_error; 21019 /* 21020 * Expand attribute group references of attribute group definitions. 21021 */ 21022 for (i = 0; i < nbItems; i++) { 21023 item = items[i]; 21024 switch (item->type) { 21025 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: 21026 if ((! WXS_ATTR_GROUP_EXPANDED(item)) && 21027 WXS_ATTR_GROUP_HAS_REFS(item)) 21028 { 21029 xmlSchemaAttributeGroupExpandRefs(pctxt, 21030 WXS_ATTR_GROUP_CAST item); 21031 FIXHFAILURE; 21032 } 21033 break; 21034 default: 21035 break; 21036 } 21037 } 21038 if (pctxt->nberrors != 0) 21039 goto exit_error; 21040 /* 21041 * First compute the variety of simple types. This is needed as 21042 * a seperate step, since otherwise we won't be able to detect 21043 * circular union types in all cases. 21044 */ 21045 for (i = 0; i < nbItems; i++) { 21046 item = items[i]; 21047 switch (item->type) { 21048 case XML_SCHEMA_TYPE_SIMPLE: 21049 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) { 21050 xmlSchemaFixupSimpleTypeStageOne(pctxt, 21051 (xmlSchemaTypePtr) item); 21052 FIXHFAILURE; 21053 } 21054 break; 21055 default: 21056 break; 21057 } 21058 } 21059 if (pctxt->nberrors != 0) 21060 goto exit_error; 21061 /* 21062 * Detect circular union types. Note that this needs the variety to 21063 * be already computed. 21064 */ 21065 for (i = 0; i < nbItems; i++) { 21066 item = items[i]; 21067 switch (item->type) { 21068 case XML_SCHEMA_TYPE_SIMPLE: 21069 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) { 21070 xmlSchemaCheckUnionTypeDefCircular(pctxt, 21071 (xmlSchemaTypePtr) item); 21072 FIXHFAILURE; 21073 } 21074 break; 21075 default: 21076 break; 21077 } 21078 } 21079 if (pctxt->nberrors != 0) 21080 goto exit_error; 21081 21082 /* 21083 * Do the complete type fixup for simple types. 21084 */ 21085 for (i = 0; i < nbItems; i++) { 21086 item = items[i]; 21087 switch (item->type) { 21088 case XML_SCHEMA_TYPE_SIMPLE: 21089 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) { 21090 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item); 21091 FIXHFAILURE; 21092 } 21093 break; 21094 default: 21095 break; 21096 } 21097 } 21098 if (pctxt->nberrors != 0) 21099 goto exit_error; 21100 /* 21101 * At this point we need build and check all simple types. 21102 */ 21103 /* 21104 * Apply contraints for attribute declarations. 21105 */ 21106 for (i = 0; i < nbItems; i++) { 21107 item = items[i]; 21108 switch (item->type) { 21109 case XML_SCHEMA_TYPE_ATTRIBUTE: 21110 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item); 21111 FIXHFAILURE; 21112 break; 21113 default: 21114 break; 21115 } 21116 } 21117 if (pctxt->nberrors != 0) 21118 goto exit_error; 21119 /* 21120 * Apply constraints for attribute uses. 21121 */ 21122 for (i = 0; i < nbItems; i++) { 21123 item = items[i]; 21124 switch (item->type) { 21125 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: 21126 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) { 21127 xmlSchemaCheckAttrUsePropsCorrect(pctxt, 21128 WXS_ATTR_USE_CAST item); 21129 FIXHFAILURE; 21130 } 21131 break; 21132 default: 21133 break; 21134 } 21135 } 21136 if (pctxt->nberrors != 0) 21137 goto exit_error; 21138 21139 /* 21140 * Apply constraints for attribute group definitions. 21141 */ 21142 for (i = 0; i < nbItems; i++) { 21143 item = items[i]; 21144 switch (item->type) { 21145 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: 21146 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) && 21147 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1)) 21148 { 21149 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item); 21150 FIXHFAILURE; 21151 } 21152 break; 21153 default: 21154 break; 21155 } 21156 } 21157 if (pctxt->nberrors != 0) 21158 goto exit_error; 21159 21160 /* 21161 * Apply constraints for redefinitions. 21162 */ 21163 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL) 21164 xmlSchemaCheckSRCRedefineSecond(pctxt); 21165 if (pctxt->nberrors != 0) 21166 goto exit_error; 21167 21168 /* 21169 * Complex types are builded and checked. 21170 */ 21171 for (i = 0; i < nbItems; i++) { 21172 item = con->pending->items[i]; 21173 switch (item->type) { 21174 case XML_SCHEMA_TYPE_COMPLEX: 21175 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) { 21176 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item); 21177 FIXHFAILURE; 21178 } 21179 break; 21180 default: 21181 break; 21182 } 21183 } 21184 if (pctxt->nberrors != 0) 21185 goto exit_error; 21186 21187 /* 21188 * The list could have changed, since xmlSchemaFixupComplexType() 21189 * will create particles and model groups in some cases. 21190 */ 21191 items = (xmlSchemaTreeItemPtr *) con->pending->items; 21192 nbItems = con->pending->nbItems; 21193 21194 /* 21195 * Apply some constraints for element declarations. 21196 */ 21197 for (i = 0; i < nbItems; i++) { 21198 item = items[i]; 21199 switch (item->type) { 21200 case XML_SCHEMA_TYPE_ELEMENT: 21201 elemDecl = (xmlSchemaElementPtr) item; 21202 21203 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) 21204 { 21205 xmlSchemaCheckElementDeclComponent( 21206 (xmlSchemaElementPtr) elemDecl, pctxt); 21207 FIXHFAILURE; 21208 } 21209 21210#ifdef WXS_ELEM_DECL_CONS_ENABLED 21211 /* 21212 * Schema Component Constraint: Element Declarations Consistent 21213 * Apply this constraint to local types of element declarations. 21214 */ 21215 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) && 21216 (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) && 21217 (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl)))) 21218 { 21219 xmlSchemaCheckElementDeclConsistent(pctxt, 21220 WXS_BASIC_CAST elemDecl, 21221 WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)), 21222 NULL, NULL, 0); 21223 } 21224#endif 21225 break; 21226 default: 21227 break; 21228 } 21229 } 21230 if (pctxt->nberrors != 0) 21231 goto exit_error; 21232 21233 /* 21234 * Finally we can build the automaton from the content model of 21235 * complex types. 21236 */ 21237 21238 for (i = 0; i < nbItems; i++) { 21239 item = items[i]; 21240 switch (item->type) { 21241 case XML_SCHEMA_TYPE_COMPLEX: 21242 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt); 21243 /* FIXHFAILURE; */ 21244 break; 21245 default: 21246 break; 21247 } 21248 } 21249 if (pctxt->nberrors != 0) 21250 goto exit_error; 21251 /* 21252 * URGENT TODO: cos-element-consistent 21253 */ 21254 goto exit; 21255 21256exit_error: 21257 ret = pctxt->err; 21258 goto exit; 21259 21260exit_failure: 21261 ret = -1; 21262 21263exit: 21264 /* 21265 * Reset the constructor. This is needed for XSI acquisition, since 21266 * those items will be processed over and over again for every XSI 21267 * if not cleared here. 21268 */ 21269 con->bucket = oldbucket; 21270 con->pending->nbItems = 0; 21271 if (con->substGroups != NULL) { 21272 xmlHashFree(con->substGroups, 21273 (xmlHashDeallocator) xmlSchemaSubstGroupFree); 21274 con->substGroups = NULL; 21275 } 21276 if (con->redefs != NULL) { 21277 xmlSchemaRedefListFree(con->redefs); 21278 con->redefs = NULL; 21279 } 21280 return(ret); 21281} 21282/** 21283 * xmlSchemaParse: 21284 * @ctxt: a schema validation context 21285 * 21286 * parse a schema definition resource and build an internal 21287 * XML Shema struture which can be used to validate instances. 21288 * 21289 * Returns the internal XML Schema structure built from the resource or 21290 * NULL in case of error 21291 */ 21292xmlSchemaPtr 21293xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt) 21294{ 21295 xmlSchemaPtr mainSchema = NULL; 21296 xmlSchemaBucketPtr bucket = NULL; 21297 int res; 21298 21299 /* 21300 * This one is used if the schema to be parsed was specified via 21301 * the API; i.e. not automatically by the validated instance document. 21302 */ 21303 21304 xmlSchemaInitTypes(); 21305 21306 if (ctxt == NULL) 21307 return (NULL); 21308 21309 /* TODO: Init the context. Is this all we need?*/ 21310 ctxt->nberrors = 0; 21311 ctxt->err = 0; 21312 ctxt->counter = 0; 21313 21314 /* Create the *main* schema. */ 21315 mainSchema = xmlSchemaNewSchema(ctxt); 21316 if (mainSchema == NULL) 21317 goto exit_failure; 21318 /* 21319 * Create the schema constructor. 21320 */ 21321 if (ctxt->constructor == NULL) { 21322 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict); 21323 if (ctxt->constructor == NULL) 21324 return(NULL); 21325 /* Take ownership of the constructor to be able to free it. */ 21326 ctxt->ownsConstructor = 1; 21327 } 21328 ctxt->constructor->mainSchema = mainSchema; 21329 /* 21330 * Locate and add the schema document. 21331 */ 21332 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN, 21333 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL, 21334 NULL, NULL, &bucket); 21335 if (res == -1) 21336 goto exit_failure; 21337 if (res != 0) 21338 goto exit; 21339 21340 if (bucket == NULL) { 21341 /* TODO: Error code, actually we failed to *locate* the schema. */ 21342 if (ctxt->URL) 21343 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD, 21344 NULL, NULL, 21345 "Failed to locate the main schema resource at '%s'", 21346 ctxt->URL, NULL); 21347 else 21348 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD, 21349 NULL, NULL, 21350 "Failed to locate the main schema resource", 21351 NULL, NULL); 21352 goto exit; 21353 } 21354 /* Then do the parsing for good. */ 21355 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1) 21356 goto exit_failure; 21357 if (ctxt->nberrors != 0) 21358 goto exit; 21359 21360 mainSchema->doc = bucket->doc; 21361 mainSchema->preserve = ctxt->preserve; 21362 21363 ctxt->schema = mainSchema; 21364 21365 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1) 21366 goto exit_failure; 21367 21368 /* 21369 * TODO: This is not nice, since we cannot distinguish from the 21370 * result if there was an internal error or not. 21371 */ 21372exit: 21373 if (ctxt->nberrors != 0) { 21374 if (mainSchema) { 21375 xmlSchemaFree(mainSchema); 21376 mainSchema = NULL; 21377 } 21378 if (ctxt->constructor) { 21379 xmlSchemaConstructionCtxtFree(ctxt->constructor); 21380 ctxt->constructor = NULL; 21381 ctxt->ownsConstructor = 0; 21382 } 21383 } 21384 ctxt->schema = NULL; 21385 return(mainSchema); 21386exit_failure: 21387 /* 21388 * Quite verbose, but should catch internal errors, which were 21389 * not communitated. 21390 */ 21391 if (mainSchema) { 21392 xmlSchemaFree(mainSchema); 21393 mainSchema = NULL; 21394 } 21395 if (ctxt->constructor) { 21396 xmlSchemaConstructionCtxtFree(ctxt->constructor); 21397 ctxt->constructor = NULL; 21398 ctxt->ownsConstructor = 0; 21399 } 21400 PERROR_INT2("xmlSchemaParse", 21401 "An internal error occured"); 21402 ctxt->schema = NULL; 21403 return(NULL); 21404} 21405 21406/** 21407 * xmlSchemaSetParserErrors: 21408 * @ctxt: a schema validation context 21409 * @err: the error callback 21410 * @warn: the warning callback 21411 * @ctx: contextual data for the callbacks 21412 * 21413 * Set the callback functions used to handle errors for a validation context 21414 */ 21415void 21416xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt, 21417 xmlSchemaValidityErrorFunc err, 21418 xmlSchemaValidityWarningFunc warn, void *ctx) 21419{ 21420 if (ctxt == NULL) 21421 return; 21422 ctxt->error = err; 21423 ctxt->warning = warn; 21424 ctxt->errCtxt = ctx; 21425 if (ctxt->vctxt != NULL) 21426 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx); 21427} 21428 21429/** 21430 * xmlSchemaSetParserStructuredErrors: 21431 * @ctxt: a schema parser context 21432 * @serror: the structured error function 21433 * @ctx: the functions context 21434 * 21435 * Set the structured error callback 21436 */ 21437void 21438xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt, 21439 xmlStructuredErrorFunc serror, 21440 void *ctx) 21441{ 21442 if (ctxt == NULL) 21443 return; 21444 ctxt->serror = serror; 21445 ctxt->errCtxt = ctx; 21446 if (ctxt->vctxt != NULL) 21447 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx); 21448} 21449 21450/** 21451 * xmlSchemaGetParserErrors: 21452 * @ctxt: a XMl-Schema parser context 21453 * @err: the error callback result 21454 * @warn: the warning callback result 21455 * @ctx: contextual data for the callbacks result 21456 * 21457 * Get the callback information used to handle errors for a parser context 21458 * 21459 * Returns -1 in case of failure, 0 otherwise 21460 */ 21461int 21462xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt, 21463 xmlSchemaValidityErrorFunc * err, 21464 xmlSchemaValidityWarningFunc * warn, void **ctx) 21465{ 21466 if (ctxt == NULL) 21467 return(-1); 21468 if (err != NULL) 21469 *err = ctxt->error; 21470 if (warn != NULL) 21471 *warn = ctxt->warning; 21472 if (ctx != NULL) 21473 *ctx = ctxt->errCtxt; 21474 return(0); 21475} 21476 21477/** 21478 * xmlSchemaFacetTypeToString: 21479 * @type: the facet type 21480 * 21481 * Convert the xmlSchemaTypeType to a char string. 21482 * 21483 * Returns the char string representation of the facet type if the 21484 * type is a facet and an "Internal Error" string otherwise. 21485 */ 21486static const xmlChar * 21487xmlSchemaFacetTypeToString(xmlSchemaTypeType type) 21488{ 21489 switch (type) { 21490 case XML_SCHEMA_FACET_PATTERN: 21491 return (BAD_CAST "pattern"); 21492 case XML_SCHEMA_FACET_MAXEXCLUSIVE: 21493 return (BAD_CAST "maxExclusive"); 21494 case XML_SCHEMA_FACET_MAXINCLUSIVE: 21495 return (BAD_CAST "maxInclusive"); 21496 case XML_SCHEMA_FACET_MINEXCLUSIVE: 21497 return (BAD_CAST "minExclusive"); 21498 case XML_SCHEMA_FACET_MININCLUSIVE: 21499 return (BAD_CAST "minInclusive"); 21500 case XML_SCHEMA_FACET_WHITESPACE: 21501 return (BAD_CAST "whiteSpace"); 21502 case XML_SCHEMA_FACET_ENUMERATION: 21503 return (BAD_CAST "enumeration"); 21504 case XML_SCHEMA_FACET_LENGTH: 21505 return (BAD_CAST "length"); 21506 case XML_SCHEMA_FACET_MAXLENGTH: 21507 return (BAD_CAST "maxLength"); 21508 case XML_SCHEMA_FACET_MINLENGTH: 21509 return (BAD_CAST "minLength"); 21510 case XML_SCHEMA_FACET_TOTALDIGITS: 21511 return (BAD_CAST "totalDigits"); 21512 case XML_SCHEMA_FACET_FRACTIONDIGITS: 21513 return (BAD_CAST "fractionDigits"); 21514 default: 21515 break; 21516 } 21517 return (BAD_CAST "Internal Error"); 21518} 21519 21520static xmlSchemaWhitespaceValueType 21521xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type) 21522{ 21523 /* 21524 * The normalization type can be changed only for types which are derived 21525 * from xsd:string. 21526 */ 21527 if (type->type == XML_SCHEMA_TYPE_BASIC) { 21528 /* 21529 * Note that we assume a whitespace of preserve for anySimpleType. 21530 */ 21531 if ((type->builtInType == XML_SCHEMAS_STRING) || 21532 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) 21533 return(XML_SCHEMA_WHITESPACE_PRESERVE); 21534 else if (type->builtInType == XML_SCHEMAS_NORMSTRING) 21535 return(XML_SCHEMA_WHITESPACE_REPLACE); 21536 else { 21537 /* 21538 * For all �atomic� datatypes other than string (and types �derived� 21539 * by �restriction� from it) the value of whiteSpace is fixed to 21540 * collapse 21541 * Note that this includes built-in list datatypes. 21542 */ 21543 return(XML_SCHEMA_WHITESPACE_COLLAPSE); 21544 } 21545 } else if (WXS_IS_LIST(type)) { 21546 /* 21547 * For list types the facet "whiteSpace" is fixed to "collapse". 21548 */ 21549 return (XML_SCHEMA_WHITESPACE_COLLAPSE); 21550 } else if (WXS_IS_UNION(type)) { 21551 return (XML_SCHEMA_WHITESPACE_UNKNOWN); 21552 } else if (WXS_IS_ATOMIC(type)) { 21553 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE) 21554 return (XML_SCHEMA_WHITESPACE_PRESERVE); 21555 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE) 21556 return (XML_SCHEMA_WHITESPACE_REPLACE); 21557 else 21558 return (XML_SCHEMA_WHITESPACE_COLLAPSE); 21559 } 21560 return (-1); 21561} 21562 21563/************************************************************************ 21564 * * 21565 * Simple type validation * 21566 * * 21567 ************************************************************************/ 21568 21569 21570/************************************************************************ 21571 * * 21572 * DOM Validation code * 21573 * * 21574 ************************************************************************/ 21575 21576/** 21577 * xmlSchemaAssembleByLocation: 21578 * @pctxt: a schema parser context 21579 * @vctxt: a schema validation context 21580 * @schema: the existing schema 21581 * @node: the node that fired the assembling 21582 * @nsName: the namespace name of the new schema 21583 * @location: the location of the schema 21584 * 21585 * Expands an existing schema by an additional schema. 21586 * 21587 * Returns 0 if the new schema is correct, a positive error code 21588 * number otherwise and -1 in case of an internal or API error. 21589 */ 21590static int 21591xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt, 21592 xmlSchemaPtr schema, 21593 xmlNodePtr node, 21594 const xmlChar *nsName, 21595 const xmlChar *location) 21596{ 21597 int ret = 0; 21598 xmlSchemaParserCtxtPtr pctxt; 21599 xmlSchemaBucketPtr bucket = NULL; 21600 21601 if ((vctxt == NULL) || (schema == NULL)) 21602 return (-1); 21603 21604 if (vctxt->pctxt == NULL) { 21605 VERROR_INT("xmlSchemaAssembleByLocation", 21606 "no parser context available"); 21607 return(-1); 21608 } 21609 pctxt = vctxt->pctxt; 21610 if (pctxt->constructor == NULL) { 21611 PERROR_INT("xmlSchemaAssembleByLocation", 21612 "no constructor"); 21613 return(-1); 21614 } 21615 /* 21616 * Acquire the schema document. 21617 */ 21618 location = xmlSchemaBuildAbsoluteURI(pctxt->dict, 21619 location, node); 21620 /* 21621 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here; 21622 * the process will automatically change this to 21623 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document. 21624 */ 21625 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT, 21626 location, NULL, NULL, 0, node, NULL, nsName, 21627 &bucket); 21628 if (ret != 0) 21629 return(ret); 21630 if (bucket == NULL) { 21631 /* 21632 * Generate a warning that the document could not be located. 21633 */ 21634 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC, 21635 node, NULL, 21636 "The document at location '%s' could not be acquired", 21637 location, NULL, NULL); 21638 return(ret); 21639 } 21640 /* 21641 * The first located schema will be handled as if all other 21642 * schemas imported by XSI were imported by this first schema. 21643 */ 21644 if ((bucket != NULL) && 21645 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL)) 21646 WXS_CONSTRUCTOR(pctxt)->bucket = bucket; 21647 /* 21648 * TODO: Is this handled like an import? I.e. is it not an error 21649 * if the schema cannot be located? 21650 */ 21651 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket))) 21652 return(0); 21653 /* 21654 * We will reuse the parser context for every schema imported 21655 * directly via XSI. So reset the context. 21656 */ 21657 pctxt->nberrors = 0; 21658 pctxt->err = 0; 21659 pctxt->doc = bucket->doc; 21660 21661 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket); 21662 if (ret == -1) { 21663 pctxt->doc = NULL; 21664 goto exit_failure; 21665 } 21666 /* Paranoid error channelling. */ 21667 if ((ret == 0) && (pctxt->nberrors != 0)) 21668 ret = pctxt->err; 21669 if (pctxt->nberrors == 0) { 21670 /* 21671 * Only bother to fixup pending components, if there was 21672 * no error yet. 21673 * For every XSI acquired schema (and its sub-schemata) we will 21674 * fixup the components. 21675 */ 21676 xmlSchemaFixupComponents(pctxt, bucket); 21677 ret = pctxt->err; 21678 /* 21679 * Not nice, but we need somehow to channel the schema parser 21680 * error to the validation context. 21681 */ 21682 if ((ret != 0) && (vctxt->err == 0)) 21683 vctxt->err = ret; 21684 vctxt->nberrors += pctxt->nberrors; 21685 } else { 21686 /* Add to validation error sum. */ 21687 vctxt->nberrors += pctxt->nberrors; 21688 } 21689 pctxt->doc = NULL; 21690 return(ret); 21691exit_failure: 21692 pctxt->doc = NULL; 21693 return (-1); 21694} 21695 21696static xmlSchemaAttrInfoPtr 21697xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt, 21698 int metaType) 21699{ 21700 if (vctxt->nbAttrInfos == 0) 21701 return (NULL); 21702 { 21703 int i; 21704 xmlSchemaAttrInfoPtr iattr; 21705 21706 for (i = 0; i < vctxt->nbAttrInfos; i++) { 21707 iattr = vctxt->attrInfos[i]; 21708 if (iattr->metaType == metaType) 21709 return (iattr); 21710 } 21711 21712 } 21713 return (NULL); 21714} 21715 21716/** 21717 * xmlSchemaAssembleByXSI: 21718 * @vctxt: a schema validation context 21719 * 21720 * Expands an existing schema by an additional schema using 21721 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute 21722 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace 21723 * must be set to 1. 21724 * 21725 * Returns 0 if the new schema is correct, a positive error code 21726 * number otherwise and -1 in case of an internal or API error. 21727 */ 21728static int 21729xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt) 21730{ 21731 const xmlChar *cur, *end; 21732 const xmlChar *nsname = NULL, *location; 21733 int count = 0; 21734 int ret = 0; 21735 xmlSchemaAttrInfoPtr iattr; 21736 21737 /* 21738 * Parse the value; we will assume an even number of values 21739 * to be given (this is how Xerces and XSV work). 21740 * 21741 * URGENT TODO: !! This needs to work for both 21742 * @noNamespaceSchemaLocation AND @schemaLocation on the same 21743 * element !! 21744 */ 21745 iattr = xmlSchemaGetMetaAttrInfo(vctxt, 21746 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC); 21747 if (iattr == NULL) 21748 iattr = xmlSchemaGetMetaAttrInfo(vctxt, 21749 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC); 21750 if (iattr == NULL) 21751 return (0); 21752 cur = iattr->value; 21753 do { 21754 /* 21755 * TODO: Move the string parsing mechanism away from here. 21756 */ 21757 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) { 21758 /* 21759 * Get the namespace name. 21760 */ 21761 while (IS_BLANK_CH(*cur)) 21762 cur++; 21763 end = cur; 21764 while ((*end != 0) && (!(IS_BLANK_CH(*end)))) 21765 end++; 21766 if (end == cur) 21767 break; 21768 count++; /* TODO: Don't use the schema's dict. */ 21769 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur); 21770 cur = end; 21771 } 21772 /* 21773 * Get the URI. 21774 */ 21775 while (IS_BLANK_CH(*cur)) 21776 cur++; 21777 end = cur; 21778 while ((*end != 0) && (!(IS_BLANK_CH(*end)))) 21779 end++; 21780 if (end == cur) { 21781 if (iattr->metaType == 21782 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) 21783 { 21784 /* 21785 * If using @schemaLocation then tuples are expected. 21786 * I.e. the namespace name *and* the document's URI. 21787 */ 21788 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC, 21789 iattr->node, NULL, 21790 "The value must consist of tuples: the target namespace " 21791 "name and the document's URI", NULL, NULL, NULL); 21792 } 21793 break; 21794 } 21795 count++; /* TODO: Don't use the schema's dict. */ 21796 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur); 21797 cur = end; 21798 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema, 21799 iattr->node, nsname, location); 21800 if (ret == -1) { 21801 VERROR_INT("xmlSchemaAssembleByXSI", 21802 "assembling schemata"); 21803 return (-1); 21804 } 21805 } while (*cur != 0); 21806 return (ret); 21807} 21808 21809static const xmlChar * 21810xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt, 21811 const xmlChar *prefix) 21812{ 21813 if (vctxt->sax != NULL) { 21814 int i, j; 21815 xmlSchemaNodeInfoPtr inode; 21816 21817 for (i = vctxt->depth; i >= 0; i--) { 21818 if (vctxt->elemInfos[i]->nbNsBindings != 0) { 21819 inode = vctxt->elemInfos[i]; 21820 for (j = 0; j < inode->nbNsBindings * 2; j += 2) { 21821 if (((prefix == NULL) && 21822 (inode->nsBindings[j] == NULL)) || 21823 ((prefix != NULL) && xmlStrEqual(prefix, 21824 inode->nsBindings[j]))) { 21825 21826 /* 21827 * Note that the namespace bindings are already 21828 * in a string dict. 21829 */ 21830 return (inode->nsBindings[j+1]); 21831 } 21832 } 21833 } 21834 } 21835 return (NULL); 21836#ifdef LIBXML_READER_ENABLED 21837 } else if (vctxt->reader != NULL) { 21838 xmlChar *nsName; 21839 21840 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix); 21841 if (nsName != NULL) { 21842 const xmlChar *ret; 21843 21844 ret = xmlDictLookup(vctxt->dict, nsName, -1); 21845 xmlFree(nsName); 21846 return (ret); 21847 } else 21848 return (NULL); 21849#endif 21850 } else { 21851 xmlNsPtr ns; 21852 21853 if ((vctxt->inode->node == NULL) || 21854 (vctxt->inode->node->doc == NULL)) { 21855 VERROR_INT("xmlSchemaLookupNamespace", 21856 "no node or node's doc avaliable"); 21857 return (NULL); 21858 } 21859 ns = xmlSearchNs(vctxt->inode->node->doc, 21860 vctxt->inode->node, prefix); 21861 if (ns != NULL) 21862 return (ns->href); 21863 return (NULL); 21864 } 21865} 21866 21867/* 21868* This one works on the schema of the validation context. 21869*/ 21870static int 21871xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt, 21872 xmlSchemaPtr schema, 21873 xmlNodePtr node, 21874 const xmlChar *value, 21875 xmlSchemaValPtr *val, 21876 int valNeeded) 21877{ 21878 int ret; 21879 21880 if (vctxt && (vctxt->schema == NULL)) { 21881 VERROR_INT("xmlSchemaValidateNotation", 21882 "a schema is needed on the validation context"); 21883 return (-1); 21884 } 21885 ret = xmlValidateQName(value, 1); 21886 if (ret != 0) 21887 return (ret); 21888 { 21889 xmlChar *localName = NULL; 21890 xmlChar *prefix = NULL; 21891 21892 localName = xmlSplitQName2(value, &prefix); 21893 if (prefix != NULL) { 21894 const xmlChar *nsName = NULL; 21895 21896 if (vctxt != NULL) 21897 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix); 21898 else if (node != NULL) { 21899 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix); 21900 if (ns != NULL) 21901 nsName = ns->href; 21902 } else { 21903 xmlFree(prefix); 21904 xmlFree(localName); 21905 return (1); 21906 } 21907 if (nsName == NULL) { 21908 xmlFree(prefix); 21909 xmlFree(localName); 21910 return (1); 21911 } 21912 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) { 21913 if ((valNeeded) && (val != NULL)) { 21914 (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName), 21915 xmlStrdup(nsName)); 21916 if (*val == NULL) 21917 ret = -1; 21918 } 21919 } else 21920 ret = 1; 21921 xmlFree(prefix); 21922 xmlFree(localName); 21923 } else { 21924 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) { 21925 if (valNeeded && (val != NULL)) { 21926 (*val) = xmlSchemaNewNOTATIONValue( 21927 BAD_CAST xmlStrdup(value), NULL); 21928 if (*val == NULL) 21929 ret = -1; 21930 } 21931 } else 21932 return (1); 21933 } 21934 } 21935 return (ret); 21936} 21937 21938static int 21939xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt, 21940 const xmlChar* lname, 21941 const xmlChar* nsname) 21942{ 21943 int i; 21944 21945 lname = xmlDictLookup(vctxt->dict, lname, -1); 21946 if (lname == NULL) 21947 return(-1); 21948 if (nsname != NULL) { 21949 nsname = xmlDictLookup(vctxt->dict, nsname, -1); 21950 if (nsname == NULL) 21951 return(-1); 21952 } 21953 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) { 21954 if ((vctxt->nodeQNames->items [i] == lname) && 21955 (vctxt->nodeQNames->items[i +1] == nsname)) 21956 /* Already there */ 21957 return(i); 21958 } 21959 /* Add new entry. */ 21960 i = vctxt->nodeQNames->nbItems; 21961 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname); 21962 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname); 21963 return(i); 21964} 21965 21966/************************************************************************ 21967 * * 21968 * Validation of identity-constraints (IDC) * 21969 * * 21970 ************************************************************************/ 21971 21972/** 21973 * xmlSchemaAugmentIDC: 21974 * @idcDef: the IDC definition 21975 * 21976 * Creates an augmented IDC definition item. 21977 * 21978 * Returns the item, or NULL on internal errors. 21979 */ 21980static void 21981xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef, 21982 xmlSchemaValidCtxtPtr vctxt) 21983{ 21984 xmlSchemaIDCAugPtr aidc; 21985 21986 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug)); 21987 if (aidc == NULL) { 21988 xmlSchemaVErrMemory(vctxt, 21989 "xmlSchemaAugmentIDC: allocating an augmented IDC definition", 21990 NULL); 21991 return; 21992 } 21993 aidc->keyrefDepth = -1; 21994 aidc->def = idcDef; 21995 aidc->next = NULL; 21996 if (vctxt->aidcs == NULL) 21997 vctxt->aidcs = aidc; 21998 else { 21999 aidc->next = vctxt->aidcs; 22000 vctxt->aidcs = aidc; 22001 } 22002 /* 22003 * Save if we have keyrefs at all. 22004 */ 22005 if ((vctxt->hasKeyrefs == 0) && 22006 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF)) 22007 vctxt->hasKeyrefs = 1; 22008} 22009 22010/** 22011 * xmlSchemaAugmentImportedIDC: 22012 * @imported: the imported schema 22013 * 22014 * Creates an augmented IDC definition for the imported schema. 22015 */ 22016static void 22017xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) { 22018 if (imported->schema->idcDef != NULL) { 22019 xmlHashScan(imported->schema->idcDef , 22020 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt); 22021 } 22022} 22023 22024/** 22025 * xmlSchemaIDCNewBinding: 22026 * @idcDef: the IDC definition of this binding 22027 * 22028 * Creates a new IDC binding. 22029 * 22030 * Returns the new IDC binding, NULL on internal errors. 22031 */ 22032static xmlSchemaPSVIIDCBindingPtr 22033xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef) 22034{ 22035 xmlSchemaPSVIIDCBindingPtr ret; 22036 22037 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc( 22038 sizeof(xmlSchemaPSVIIDCBinding)); 22039 if (ret == NULL) { 22040 xmlSchemaVErrMemory(NULL, 22041 "allocating a PSVI IDC binding item", NULL); 22042 return (NULL); 22043 } 22044 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding)); 22045 ret->definition = idcDef; 22046 return (ret); 22047} 22048 22049/** 22050 * xmlSchemaIDCStoreNodeTableItem: 22051 * @vctxt: the WXS validation context 22052 * @item: the IDC node table item 22053 * 22054 * The validation context is used to store IDC node table items. 22055 * They are stored to avoid copying them if IDC node-tables are merged 22056 * with corresponding parent IDC node-tables (bubbling). 22057 * 22058 * Returns 0 if succeeded, -1 on internal errors. 22059 */ 22060static int 22061xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt, 22062 xmlSchemaPSVIIDCNodePtr item) 22063{ 22064 /* 22065 * Add to gobal list. 22066 */ 22067 if (vctxt->idcNodes == NULL) { 22068 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *) 22069 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr)); 22070 if (vctxt->idcNodes == NULL) { 22071 xmlSchemaVErrMemory(vctxt, 22072 "allocating the IDC node table item list", NULL); 22073 return (-1); 22074 } 22075 vctxt->sizeIdcNodes = 20; 22076 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) { 22077 vctxt->sizeIdcNodes *= 2; 22078 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *) 22079 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes * 22080 sizeof(xmlSchemaPSVIIDCNodePtr)); 22081 if (vctxt->idcNodes == NULL) { 22082 xmlSchemaVErrMemory(vctxt, 22083 "re-allocating the IDC node table item list", NULL); 22084 return (-1); 22085 } 22086 } 22087 vctxt->idcNodes[vctxt->nbIdcNodes++] = item; 22088 22089 return (0); 22090} 22091 22092/** 22093 * xmlSchemaIDCStoreKey: 22094 * @vctxt: the WXS validation context 22095 * @item: the IDC key 22096 * 22097 * The validation context is used to store an IDC key. 22098 * 22099 * Returns 0 if succeeded, -1 on internal errors. 22100 */ 22101static int 22102xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt, 22103 xmlSchemaPSVIIDCKeyPtr key) 22104{ 22105 /* 22106 * Add to gobal list. 22107 */ 22108 if (vctxt->idcKeys == NULL) { 22109 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *) 22110 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr)); 22111 if (vctxt->idcKeys == NULL) { 22112 xmlSchemaVErrMemory(vctxt, 22113 "allocating the IDC key storage list", NULL); 22114 return (-1); 22115 } 22116 vctxt->sizeIdcKeys = 40; 22117 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) { 22118 vctxt->sizeIdcKeys *= 2; 22119 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *) 22120 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys * 22121 sizeof(xmlSchemaPSVIIDCKeyPtr)); 22122 if (vctxt->idcKeys == NULL) { 22123 xmlSchemaVErrMemory(vctxt, 22124 "re-allocating the IDC key storage list", NULL); 22125 return (-1); 22126 } 22127 } 22128 vctxt->idcKeys[vctxt->nbIdcKeys++] = key; 22129 22130 return (0); 22131} 22132 22133/** 22134 * xmlSchemaIDCAppendNodeTableItem: 22135 * @bind: the IDC binding 22136 * @ntItem: the node-table item 22137 * 22138 * Appends the IDC node-table item to the binding. 22139 * 22140 * Returns 0 on success and -1 on internal errors. 22141 */ 22142static int 22143xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind, 22144 xmlSchemaPSVIIDCNodePtr ntItem) 22145{ 22146 if (bind->nodeTable == NULL) { 22147 bind->sizeNodes = 10; 22148 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) 22149 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr)); 22150 if (bind->nodeTable == NULL) { 22151 xmlSchemaVErrMemory(NULL, 22152 "allocating an array of IDC node-table items", NULL); 22153 return(-1); 22154 } 22155 } else if (bind->sizeNodes <= bind->nbNodes) { 22156 bind->sizeNodes *= 2; 22157 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) 22158 xmlRealloc(bind->nodeTable, bind->sizeNodes * 22159 sizeof(xmlSchemaPSVIIDCNodePtr)); 22160 if (bind->nodeTable == NULL) { 22161 xmlSchemaVErrMemory(NULL, 22162 "re-allocating an array of IDC node-table items", NULL); 22163 return(-1); 22164 } 22165 } 22166 bind->nodeTable[bind->nbNodes++] = ntItem; 22167 return(0); 22168} 22169 22170/** 22171 * xmlSchemaIDCAcquireBinding: 22172 * @vctxt: the WXS validation context 22173 * @matcher: the IDC matcher 22174 * 22175 * Looks up an PSVI IDC binding, for the IDC definition and 22176 * of the given matcher. If none found, a new one is created 22177 * and added to the IDC table. 22178 * 22179 * Returns an IDC binding or NULL on internal errors. 22180 */ 22181static xmlSchemaPSVIIDCBindingPtr 22182xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt, 22183 xmlSchemaIDCMatcherPtr matcher) 22184{ 22185 xmlSchemaNodeInfoPtr ielem; 22186 22187 ielem = vctxt->elemInfos[matcher->depth]; 22188 22189 if (ielem->idcTable == NULL) { 22190 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def); 22191 if (ielem->idcTable == NULL) 22192 return (NULL); 22193 return(ielem->idcTable); 22194 } else { 22195 xmlSchemaPSVIIDCBindingPtr bind = NULL; 22196 22197 bind = ielem->idcTable; 22198 do { 22199 if (bind->definition == matcher->aidc->def) 22200 return(bind); 22201 if (bind->next == NULL) { 22202 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def); 22203 if (bind->next == NULL) 22204 return (NULL); 22205 return(bind->next); 22206 } 22207 bind = bind->next; 22208 } while (bind != NULL); 22209 } 22210 return (NULL); 22211} 22212 22213static xmlSchemaItemListPtr 22214xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED, 22215 xmlSchemaIDCMatcherPtr matcher) 22216{ 22217 if (matcher->targets == NULL) 22218 matcher->targets = xmlSchemaItemListCreate(); 22219 return(matcher->targets); 22220} 22221 22222/** 22223 * xmlSchemaIDCFreeKey: 22224 * @key: the IDC key 22225 * 22226 * Frees an IDC key together with its compiled value. 22227 */ 22228static void 22229xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key) 22230{ 22231 if (key->val != NULL) 22232 xmlSchemaFreeValue(key->val); 22233 xmlFree(key); 22234} 22235 22236/** 22237 * xmlSchemaIDCFreeBinding: 22238 * 22239 * Frees an IDC binding. Note that the node table-items 22240 * are not freed. 22241 */ 22242static void 22243xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind) 22244{ 22245 if (bind->nodeTable != NULL) 22246 xmlFree(bind->nodeTable); 22247 if (bind->dupls != NULL) 22248 xmlSchemaItemListFree(bind->dupls); 22249 xmlFree(bind); 22250} 22251 22252/** 22253 * xmlSchemaIDCFreeIDCTable: 22254 * @bind: the first IDC binding in the list 22255 * 22256 * Frees an IDC table, i.e. all the IDC bindings in the list. 22257 */ 22258static void 22259xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind) 22260{ 22261 xmlSchemaPSVIIDCBindingPtr prev; 22262 22263 while (bind != NULL) { 22264 prev = bind; 22265 bind = bind->next; 22266 xmlSchemaIDCFreeBinding(prev); 22267 } 22268} 22269 22270/** 22271 * xmlSchemaIDCFreeMatcherList: 22272 * @matcher: the first IDC matcher in the list 22273 * 22274 * Frees a list of IDC matchers. 22275 */ 22276static void 22277xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher) 22278{ 22279 xmlSchemaIDCMatcherPtr next; 22280 22281 while (matcher != NULL) { 22282 next = matcher->next; 22283 if (matcher->keySeqs != NULL) { 22284 int i; 22285 for (i = 0; i < matcher->sizeKeySeqs; i++) 22286 if (matcher->keySeqs[i] != NULL) 22287 xmlFree(matcher->keySeqs[i]); 22288 xmlFree(matcher->keySeqs); 22289 } 22290 if (matcher->targets != NULL) { 22291 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) { 22292 int i; 22293 xmlSchemaPSVIIDCNodePtr idcNode; 22294 /* 22295 * Node-table items for keyrefs are not stored globally 22296 * to the validation context, since they are not bubbled. 22297 * We need to free them here. 22298 */ 22299 for (i = 0; i < matcher->targets->nbItems; i++) { 22300 idcNode = 22301 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i]; 22302 xmlFree(idcNode->keys); 22303 xmlFree(idcNode); 22304 } 22305 } 22306 xmlSchemaItemListFree(matcher->targets); 22307 } 22308 xmlFree(matcher); 22309 matcher = next; 22310 } 22311} 22312 22313/** 22314 * xmlSchemaIDCReleaseMatcherList: 22315 * @vctxt: the WXS validation context 22316 * @matcher: the first IDC matcher in the list 22317 * 22318 * Caches a list of IDC matchers for reuse. 22319 */ 22320static void 22321xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt, 22322 xmlSchemaIDCMatcherPtr matcher) 22323{ 22324 xmlSchemaIDCMatcherPtr next; 22325 22326 while (matcher != NULL) { 22327 next = matcher->next; 22328 if (matcher->keySeqs != NULL) { 22329 int i; 22330 /* 22331 * Don't free the array, but only the content. 22332 */ 22333 for (i = 0; i < matcher->sizeKeySeqs; i++) 22334 if (matcher->keySeqs[i] != NULL) { 22335 xmlFree(matcher->keySeqs[i]); 22336 matcher->keySeqs[i] = NULL; 22337 } 22338 } 22339 if (matcher->targets) { 22340 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) { 22341 int i; 22342 xmlSchemaPSVIIDCNodePtr idcNode; 22343 /* 22344 * Node-table items for keyrefs are not stored globally 22345 * to the validation context, since they are not bubbled. 22346 * We need to free them here. 22347 */ 22348 for (i = 0; i < matcher->targets->nbItems; i++) { 22349 idcNode = 22350 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i]; 22351 xmlFree(idcNode->keys); 22352 xmlFree(idcNode); 22353 } 22354 } 22355 xmlSchemaItemListFree(matcher->targets); 22356 matcher->targets = NULL; 22357 } 22358 matcher->next = NULL; 22359 /* 22360 * Cache the matcher. 22361 */ 22362 if (vctxt->idcMatcherCache != NULL) 22363 matcher->nextCached = vctxt->idcMatcherCache; 22364 vctxt->idcMatcherCache = matcher; 22365 22366 matcher = next; 22367 } 22368} 22369 22370/** 22371 * xmlSchemaIDCAddStateObject: 22372 * @vctxt: the WXS validation context 22373 * @matcher: the IDC matcher 22374 * @sel: the XPath information 22375 * @parent: the parent "selector" state object if any 22376 * @type: "selector" or "field" 22377 * 22378 * Creates/reuses and activates state objects for the given 22379 * XPath information; if the XPath expression consists of unions, 22380 * multiple state objects are created for every unioned expression. 22381 * 22382 * Returns 0 on success and -1 on internal errors. 22383 */ 22384static int 22385xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt, 22386 xmlSchemaIDCMatcherPtr matcher, 22387 xmlSchemaIDCSelectPtr sel, 22388 int type) 22389{ 22390 xmlSchemaIDCStateObjPtr sto; 22391 22392 /* 22393 * Reuse the state objects from the pool. 22394 */ 22395 if (vctxt->xpathStatePool != NULL) { 22396 sto = vctxt->xpathStatePool; 22397 vctxt->xpathStatePool = sto->next; 22398 sto->next = NULL; 22399 } else { 22400 /* 22401 * Create a new state object. 22402 */ 22403 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj)); 22404 if (sto == NULL) { 22405 xmlSchemaVErrMemory(NULL, 22406 "allocating an IDC state object", NULL); 22407 return (-1); 22408 } 22409 memset(sto, 0, sizeof(xmlSchemaIDCStateObj)); 22410 } 22411 /* 22412 * Add to global list. 22413 */ 22414 if (vctxt->xpathStates != NULL) 22415 sto->next = vctxt->xpathStates; 22416 vctxt->xpathStates = sto; 22417 22418 /* 22419 * Free the old xpath validation context. 22420 */ 22421 if (sto->xpathCtxt != NULL) 22422 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt); 22423 22424 /* 22425 * Create a new XPath (pattern) validation context. 22426 */ 22427 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt( 22428 (xmlPatternPtr) sel->xpathComp); 22429 if (sto->xpathCtxt == NULL) { 22430 VERROR_INT("xmlSchemaIDCAddStateObject", 22431 "failed to create an XPath validation context"); 22432 return (-1); 22433 } 22434 sto->type = type; 22435 sto->depth = vctxt->depth; 22436 sto->matcher = matcher; 22437 sto->sel = sel; 22438 sto->nbHistory = 0; 22439 22440#ifdef DEBUG_IDC 22441 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n", 22442 sto->sel->xpath); 22443#endif 22444 return (0); 22445} 22446 22447/** 22448 * xmlSchemaXPathEvaluate: 22449 * @vctxt: the WXS validation context 22450 * @nodeType: the nodeType of the current node 22451 * 22452 * Evaluates all active XPath state objects. 22453 * 22454 * Returns the number of IC "field" state objects which resolved to 22455 * this node, 0 if none resolved and -1 on internal errors. 22456 */ 22457static int 22458xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt, 22459 xmlElementType nodeType) 22460{ 22461 xmlSchemaIDCStateObjPtr sto, head = NULL, first; 22462 int res, resolved = 0, depth = vctxt->depth; 22463 22464 if (vctxt->xpathStates == NULL) 22465 return (0); 22466 22467 if (nodeType == XML_ATTRIBUTE_NODE) 22468 depth++; 22469#ifdef DEBUG_IDC 22470 { 22471 xmlChar *str = NULL; 22472 xmlGenericError(xmlGenericErrorContext, 22473 "IDC: EVAL on %s, depth %d, type %d\n", 22474 xmlSchemaFormatQName(&str, vctxt->inode->nsName, 22475 vctxt->inode->localName), depth, nodeType); 22476 FREE_AND_NULL(str) 22477 } 22478#endif 22479 /* 22480 * Process all active XPath state objects. 22481 */ 22482 first = vctxt->xpathStates; 22483 sto = first; 22484 while (sto != head) { 22485#ifdef DEBUG_IDC 22486 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) 22487 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n", 22488 sto->matcher->aidc->def->name, sto->sel->xpath); 22489 else 22490 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n", 22491 sto->matcher->aidc->def->name, sto->sel->xpath); 22492#endif 22493 if (nodeType == XML_ELEMENT_NODE) 22494 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt, 22495 vctxt->inode->localName, vctxt->inode->nsName); 22496 else 22497 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt, 22498 vctxt->inode->localName, vctxt->inode->nsName); 22499 22500 if (res == -1) { 22501 VERROR_INT("xmlSchemaXPathEvaluate", 22502 "calling xmlStreamPush()"); 22503 return (-1); 22504 } 22505 if (res == 0) 22506 goto next_sto; 22507 /* 22508 * Full match. 22509 */ 22510#ifdef DEBUG_IDC 22511 xmlGenericError(xmlGenericErrorContext, "IDC: " 22512 "MATCH\n"); 22513#endif 22514 /* 22515 * Register a match in the state object history. 22516 */ 22517 if (sto->history == NULL) { 22518 sto->history = (int *) xmlMalloc(5 * sizeof(int)); 22519 if (sto->history == NULL) { 22520 xmlSchemaVErrMemory(NULL, 22521 "allocating the state object history", NULL); 22522 return(-1); 22523 } 22524 sto->sizeHistory = 5; 22525 } else if (sto->sizeHistory <= sto->nbHistory) { 22526 sto->sizeHistory *= 2; 22527 sto->history = (int *) xmlRealloc(sto->history, 22528 sto->sizeHistory * sizeof(int)); 22529 if (sto->history == NULL) { 22530 xmlSchemaVErrMemory(NULL, 22531 "re-allocating the state object history", NULL); 22532 return(-1); 22533 } 22534 } 22535 sto->history[sto->nbHistory++] = depth; 22536 22537#ifdef DEBUG_IDC 22538 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n", 22539 vctxt->depth); 22540#endif 22541 22542 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) { 22543 xmlSchemaIDCSelectPtr sel; 22544 /* 22545 * Activate state objects for the IDC fields of 22546 * the IDC selector. 22547 */ 22548#ifdef DEBUG_IDC 22549 xmlGenericError(xmlGenericErrorContext, "IDC: " 22550 "activating field states\n"); 22551#endif 22552 sel = sto->matcher->aidc->def->fields; 22553 while (sel != NULL) { 22554 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher, 22555 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1) 22556 return (-1); 22557 sel = sel->next; 22558 } 22559 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) { 22560 /* 22561 * An IDC key node was found by the IDC field. 22562 */ 22563#ifdef DEBUG_IDC 22564 xmlGenericError(xmlGenericErrorContext, 22565 "IDC: key found\n"); 22566#endif 22567 /* 22568 * Notify that the character value of this node is 22569 * needed. 22570 */ 22571 if (resolved == 0) { 22572 if ((vctxt->inode->flags & 22573 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0) 22574 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED; 22575 } 22576 resolved++; 22577 } 22578next_sto: 22579 if (sto->next == NULL) { 22580 /* 22581 * Evaluate field state objects created on this node as well. 22582 */ 22583 head = first; 22584 sto = vctxt->xpathStates; 22585 } else 22586 sto = sto->next; 22587 } 22588 return (resolved); 22589} 22590 22591static const xmlChar * 22592xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt, 22593 xmlChar **buf, 22594 xmlSchemaPSVIIDCKeyPtr *seq, 22595 int count) 22596{ 22597 int i, res; 22598 xmlChar *value = NULL; 22599 22600 *buf = xmlStrdup(BAD_CAST "["); 22601 for (i = 0; i < count; i++) { 22602 *buf = xmlStrcat(*buf, BAD_CAST "'"); 22603 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val, 22604 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type), 22605 &value); 22606 if (res == 0) 22607 *buf = xmlStrcat(*buf, BAD_CAST value); 22608 else { 22609 VERROR_INT("xmlSchemaFormatIDCKeySequence", 22610 "failed to compute a canonical value"); 22611 *buf = xmlStrcat(*buf, BAD_CAST "???"); 22612 } 22613 if (i < count -1) 22614 *buf = xmlStrcat(*buf, BAD_CAST "', "); 22615 else 22616 *buf = xmlStrcat(*buf, BAD_CAST "'"); 22617 if (value != NULL) { 22618 xmlFree(value); 22619 value = NULL; 22620 } 22621 } 22622 *buf = xmlStrcat(*buf, BAD_CAST "]"); 22623 22624 return (BAD_CAST *buf); 22625} 22626 22627/** 22628 * xmlSchemaXPathPop: 22629 * @vctxt: the WXS validation context 22630 * 22631 * Pops all XPath states. 22632 * 22633 * Returns 0 on success and -1 on internal errors. 22634 */ 22635static int 22636xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt) 22637{ 22638 xmlSchemaIDCStateObjPtr sto; 22639 int res; 22640 22641 if (vctxt->xpathStates == NULL) 22642 return(0); 22643 sto = vctxt->xpathStates; 22644 do { 22645 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt); 22646 if (res == -1) 22647 return (-1); 22648 sto = sto->next; 22649 } while (sto != NULL); 22650 return(0); 22651} 22652 22653/** 22654 * xmlSchemaXPathProcessHistory: 22655 * @vctxt: the WXS validation context 22656 * @type: the simple/complex type of the current node if any at all 22657 * @val: the precompiled value 22658 * 22659 * Processes and pops the history items of the IDC state objects. 22660 * IDC key-sequences are validated/created on IDC bindings. 22661 * 22662 * Returns 0 on success and -1 on internal errors. 22663 */ 22664static int 22665xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt, 22666 int depth) 22667{ 22668 xmlSchemaIDCStateObjPtr sto, nextsto; 22669 int res, matchDepth; 22670 xmlSchemaPSVIIDCKeyPtr key = NULL; 22671 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL; 22672 22673 if (vctxt->xpathStates == NULL) 22674 return (0); 22675 sto = vctxt->xpathStates; 22676 22677#ifdef DEBUG_IDC 22678 { 22679 xmlChar *str = NULL; 22680 xmlGenericError(xmlGenericErrorContext, 22681 "IDC: BACK on %s, depth %d\n", 22682 xmlSchemaFormatQName(&str, vctxt->inode->nsName, 22683 vctxt->inode->localName), vctxt->depth); 22684 FREE_AND_NULL(str) 22685 } 22686#endif 22687 /* 22688 * Evaluate the state objects. 22689 */ 22690 while (sto != NULL) { 22691 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt); 22692 if (res == -1) { 22693 VERROR_INT("xmlSchemaXPathProcessHistory", 22694 "calling xmlStreamPop()"); 22695 return (-1); 22696 } 22697#ifdef DEBUG_IDC 22698 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n", 22699 sto->sel->xpath); 22700#endif 22701 if (sto->nbHistory == 0) 22702 goto deregister_check; 22703 22704 matchDepth = sto->history[sto->nbHistory -1]; 22705 22706 /* 22707 * Only matches at the current depth are of interest. 22708 */ 22709 if (matchDepth != depth) { 22710 sto = sto->next; 22711 continue; 22712 } 22713 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) { 22714 /* 22715 * NOTE: According to 22716 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198 22717 * ... the simple-content of complex types is also allowed. 22718 */ 22719 22720 if (WXS_IS_COMPLEX(type)) { 22721 if (WXS_HAS_SIMPLE_CONTENT(type)) { 22722 /* 22723 * Sanity check for complex types with simple content. 22724 */ 22725 simpleType = type->contentTypeDef; 22726 if (simpleType == NULL) { 22727 VERROR_INT("xmlSchemaXPathProcessHistory", 22728 "field resolves to a CT with simple content " 22729 "but the CT is missing the ST definition"); 22730 return (-1); 22731 } 22732 } else 22733 simpleType = NULL; 22734 } else 22735 simpleType = type; 22736 if (simpleType == NULL) { 22737 xmlChar *str = NULL; 22738 22739 /* 22740 * Not qualified if the field resolves to a node of non 22741 * simple type. 22742 */ 22743 xmlSchemaCustomErr(ACTXT_CAST vctxt, 22744 XML_SCHEMAV_CVC_IDC, NULL, 22745 WXS_BASIC_CAST sto->matcher->aidc->def, 22746 "The XPath '%s' of a field of %s does evaluate to a node of " 22747 "non-simple type", 22748 sto->sel->xpath, 22749 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def)); 22750 FREE_AND_NULL(str); 22751 sto->nbHistory--; 22752 goto deregister_check; 22753 } 22754 22755 if ((key == NULL) && (vctxt->inode->val == NULL)) { 22756 /* 22757 * Failed to provide the normalized value; maybe 22758 * the value was invalid. 22759 */ 22760 VERROR(XML_SCHEMAV_CVC_IDC, 22761 WXS_BASIC_CAST sto->matcher->aidc->def, 22762 "Warning: No precomputed value available, the value " 22763 "was either invalid or something strange happend"); 22764 sto->nbHistory--; 22765 goto deregister_check; 22766 } else { 22767 xmlSchemaIDCMatcherPtr matcher = sto->matcher; 22768 xmlSchemaPSVIIDCKeyPtr *keySeq; 22769 int pos, idx; 22770 22771 /* 22772 * The key will be anchored on the matcher's list of 22773 * key-sequences. The position in this list is determined 22774 * by the target node's depth relative to the matcher's 22775 * depth of creation (i.e. the depth of the scope element). 22776 * 22777 * Element Depth Pos List-entries 22778 * <scope> 0 NULL 22779 * <bar> 1 NULL 22780 * <target/> 2 2 target 22781 * <bar> 22782 * </scope> 22783 * 22784 * The size of the list is only dependant on the depth of 22785 * the tree. 22786 * An entry will be NULLed in selector_leave, i.e. when 22787 * we hit the target's 22788 */ 22789 pos = sto->depth - matcher->depth; 22790 idx = sto->sel->index; 22791 22792 /* 22793 * Create/grow the array of key-sequences. 22794 */ 22795 if (matcher->keySeqs == NULL) { 22796 if (pos > 9) 22797 matcher->sizeKeySeqs = pos * 2; 22798 else 22799 matcher->sizeKeySeqs = 10; 22800 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **) 22801 xmlMalloc(matcher->sizeKeySeqs * 22802 sizeof(xmlSchemaPSVIIDCKeyPtr *)); 22803 if (matcher->keySeqs == NULL) { 22804 xmlSchemaVErrMemory(NULL, 22805 "allocating an array of key-sequences", 22806 NULL); 22807 return(-1); 22808 } 22809 memset(matcher->keySeqs, 0, 22810 matcher->sizeKeySeqs * 22811 sizeof(xmlSchemaPSVIIDCKeyPtr *)); 22812 } else if (pos >= matcher->sizeKeySeqs) { 22813 int i = matcher->sizeKeySeqs; 22814 22815 matcher->sizeKeySeqs *= 2; 22816 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **) 22817 xmlRealloc(matcher->keySeqs, 22818 matcher->sizeKeySeqs * 22819 sizeof(xmlSchemaPSVIIDCKeyPtr *)); 22820 if (matcher->keySeqs == NULL) { 22821 xmlSchemaVErrMemory(NULL, 22822 "reallocating an array of key-sequences", 22823 NULL); 22824 return (-1); 22825 } 22826 /* 22827 * The array needs to be NULLed. 22828 * TODO: Use memset? 22829 */ 22830 for (; i < matcher->sizeKeySeqs; i++) 22831 matcher->keySeqs[i] = NULL; 22832 } 22833 22834 /* 22835 * Get/create the key-sequence. 22836 */ 22837 keySeq = matcher->keySeqs[pos]; 22838 if (keySeq == NULL) { 22839 goto create_sequence; 22840 } else if (keySeq[idx] != NULL) { 22841 xmlChar *str = NULL; 22842 /* 22843 * cvc-identity-constraint: 22844 * 3 For each node in the �target node set� all 22845 * of the {fields}, with that node as the context 22846 * node, evaluate to either an empty node-set or 22847 * a node-set with exactly one member, which must 22848 * have a simple type. 22849 * 22850 * The key was already set; report an error. 22851 */ 22852 xmlSchemaCustomErr(ACTXT_CAST vctxt, 22853 XML_SCHEMAV_CVC_IDC, NULL, 22854 WXS_BASIC_CAST matcher->aidc->def, 22855 "The XPath '%s' of a field of %s evaluates to a " 22856 "node-set with more than one member", 22857 sto->sel->xpath, 22858 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def)); 22859 FREE_AND_NULL(str); 22860 sto->nbHistory--; 22861 goto deregister_check; 22862 } else 22863 goto create_key; 22864 22865create_sequence: 22866 /* 22867 * Create a key-sequence. 22868 */ 22869 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc( 22870 matcher->aidc->def->nbFields * 22871 sizeof(xmlSchemaPSVIIDCKeyPtr)); 22872 if (keySeq == NULL) { 22873 xmlSchemaVErrMemory(NULL, 22874 "allocating an IDC key-sequence", NULL); 22875 return(-1); 22876 } 22877 memset(keySeq, 0, matcher->aidc->def->nbFields * 22878 sizeof(xmlSchemaPSVIIDCKeyPtr)); 22879 matcher->keySeqs[pos] = keySeq; 22880create_key: 22881 /* 22882 * Create a key once per node only. 22883 */ 22884 if (key == NULL) { 22885 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc( 22886 sizeof(xmlSchemaPSVIIDCKey)); 22887 if (key == NULL) { 22888 xmlSchemaVErrMemory(NULL, 22889 "allocating a IDC key", NULL); 22890 xmlFree(keySeq); 22891 matcher->keySeqs[pos] = NULL; 22892 return(-1); 22893 } 22894 /* 22895 * Consume the compiled value. 22896 */ 22897 key->type = simpleType; 22898 key->val = vctxt->inode->val; 22899 vctxt->inode->val = NULL; 22900 /* 22901 * Store the key in a global list. 22902 */ 22903 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) { 22904 xmlSchemaIDCFreeKey(key); 22905 return (-1); 22906 } 22907 } 22908 keySeq[idx] = key; 22909 } 22910 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) { 22911 22912 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL; 22913 /* xmlSchemaPSVIIDCBindingPtr bind; */ 22914 xmlSchemaPSVIIDCNodePtr ntItem; 22915 xmlSchemaIDCMatcherPtr matcher; 22916 xmlSchemaIDCPtr idc; 22917 xmlSchemaItemListPtr targets; 22918 int pos, i, j, nbKeys; 22919 /* 22920 * Here we have the following scenario: 22921 * An IDC 'selector' state object resolved to a target node, 22922 * during the time this target node was in the 22923 * ancestor-or-self axis, the 'field' state object(s) looked 22924 * out for matching nodes to create a key-sequence for this 22925 * target node. Now we are back to this target node and need 22926 * to put the key-sequence, together with the target node 22927 * itself, into the node-table of the corresponding IDC 22928 * binding. 22929 */ 22930 matcher = sto->matcher; 22931 idc = matcher->aidc->def; 22932 nbKeys = idc->nbFields; 22933 pos = depth - matcher->depth; 22934 /* 22935 * Check if the matcher has any key-sequences at all, plus 22936 * if it has a key-sequence for the current target node. 22937 */ 22938 if ((matcher->keySeqs == NULL) || 22939 (matcher->sizeKeySeqs <= pos)) { 22940 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) 22941 goto selector_key_error; 22942 else 22943 goto selector_leave; 22944 } 22945 22946 keySeq = &(matcher->keySeqs[pos]); 22947 if (*keySeq == NULL) { 22948 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) 22949 goto selector_key_error; 22950 else 22951 goto selector_leave; 22952 } 22953 22954 for (i = 0; i < nbKeys; i++) { 22955 if ((*keySeq)[i] == NULL) { 22956 /* 22957 * Not qualified, if not all fields did resolve. 22958 */ 22959 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) { 22960 /* 22961 * All fields of a "key" IDC must resolve. 22962 */ 22963 goto selector_key_error; 22964 } 22965 goto selector_leave; 22966 } 22967 } 22968 /* 22969 * All fields did resolve. 22970 */ 22971 22972 /* 22973 * 4.1 If the {identity-constraint category} is unique(/key), 22974 * then no two members of the �qualified node set� have 22975 * �key-sequences� whose members are pairwise equal, as 22976 * defined by Equal in [XML Schemas: Datatypes]. 22977 * 22978 * Get the IDC binding from the matcher and check for 22979 * duplicate key-sequences. 22980 */ 22981#if 0 22982 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher); 22983#endif 22984 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher); 22985 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) && 22986 (targets->nbItems != 0)) { 22987 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq; 22988 22989 i = 0; 22990 res = 0; 22991 /* 22992 * Compare the key-sequences, key by key. 22993 */ 22994 do { 22995 bkeySeq = 22996 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys; 22997 for (j = 0; j < nbKeys; j++) { 22998 ckey = (*keySeq)[j]; 22999 bkey = bkeySeq[j]; 23000 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val); 23001 if (res == -1) { 23002 return (-1); 23003 } else if (res == 0) { 23004 /* 23005 * One of the keys differs, so the key-sequence 23006 * won't be equal; get out. 23007 */ 23008 break; 23009 } 23010 } 23011 if (res == 1) { 23012 /* 23013 * Duplicate key-sequence found. 23014 */ 23015 break; 23016 } 23017 i++; 23018 } while (i < targets->nbItems); 23019 if (i != targets->nbItems) { 23020 xmlChar *str = NULL, *strB = NULL; 23021 /* 23022 * TODO: Try to report the key-sequence. 23023 */ 23024 xmlSchemaCustomErr(ACTXT_CAST vctxt, 23025 XML_SCHEMAV_CVC_IDC, NULL, 23026 WXS_BASIC_CAST idc, 23027 "Duplicate key-sequence %s in %s", 23028 xmlSchemaFormatIDCKeySequence(vctxt, &str, 23029 (*keySeq), nbKeys), 23030 xmlSchemaGetIDCDesignation(&strB, idc)); 23031 FREE_AND_NULL(str); 23032 FREE_AND_NULL(strB); 23033 goto selector_leave; 23034 } 23035 } 23036 /* 23037 * Add a node-table item to the IDC binding. 23038 */ 23039 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc( 23040 sizeof(xmlSchemaPSVIIDCNode)); 23041 if (ntItem == NULL) { 23042 xmlSchemaVErrMemory(NULL, 23043 "allocating an IDC node-table item", NULL); 23044 xmlFree(*keySeq); 23045 *keySeq = NULL; 23046 return(-1); 23047 } 23048 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode)); 23049 23050 /* 23051 * Store the node-table item in a global list. 23052 */ 23053 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) { 23054 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) { 23055 xmlFree(ntItem); 23056 xmlFree(*keySeq); 23057 *keySeq = NULL; 23058 return (-1); 23059 } 23060 ntItem->nodeQNameID = -1; 23061 } else { 23062 /* 23063 * Save a cached QName for this node on the IDC node, to be 23064 * able to report it, even if the node is not saved. 23065 */ 23066 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt, 23067 vctxt->inode->localName, vctxt->inode->nsName); 23068 if (ntItem->nodeQNameID == -1) { 23069 xmlFree(ntItem); 23070 xmlFree(*keySeq); 23071 *keySeq = NULL; 23072 return (-1); 23073 } 23074 } 23075 /* 23076 * Init the node-table item: Save the node, position and 23077 * consume the key-sequence. 23078 */ 23079 ntItem->node = vctxt->node; 23080 ntItem->nodeLine = vctxt->inode->nodeLine; 23081 ntItem->keys = *keySeq; 23082 *keySeq = NULL; 23083#if 0 23084 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) 23085#endif 23086 if (xmlSchemaItemListAdd(targets, ntItem) == -1) { 23087 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) { 23088 /* 23089 * Free the item, since keyref items won't be 23090 * put on a global list. 23091 */ 23092 xmlFree(ntItem->keys); 23093 xmlFree(ntItem); 23094 } 23095 return (-1); 23096 } 23097 23098 goto selector_leave; 23099selector_key_error: 23100 { 23101 xmlChar *str = NULL; 23102 /* 23103 * 4.2.1 (KEY) The �target node set� and the 23104 * �qualified node set� are equal, that is, every 23105 * member of the �target node set� is also a member 23106 * of the �qualified node set� and vice versa. 23107 */ 23108 xmlSchemaCustomErr(ACTXT_CAST vctxt, 23109 XML_SCHEMAV_CVC_IDC, NULL, 23110 WXS_BASIC_CAST idc, 23111 "Not all fields of %s evaluate to a node", 23112 xmlSchemaGetIDCDesignation(&str, idc), NULL); 23113 FREE_AND_NULL(str); 23114 } 23115selector_leave: 23116 /* 23117 * Free the key-sequence if not added to the IDC table. 23118 */ 23119 if ((keySeq != NULL) && (*keySeq != NULL)) { 23120 xmlFree(*keySeq); 23121 *keySeq = NULL; 23122 } 23123 } /* if selector */ 23124 23125 sto->nbHistory--; 23126 23127deregister_check: 23128 /* 23129 * Deregister state objects if they reach the depth of creation. 23130 */ 23131 if ((sto->nbHistory == 0) && (sto->depth == depth)) { 23132#ifdef DEBUG_IDC 23133 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n", 23134 sto->sel->xpath); 23135#endif 23136 if (vctxt->xpathStates != sto) { 23137 VERROR_INT("xmlSchemaXPathProcessHistory", 23138 "The state object to be removed is not the first " 23139 "in the list"); 23140 } 23141 nextsto = sto->next; 23142 /* 23143 * Unlink from the list of active XPath state objects. 23144 */ 23145 vctxt->xpathStates = sto->next; 23146 sto->next = vctxt->xpathStatePool; 23147 /* 23148 * Link it to the pool of reusable state objects. 23149 */ 23150 vctxt->xpathStatePool = sto; 23151 sto = nextsto; 23152 } else 23153 sto = sto->next; 23154 } /* while (sto != NULL) */ 23155 return (0); 23156} 23157 23158/** 23159 * xmlSchemaIDCRegisterMatchers: 23160 * @vctxt: the WXS validation context 23161 * @elemDecl: the element declaration 23162 * 23163 * Creates helper objects to evaluate IDC selectors/fields 23164 * successively. 23165 * 23166 * Returns 0 if OK and -1 on internal errors. 23167 */ 23168static int 23169xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt, 23170 xmlSchemaElementPtr elemDecl) 23171{ 23172 xmlSchemaIDCMatcherPtr matcher, last = NULL; 23173 xmlSchemaIDCPtr idc, refIdc; 23174 xmlSchemaIDCAugPtr aidc; 23175 23176 idc = (xmlSchemaIDCPtr) elemDecl->idcs; 23177 if (idc == NULL) 23178 return (0); 23179 23180#ifdef DEBUG_IDC 23181 { 23182 xmlChar *str = NULL; 23183 xmlGenericError(xmlGenericErrorContext, 23184 "IDC: REGISTER on %s, depth %d\n", 23185 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName, 23186 vctxt->inode->localName), vctxt->depth); 23187 FREE_AND_NULL(str) 23188 } 23189#endif 23190 if (vctxt->inode->idcMatchers != NULL) { 23191 VERROR_INT("xmlSchemaIDCRegisterMatchers", 23192 "The chain of IDC matchers is expected to be empty"); 23193 return (-1); 23194 } 23195 do { 23196 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) { 23197 /* 23198 * Since IDCs bubbles are expensive we need to know the 23199 * depth at which the bubbles should stop; this will be 23200 * the depth of the top-most keyref IDC. If no keyref 23201 * references a key/unique IDC, the keyrefDepth will 23202 * be -1, indicating that no bubbles are needed. 23203 */ 23204 refIdc = (xmlSchemaIDCPtr) idc->ref->item; 23205 if (refIdc != NULL) { 23206 /* 23207 * Remember that we have keyrefs on this node. 23208 */ 23209 vctxt->inode->hasKeyrefs = 1; 23210 /* 23211 * Lookup the referenced augmented IDC info. 23212 */ 23213 aidc = vctxt->aidcs; 23214 while (aidc != NULL) { 23215 if (aidc->def == refIdc) 23216 break; 23217 aidc = aidc->next; 23218 } 23219 if (aidc == NULL) { 23220 VERROR_INT("xmlSchemaIDCRegisterMatchers", 23221 "Could not find an augmented IDC item for an IDC " 23222 "definition"); 23223 return (-1); 23224 } 23225 if ((aidc->keyrefDepth == -1) || 23226 (vctxt->depth < aidc->keyrefDepth)) 23227 aidc->keyrefDepth = vctxt->depth; 23228 } 23229 } 23230 /* 23231 * Lookup the augmented IDC item for the IDC definition. 23232 */ 23233 aidc = vctxt->aidcs; 23234 while (aidc != NULL) { 23235 if (aidc->def == idc) 23236 break; 23237 aidc = aidc->next; 23238 } 23239 if (aidc == NULL) { 23240 VERROR_INT("xmlSchemaIDCRegisterMatchers", 23241 "Could not find an augmented IDC item for an IDC definition"); 23242 return (-1); 23243 } 23244 /* 23245 * Create an IDC matcher for every IDC definition. 23246 */ 23247 if (vctxt->idcMatcherCache != NULL) { 23248 /* 23249 * Reuse a cached matcher. 23250 */ 23251 matcher = vctxt->idcMatcherCache; 23252 vctxt->idcMatcherCache = matcher->nextCached; 23253 matcher->nextCached = NULL; 23254 } else { 23255 matcher = (xmlSchemaIDCMatcherPtr) 23256 xmlMalloc(sizeof(xmlSchemaIDCMatcher)); 23257 if (matcher == NULL) { 23258 xmlSchemaVErrMemory(vctxt, 23259 "allocating an IDC matcher", NULL); 23260 return (-1); 23261 } 23262 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher)); 23263 } 23264 if (last == NULL) 23265 vctxt->inode->idcMatchers = matcher; 23266 else 23267 last->next = matcher; 23268 last = matcher; 23269 23270 matcher->type = IDC_MATCHER; 23271 matcher->depth = vctxt->depth; 23272 matcher->aidc = aidc; 23273 matcher->idcType = aidc->def->type; 23274#ifdef DEBUG_IDC 23275 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n"); 23276#endif 23277 /* 23278 * Init the automaton state object. 23279 */ 23280 if (xmlSchemaIDCAddStateObject(vctxt, matcher, 23281 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1) 23282 return (-1); 23283 23284 idc = idc->next; 23285 } while (idc != NULL); 23286 return (0); 23287} 23288 23289static int 23290xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt, 23291 xmlSchemaNodeInfoPtr ielem) 23292{ 23293 xmlSchemaPSVIIDCBindingPtr bind; 23294 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable; 23295 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys; 23296 xmlSchemaPSVIIDCNodePtr *targets, *dupls; 23297 23298 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers; 23299 /* vctxt->createIDCNodeTables */ 23300 while (matcher != NULL) { 23301 /* 23302 * Skip keyref IDCs and empty IDC target-lists. 23303 */ 23304 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) || 23305 WXS_ILIST_IS_EMPTY(matcher->targets)) 23306 { 23307 matcher = matcher->next; 23308 continue; 23309 } 23310 /* 23311 * If we _want_ the IDC node-table to be created in any case 23312 * then do so. Otherwise create them only if keyrefs need them. 23313 */ 23314 if ((! vctxt->createIDCNodeTables) && 23315 ((matcher->aidc->keyrefDepth == -1) || 23316 (matcher->aidc->keyrefDepth > vctxt->depth))) 23317 { 23318 matcher = matcher->next; 23319 continue; 23320 } 23321 /* 23322 * Get/create the IDC binding on this element for the IDC definition. 23323 */ 23324 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher); 23325 23326 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) { 23327 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items; 23328 nbDupls = bind->dupls->nbItems; 23329 } else { 23330 dupls = NULL; 23331 nbDupls = 0; 23332 } 23333 if (bind->nodeTable != NULL) { 23334 nbNodeTable = bind->nbNodes; 23335 } else { 23336 nbNodeTable = 0; 23337 } 23338 23339 if ((nbNodeTable == 0) && (nbDupls == 0)) { 23340 /* 23341 * Transfer all IDC target-nodes to the IDC node-table. 23342 */ 23343 bind->nodeTable = 23344 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items; 23345 bind->sizeNodes = matcher->targets->sizeItems; 23346 bind->nbNodes = matcher->targets->nbItems; 23347 23348 matcher->targets->items = NULL; 23349 matcher->targets->sizeItems = 0; 23350 matcher->targets->nbItems = 0; 23351 } else { 23352 /* 23353 * Compare the key-sequences and add to the IDC node-table. 23354 */ 23355 nbTargets = matcher->targets->nbItems; 23356 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items; 23357 nbFields = matcher->aidc->def->nbFields; 23358 i = 0; 23359 do { 23360 keys = targets[i]->keys; 23361 if (nbDupls) { 23362 /* 23363 * Search in already found duplicates first. 23364 */ 23365 j = 0; 23366 do { 23367 if (nbFields == 1) { 23368 res = xmlSchemaAreValuesEqual(keys[0]->val, 23369 dupls[j]->keys[0]->val); 23370 if (res == -1) 23371 goto internal_error; 23372 if (res == 1) { 23373 /* 23374 * Equal key-sequence. 23375 */ 23376 goto next_target; 23377 } 23378 } else { 23379 res = 0; 23380 ntkeys = dupls[j]->keys; 23381 for (k = 0; k < nbFields; k++) { 23382 res = xmlSchemaAreValuesEqual(keys[k]->val, 23383 ntkeys[k]->val); 23384 if (res == -1) 23385 goto internal_error; 23386 if (res == 0) { 23387 /* 23388 * One of the keys differs. 23389 */ 23390 break; 23391 } 23392 } 23393 if (res == 1) { 23394 /* 23395 * Equal key-sequence found. 23396 */ 23397 goto next_target; 23398 } 23399 } 23400 j++; 23401 } while (j < nbDupls); 23402 } 23403 if (nbNodeTable) { 23404 j = 0; 23405 do { 23406 if (nbFields == 1) { 23407 res = xmlSchemaAreValuesEqual(keys[0]->val, 23408 bind->nodeTable[j]->keys[0]->val); 23409 if (res == -1) 23410 goto internal_error; 23411 if (res == 0) { 23412 /* 23413 * The key-sequence differs. 23414 */ 23415 goto next_node_table_entry; 23416 } 23417 } else { 23418 res = 0; 23419 ntkeys = bind->nodeTable[j]->keys; 23420 for (k = 0; k < nbFields; k++) { 23421 res = xmlSchemaAreValuesEqual(keys[k]->val, 23422 ntkeys[k]->val); 23423 if (res == -1) 23424 goto internal_error; 23425 if (res == 0) { 23426 /* 23427 * One of the keys differs. 23428 */ 23429 goto next_node_table_entry; 23430 } 23431 } 23432 } 23433 /* 23434 * Add the duplicate to the list of duplicates. 23435 */ 23436 if (bind->dupls == NULL) { 23437 bind->dupls = xmlSchemaItemListCreate(); 23438 if (bind->dupls == NULL) 23439 goto internal_error; 23440 } 23441 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1) 23442 goto internal_error; 23443 /* 23444 * Remove the duplicate entry from the IDC node-table. 23445 */ 23446 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1]; 23447 bind->nbNodes--; 23448 23449 goto next_target; 23450 23451next_node_table_entry: 23452 j++; 23453 } while (j < nbNodeTable); 23454 } 23455 /* 23456 * If everything is fine, then add the IDC target-node to 23457 * the IDC node-table. 23458 */ 23459 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1) 23460 goto internal_error; 23461 23462next_target: 23463 i++; 23464 } while (i < nbTargets); 23465 } 23466 matcher = matcher->next; 23467 } 23468 return(0); 23469 23470internal_error: 23471 return(-1); 23472} 23473 23474/** 23475 * xmlSchemaBubbleIDCNodeTables: 23476 * @depth: the current tree depth 23477 * 23478 * Merges IDC bindings of an element at @depth into the corresponding IDC 23479 * bindings of its parent element. If a duplicate note-table entry is found, 23480 * both, the parent node-table entry and child entry are discarded from the 23481 * node-table of the parent. 23482 * 23483 * Returns 0 if OK and -1 on internal errors. 23484 */ 23485static int 23486xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt) 23487{ 23488 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */ 23489 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */ 23490 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */ 23491 xmlSchemaIDCAugPtr aidc; 23492 int i, j, k, ret = 0, nbFields, oldNum, oldDupls; 23493 23494 bind = vctxt->inode->idcTable; 23495 if (bind == NULL) { 23496 /* Fine, no table, no bubbles. */ 23497 return (0); 23498 } 23499 23500 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable); 23501 /* 23502 * Walk all bindings; create new or add to existing bindings. 23503 * Remove duplicate key-sequences. 23504 */ 23505 while (bind != NULL) { 23506 23507 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls)) 23508 goto next_binding; 23509 /* 23510 * Check if the key/unique IDC table needs to be bubbled. 23511 */ 23512 if (! vctxt->createIDCNodeTables) { 23513 aidc = vctxt->aidcs; 23514 do { 23515 if (aidc->def == bind->definition) { 23516 if ((aidc->keyrefDepth == -1) || 23517 (aidc->keyrefDepth >= vctxt->depth)) { 23518 goto next_binding; 23519 } 23520 break; 23521 } 23522 aidc = aidc->next; 23523 } while (aidc != NULL); 23524 } 23525 23526 if (parTable != NULL) 23527 parBind = *parTable; 23528 /* 23529 * Search a matching parent binding for the 23530 * IDC definition. 23531 */ 23532 while (parBind != NULL) { 23533 if (parBind->definition == bind->definition) 23534 break; 23535 parBind = parBind->next; 23536 } 23537 23538 if (parBind != NULL) { 23539 /* 23540 * Compare every node-table entry of the child node, 23541 * i.e. the key-sequence within, ... 23542 */ 23543 oldNum = parBind->nbNodes; /* Skip newly added items. */ 23544 23545 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) { 23546 oldDupls = parBind->dupls->nbItems; 23547 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items; 23548 } else { 23549 dupls = NULL; 23550 oldDupls = 0; 23551 } 23552 23553 parNodes = parBind->nodeTable; 23554 nbFields = bind->definition->nbFields; 23555 23556 for (i = 0; i < bind->nbNodes; i++) { 23557 node = bind->nodeTable[i]; 23558 if (node == NULL) 23559 continue; 23560 /* 23561 * ...with every key-sequence of the parent node, already 23562 * evaluated to be a duplicate key-sequence. 23563 */ 23564 if (oldDupls) { 23565 j = 0; 23566 while (j < oldDupls) { 23567 if (nbFields == 1) { 23568 ret = xmlSchemaAreValuesEqual( 23569 node->keys[0]->val, 23570 dupls[j]->keys[0]->val); 23571 if (ret == -1) 23572 goto internal_error; 23573 if (ret == 0) { 23574 j++; 23575 continue; 23576 } 23577 } else { 23578 parNode = dupls[j]; 23579 for (k = 0; k < nbFields; k++) { 23580 ret = xmlSchemaAreValuesEqual( 23581 node->keys[k]->val, 23582 parNode->keys[k]->val); 23583 if (ret == -1) 23584 goto internal_error; 23585 if (ret == 0) 23586 break; 23587 } 23588 } 23589 if (ret == 1) 23590 /* Duplicate found. */ 23591 break; 23592 j++; 23593 } 23594 if (j != oldDupls) { 23595 /* Duplicate found. Skip this entry. */ 23596 continue; 23597 } 23598 } 23599 /* 23600 * ... and with every key-sequence of the parent node. 23601 */ 23602 if (oldNum) { 23603 j = 0; 23604 while (j < oldNum) { 23605 parNode = parNodes[j]; 23606 if (nbFields == 1) { 23607 ret = xmlSchemaAreValuesEqual( 23608 node->keys[0]->val, 23609 parNode->keys[0]->val); 23610 if (ret == -1) 23611 goto internal_error; 23612 if (ret == 0) { 23613 j++; 23614 continue; 23615 } 23616 } else { 23617 for (k = 0; k < nbFields; k++) { 23618 ret = xmlSchemaAreValuesEqual( 23619 node->keys[k]->val, 23620 parNode->keys[k]->val); 23621 if (ret == -1) 23622 goto internal_error; 23623 if (ret == 0) 23624 break; 23625 } 23626 } 23627 if (ret == 1) 23628 /* Duplicate found. */ 23629 break; 23630 j++; 23631 } 23632 if (j != oldNum) { 23633 /* 23634 * Handle duplicates. Move the duplicate in 23635 * the parent's node-table to the list of 23636 * duplicates. 23637 */ 23638 oldNum--; 23639 parBind->nbNodes--; 23640 /* 23641 * Move last old item to pos of duplicate. 23642 */ 23643 parNodes[j] = parNodes[oldNum]; 23644 23645 if (parBind->nbNodes != oldNum) { 23646 /* 23647 * If new items exist, move last new item to 23648 * last of old items. 23649 */ 23650 parNodes[oldNum] = 23651 parNodes[parBind->nbNodes]; 23652 } 23653 if (parBind->dupls == NULL) { 23654 parBind->dupls = xmlSchemaItemListCreate(); 23655 if (parBind->dupls == NULL) 23656 goto internal_error; 23657 } 23658 xmlSchemaItemListAdd(parBind->dupls, parNode); 23659 } else { 23660 /* 23661 * Add the node-table entry (node and key-sequence) of 23662 * the child node to the node table of the parent node. 23663 */ 23664 if (parBind->nodeTable == NULL) { 23665 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) 23666 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr)); 23667 if (parBind->nodeTable == NULL) { 23668 xmlSchemaVErrMemory(NULL, 23669 "allocating IDC list of node-table items", NULL); 23670 goto internal_error; 23671 } 23672 parBind->sizeNodes = 1; 23673 } else if (parBind->nbNodes >= parBind->sizeNodes) { 23674 parBind->sizeNodes *= 2; 23675 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) 23676 xmlRealloc(parBind->nodeTable, parBind->sizeNodes * 23677 sizeof(xmlSchemaPSVIIDCNodePtr)); 23678 if (parBind->nodeTable == NULL) { 23679 xmlSchemaVErrMemory(NULL, 23680 "re-allocating IDC list of node-table items", NULL); 23681 goto internal_error; 23682 } 23683 } 23684 parNodes = parBind->nodeTable; 23685 /* 23686 * Append the new node-table entry to the 'new node-table 23687 * entries' section. 23688 */ 23689 parNodes[parBind->nbNodes++] = node; 23690 } 23691 23692 } 23693 23694 } 23695 } else { 23696 /* 23697 * No binding for the IDC was found: create a new one and 23698 * copy all node-tables. 23699 */ 23700 parBind = xmlSchemaIDCNewBinding(bind->definition); 23701 if (parBind == NULL) 23702 goto internal_error; 23703 23704 /* 23705 * TODO: Hmm, how to optimize the initial number of 23706 * allocated entries? 23707 */ 23708 if (bind->nbNodes != 0) { 23709 /* 23710 * Add all IDC node-table entries. 23711 */ 23712 if (! vctxt->psviExposeIDCNodeTables) { 23713 /* 23714 * Just move the entries. 23715 * NOTE: this is quite save here, since 23716 * all the keyref lookups have already been 23717 * performed. 23718 */ 23719 parBind->nodeTable = bind->nodeTable; 23720 bind->nodeTable = NULL; 23721 parBind->sizeNodes = bind->sizeNodes; 23722 bind->sizeNodes = 0; 23723 parBind->nbNodes = bind->nbNodes; 23724 bind->nbNodes = 0; 23725 } else { 23726 /* 23727 * Copy the entries. 23728 */ 23729 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) 23730 xmlMalloc(bind->nbNodes * 23731 sizeof(xmlSchemaPSVIIDCNodePtr)); 23732 if (parBind->nodeTable == NULL) { 23733 xmlSchemaVErrMemory(NULL, 23734 "allocating an array of IDC node-table " 23735 "items", NULL); 23736 xmlSchemaIDCFreeBinding(parBind); 23737 goto internal_error; 23738 } 23739 parBind->sizeNodes = bind->nbNodes; 23740 parBind->nbNodes = bind->nbNodes; 23741 memcpy(parBind->nodeTable, bind->nodeTable, 23742 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr)); 23743 } 23744 } 23745 if (bind->dupls) { 23746 /* 23747 * Move the duplicates. 23748 */ 23749 if (parBind->dupls != NULL) 23750 xmlSchemaItemListFree(parBind->dupls); 23751 parBind->dupls = bind->dupls; 23752 bind->dupls = NULL; 23753 } 23754 if (parTable != NULL) { 23755 if (*parTable == NULL) 23756 *parTable = parBind; 23757 else { 23758 parBind->next = *parTable; 23759 *parTable = parBind; 23760 } 23761 } 23762 } 23763 23764next_binding: 23765 bind = bind->next; 23766 } 23767 return (0); 23768 23769internal_error: 23770 return(-1); 23771} 23772 23773/** 23774 * xmlSchemaCheckCVCIDCKeyRef: 23775 * @vctxt: the WXS validation context 23776 * @elemDecl: the element declaration 23777 * 23778 * Check the cvc-idc-keyref constraints. 23779 */ 23780static int 23781xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt) 23782{ 23783 xmlSchemaIDCMatcherPtr matcher; 23784 xmlSchemaPSVIIDCBindingPtr bind; 23785 23786 matcher = vctxt->inode->idcMatchers; 23787 /* 23788 * Find a keyref. 23789 */ 23790 while (matcher != NULL) { 23791 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) && 23792 matcher->targets && 23793 matcher->targets->nbItems) 23794 { 23795 int i, j, k, res, nbFields, hasDupls; 23796 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys; 23797 xmlSchemaPSVIIDCNodePtr refNode = NULL; 23798 23799 nbFields = matcher->aidc->def->nbFields; 23800 23801 /* 23802 * Find the IDC node-table for the referenced IDC key/unique. 23803 */ 23804 bind = vctxt->inode->idcTable; 23805 while (bind != NULL) { 23806 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item == 23807 bind->definition) 23808 break; 23809 bind = bind->next; 23810 } 23811 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0; 23812 /* 23813 * Search for a matching key-sequences. 23814 */ 23815 for (i = 0; i < matcher->targets->nbItems; i++) { 23816 res = 0; 23817 refNode = matcher->targets->items[i]; 23818 if (bind != NULL) { 23819 refKeys = refNode->keys; 23820 for (j = 0; j < bind->nbNodes; j++) { 23821 keys = bind->nodeTable[j]->keys; 23822 for (k = 0; k < nbFields; k++) { 23823 res = xmlSchemaAreValuesEqual(keys[k]->val, 23824 refKeys[k]->val); 23825 if (res == 0) 23826 break; 23827 else if (res == -1) { 23828 return (-1); 23829 } 23830 } 23831 if (res == 1) { 23832 /* 23833 * Match found. 23834 */ 23835 break; 23836 } 23837 } 23838 if ((res == 0) && hasDupls) { 23839 /* 23840 * Search in duplicates 23841 */ 23842 for (j = 0; j < bind->dupls->nbItems; j++) { 23843 keys = ((xmlSchemaPSVIIDCNodePtr) 23844 bind->dupls->items[j])->keys; 23845 for (k = 0; k < nbFields; k++) { 23846 res = xmlSchemaAreValuesEqual(keys[k]->val, 23847 refKeys[k]->val); 23848 if (res == 0) 23849 break; 23850 else if (res == -1) { 23851 return (-1); 23852 } 23853 } 23854 if (res == 1) { 23855 /* 23856 * Match in duplicates found. 23857 */ 23858 xmlChar *str = NULL, *strB = NULL; 23859 xmlSchemaKeyrefErr(vctxt, 23860 XML_SCHEMAV_CVC_IDC, refNode, 23861 (xmlSchemaTypePtr) matcher->aidc->def, 23862 "More than one match found for " 23863 "key-sequence %s of keyref '%s'", 23864 xmlSchemaFormatIDCKeySequence(vctxt, &str, 23865 refNode->keys, nbFields), 23866 xmlSchemaGetComponentQName(&strB, 23867 matcher->aidc->def)); 23868 FREE_AND_NULL(str); 23869 FREE_AND_NULL(strB); 23870 break; 23871 } 23872 } 23873 } 23874 } 23875 23876 if (res == 0) { 23877 xmlChar *str = NULL, *strB = NULL; 23878 xmlSchemaKeyrefErr(vctxt, 23879 XML_SCHEMAV_CVC_IDC, refNode, 23880 (xmlSchemaTypePtr) matcher->aidc->def, 23881 "No match found for key-sequence %s of keyref '%s'", 23882 xmlSchemaFormatIDCKeySequence(vctxt, &str, 23883 refNode->keys, nbFields), 23884 xmlSchemaGetComponentQName(&strB, matcher->aidc->def)); 23885 FREE_AND_NULL(str); 23886 FREE_AND_NULL(strB); 23887 } 23888 } 23889 } 23890 matcher = matcher->next; 23891 } 23892 /* TODO: Return an error if any error encountered. */ 23893 return (0); 23894} 23895 23896/************************************************************************ 23897 * * 23898 * XML Reader validation code * 23899 * * 23900 ************************************************************************/ 23901 23902static xmlSchemaAttrInfoPtr 23903xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt) 23904{ 23905 xmlSchemaAttrInfoPtr iattr; 23906 /* 23907 * Grow/create list of attribute infos. 23908 */ 23909 if (vctxt->attrInfos == NULL) { 23910 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *) 23911 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr)); 23912 vctxt->sizeAttrInfos = 1; 23913 if (vctxt->attrInfos == NULL) { 23914 xmlSchemaVErrMemory(vctxt, 23915 "allocating attribute info list", NULL); 23916 return (NULL); 23917 } 23918 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) { 23919 vctxt->sizeAttrInfos++; 23920 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *) 23921 xmlRealloc(vctxt->attrInfos, 23922 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr)); 23923 if (vctxt->attrInfos == NULL) { 23924 xmlSchemaVErrMemory(vctxt, 23925 "re-allocating attribute info list", NULL); 23926 return (NULL); 23927 } 23928 } else { 23929 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++]; 23930 if (iattr->localName != NULL) { 23931 VERROR_INT("xmlSchemaGetFreshAttrInfo", 23932 "attr info not cleared"); 23933 return (NULL); 23934 } 23935 iattr->nodeType = XML_ATTRIBUTE_NODE; 23936 return (iattr); 23937 } 23938 /* 23939 * Create an attribute info. 23940 */ 23941 iattr = (xmlSchemaAttrInfoPtr) 23942 xmlMalloc(sizeof(xmlSchemaAttrInfo)); 23943 if (iattr == NULL) { 23944 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL); 23945 return (NULL); 23946 } 23947 memset(iattr, 0, sizeof(xmlSchemaAttrInfo)); 23948 iattr->nodeType = XML_ATTRIBUTE_NODE; 23949 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr; 23950 23951 return (iattr); 23952} 23953 23954static int 23955xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt, 23956 xmlNodePtr attrNode, 23957 int nodeLine, 23958 const xmlChar *localName, 23959 const xmlChar *nsName, 23960 int ownedNames, 23961 xmlChar *value, 23962 int ownedValue) 23963{ 23964 xmlSchemaAttrInfoPtr attr; 23965 23966 attr = xmlSchemaGetFreshAttrInfo(vctxt); 23967 if (attr == NULL) { 23968 VERROR_INT("xmlSchemaPushAttribute", 23969 "calling xmlSchemaGetFreshAttrInfo()"); 23970 return (-1); 23971 } 23972 attr->node = attrNode; 23973 attr->nodeLine = nodeLine; 23974 attr->state = XML_SCHEMAS_ATTR_UNKNOWN; 23975 attr->localName = localName; 23976 attr->nsName = nsName; 23977 if (ownedNames) 23978 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES; 23979 /* 23980 * Evaluate if it's an XSI attribute. 23981 */ 23982 if (nsName != NULL) { 23983 if (xmlStrEqual(localName, BAD_CAST "nil")) { 23984 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { 23985 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL; 23986 } 23987 } else if (xmlStrEqual(localName, BAD_CAST "type")) { 23988 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { 23989 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE; 23990 } 23991 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) { 23992 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { 23993 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC; 23994 } 23995 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) { 23996 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { 23997 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC; 23998 } 23999 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) { 24000 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS; 24001 } 24002 } 24003 attr->value = value; 24004 if (ownedValue) 24005 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; 24006 if (attr->metaType != 0) 24007 attr->state = XML_SCHEMAS_ATTR_META; 24008 return (0); 24009} 24010 24011/** 24012 * xmlSchemaClearElemInfo: 24013 * @vctxt: the WXS validation context 24014 * @ielem: the element information item 24015 */ 24016static void 24017xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt, 24018 xmlSchemaNodeInfoPtr ielem) 24019{ 24020 ielem->hasKeyrefs = 0; 24021 ielem->appliedXPath = 0; 24022 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) { 24023 FREE_AND_NULL(ielem->localName); 24024 FREE_AND_NULL(ielem->nsName); 24025 } else { 24026 ielem->localName = NULL; 24027 ielem->nsName = NULL; 24028 } 24029 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) { 24030 FREE_AND_NULL(ielem->value); 24031 } else { 24032 ielem->value = NULL; 24033 } 24034 if (ielem->val != NULL) { 24035 /* 24036 * PSVI TODO: Be careful not to free it when the value is 24037 * exposed via PSVI. 24038 */ 24039 xmlSchemaFreeValue(ielem->val); 24040 ielem->val = NULL; 24041 } 24042 if (ielem->idcMatchers != NULL) { 24043 /* 24044 * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers. 24045 * Does it work? 24046 */ 24047 xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers); 24048#if 0 24049 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers); 24050#endif 24051 ielem->idcMatchers = NULL; 24052 } 24053 if (ielem->idcTable != NULL) { 24054 /* 24055 * OPTIMIZE TODO: Use a pool of IDC tables??. 24056 */ 24057 xmlSchemaIDCFreeIDCTable(ielem->idcTable); 24058 ielem->idcTable = NULL; 24059 } 24060 if (ielem->regexCtxt != NULL) { 24061 xmlRegFreeExecCtxt(ielem->regexCtxt); 24062 ielem->regexCtxt = NULL; 24063 } 24064 if (ielem->nsBindings != NULL) { 24065 xmlFree((xmlChar **)ielem->nsBindings); 24066 ielem->nsBindings = NULL; 24067 ielem->nbNsBindings = 0; 24068 ielem->sizeNsBindings = 0; 24069 } 24070} 24071 24072/** 24073 * xmlSchemaGetFreshElemInfo: 24074 * @vctxt: the schema validation context 24075 * 24076 * Creates/reuses and initializes the element info item for 24077 * the currect tree depth. 24078 * 24079 * Returns the element info item or NULL on API or internal errors. 24080 */ 24081static xmlSchemaNodeInfoPtr 24082xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt) 24083{ 24084 xmlSchemaNodeInfoPtr info = NULL; 24085 24086 if (vctxt->depth > vctxt->sizeElemInfos) { 24087 VERROR_INT("xmlSchemaGetFreshElemInfo", 24088 "inconsistent depth encountered"); 24089 return (NULL); 24090 } 24091 if (vctxt->elemInfos == NULL) { 24092 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *) 24093 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr)); 24094 if (vctxt->elemInfos == NULL) { 24095 xmlSchemaVErrMemory(vctxt, 24096 "allocating the element info array", NULL); 24097 return (NULL); 24098 } 24099 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr)); 24100 vctxt->sizeElemInfos = 10; 24101 } else if (vctxt->sizeElemInfos <= vctxt->depth) { 24102 int i = vctxt->sizeElemInfos; 24103 24104 vctxt->sizeElemInfos *= 2; 24105 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *) 24106 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos * 24107 sizeof(xmlSchemaNodeInfoPtr)); 24108 if (vctxt->elemInfos == NULL) { 24109 xmlSchemaVErrMemory(vctxt, 24110 "re-allocating the element info array", NULL); 24111 return (NULL); 24112 } 24113 /* 24114 * We need the new memory to be NULLed. 24115 * TODO: Use memset instead? 24116 */ 24117 for (; i < vctxt->sizeElemInfos; i++) 24118 vctxt->elemInfos[i] = NULL; 24119 } else 24120 info = vctxt->elemInfos[vctxt->depth]; 24121 24122 if (info == NULL) { 24123 info = (xmlSchemaNodeInfoPtr) 24124 xmlMalloc(sizeof(xmlSchemaNodeInfo)); 24125 if (info == NULL) { 24126 xmlSchemaVErrMemory(vctxt, 24127 "allocating an element info", NULL); 24128 return (NULL); 24129 } 24130 vctxt->elemInfos[vctxt->depth] = info; 24131 } else { 24132 if (info->localName != NULL) { 24133 VERROR_INT("xmlSchemaGetFreshElemInfo", 24134 "elem info has not been cleared"); 24135 return (NULL); 24136 } 24137 } 24138 memset(info, 0, sizeof(xmlSchemaNodeInfo)); 24139 info->nodeType = XML_ELEMENT_NODE; 24140 info->depth = vctxt->depth; 24141 24142 return (info); 24143} 24144 24145#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item; 24146#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth]; 24147#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1]; 24148 24149static int 24150xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt, 24151 xmlNodePtr node, 24152 xmlSchemaTypePtr type, 24153 xmlSchemaValType valType, 24154 const xmlChar * value, 24155 xmlSchemaValPtr val, 24156 unsigned long length, 24157 int fireErrors) 24158{ 24159 int ret, error = 0; 24160 24161 xmlSchemaTypePtr tmpType; 24162 xmlSchemaFacetLinkPtr facetLink; 24163 xmlSchemaFacetPtr facet; 24164 unsigned long len = 0; 24165 xmlSchemaWhitespaceValueType ws; 24166 24167 /* 24168 * In Libxml2, derived built-in types have currently no explicit facets. 24169 */ 24170 if (type->type == XML_SCHEMA_TYPE_BASIC) 24171 return (0); 24172 24173 /* 24174 * NOTE: Do not jump away, if the facetSet of the given type is 24175 * empty: until now, "pattern" and "enumeration" facets of the 24176 * *base types* need to be checked as well. 24177 */ 24178 if (type->facetSet == NULL) 24179 goto pattern_and_enum; 24180 24181 if (! WXS_IS_ATOMIC(type)) { 24182 if (WXS_IS_LIST(type)) 24183 goto WXS_IS_LIST; 24184 else 24185 goto pattern_and_enum; 24186 } 24187 /* 24188 * Whitespace handling is only of importance for string-based 24189 * types. 24190 */ 24191 tmpType = xmlSchemaGetPrimitiveType(type); 24192 if ((tmpType->builtInType == XML_SCHEMAS_STRING) || 24193 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) { 24194 ws = xmlSchemaGetWhiteSpaceFacetValue(type); 24195 } else 24196 ws = XML_SCHEMA_WHITESPACE_COLLAPSE; 24197 /* 24198 * If the value was not computed (for string or 24199 * anySimpleType based types), then use the provided 24200 * type. 24201 */ 24202 if (val == NULL) 24203 valType = valType; 24204 else 24205 valType = xmlSchemaGetValType(val); 24206 24207 ret = 0; 24208 for (facetLink = type->facetSet; facetLink != NULL; 24209 facetLink = facetLink->next) { 24210 /* 24211 * Skip the pattern "whiteSpace": it is used to 24212 * format the character content beforehand. 24213 */ 24214 switch (facetLink->facet->type) { 24215 case XML_SCHEMA_FACET_WHITESPACE: 24216 case XML_SCHEMA_FACET_PATTERN: 24217 case XML_SCHEMA_FACET_ENUMERATION: 24218 continue; 24219 case XML_SCHEMA_FACET_LENGTH: 24220 case XML_SCHEMA_FACET_MINLENGTH: 24221 case XML_SCHEMA_FACET_MAXLENGTH: 24222 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet, 24223 valType, value, val, &len, ws); 24224 break; 24225 default: 24226 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws, 24227 valType, value, val, ws); 24228 break; 24229 } 24230 if (ret < 0) { 24231 AERROR_INT("xmlSchemaValidateFacets", 24232 "validating against a atomic type facet"); 24233 return (-1); 24234 } else if (ret > 0) { 24235 if (fireErrors) 24236 xmlSchemaFacetErr(actxt, ret, node, 24237 value, len, type, facetLink->facet, NULL, NULL, NULL); 24238 else 24239 return (ret); 24240 if (error == 0) 24241 error = ret; 24242 } 24243 ret = 0; 24244 } 24245 24246WXS_IS_LIST: 24247 if (! WXS_IS_LIST(type)) 24248 goto pattern_and_enum; 24249 /* 24250 * "length", "minLength" and "maxLength" of list types. 24251 */ 24252 ret = 0; 24253 for (facetLink = type->facetSet; facetLink != NULL; 24254 facetLink = facetLink->next) { 24255 24256 switch (facetLink->facet->type) { 24257 case XML_SCHEMA_FACET_LENGTH: 24258 case XML_SCHEMA_FACET_MINLENGTH: 24259 case XML_SCHEMA_FACET_MAXLENGTH: 24260 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet, 24261 value, length, NULL); 24262 break; 24263 default: 24264 continue; 24265 } 24266 if (ret < 0) { 24267 AERROR_INT("xmlSchemaValidateFacets", 24268 "validating against a list type facet"); 24269 return (-1); 24270 } else if (ret > 0) { 24271 if (fireErrors) 24272 xmlSchemaFacetErr(actxt, ret, node, 24273 value, length, type, facetLink->facet, NULL, NULL, NULL); 24274 else 24275 return (ret); 24276 if (error == 0) 24277 error = ret; 24278 } 24279 ret = 0; 24280 } 24281 24282pattern_and_enum: 24283 if (error >= 0) { 24284 int found = 0; 24285 /* 24286 * Process enumerations. Facet values are in the value space 24287 * of the defining type's base type. This seems to be a bug in the 24288 * XML Schema 1.0 spec. Use the whitespace type of the base type. 24289 * Only the first set of enumerations in the ancestor-or-self axis 24290 * is used for validation. 24291 */ 24292 ret = 0; 24293 tmpType = type; 24294 do { 24295 for (facet = tmpType->facets; facet != NULL; facet = facet->next) { 24296 if (facet->type != XML_SCHEMA_FACET_ENUMERATION) 24297 continue; 24298 found = 1; 24299 ret = xmlSchemaAreValuesEqual(facet->val, val); 24300 if (ret == 1) 24301 break; 24302 else if (ret < 0) { 24303 AERROR_INT("xmlSchemaValidateFacets", 24304 "validating against an enumeration facet"); 24305 return (-1); 24306 } 24307 } 24308 if (ret != 0) 24309 break; 24310 /* 24311 * Break on the first set of enumerations. Any additional 24312 * enumerations which might be existent on the ancestors 24313 * of the current type are restricted by this set; thus 24314 * *must* *not* be taken into account. 24315 */ 24316 if (found) 24317 break; 24318 tmpType = tmpType->baseType; 24319 } while ((tmpType != NULL) && 24320 (tmpType->type != XML_SCHEMA_TYPE_BASIC)); 24321 if (found && (ret == 0)) { 24322 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID; 24323 if (fireErrors) { 24324 xmlSchemaFacetErr(actxt, ret, node, 24325 value, 0, type, NULL, NULL, NULL, NULL); 24326 } else 24327 return (ret); 24328 if (error == 0) 24329 error = ret; 24330 } 24331 } 24332 24333 if (error >= 0) { 24334 int found; 24335 /* 24336 * Process patters. Pattern facets are ORed at type level 24337 * and ANDed if derived. Walk the base type axis. 24338 */ 24339 tmpType = type; 24340 facet = NULL; 24341 do { 24342 found = 0; 24343 for (facetLink = tmpType->facetSet; facetLink != NULL; 24344 facetLink = facetLink->next) { 24345 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN) 24346 continue; 24347 found = 1; 24348 /* 24349 * NOTE that for patterns, @value needs to be the 24350 * normalized vaule. 24351 */ 24352 ret = xmlRegexpExec(facetLink->facet->regexp, value); 24353 if (ret == 1) 24354 break; 24355 else if (ret < 0) { 24356 AERROR_INT("xmlSchemaValidateFacets", 24357 "validating against a pattern facet"); 24358 return (-1); 24359 } else { 24360 /* 24361 * Save the last non-validating facet. 24362 */ 24363 facet = facetLink->facet; 24364 } 24365 } 24366 if (found && (ret != 1)) { 24367 ret = XML_SCHEMAV_CVC_PATTERN_VALID; 24368 if (fireErrors) { 24369 xmlSchemaFacetErr(actxt, ret, node, 24370 value, 0, type, facet, NULL, NULL, NULL); 24371 } else 24372 return (ret); 24373 if (error == 0) 24374 error = ret; 24375 break; 24376 } 24377 tmpType = tmpType->baseType; 24378 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC)); 24379 } 24380 24381 return (error); 24382} 24383 24384static xmlChar * 24385xmlSchemaNormalizeValue(xmlSchemaTypePtr type, 24386 const xmlChar *value) 24387{ 24388 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) { 24389 case XML_SCHEMA_WHITESPACE_COLLAPSE: 24390 return (xmlSchemaCollapseString(value)); 24391 case XML_SCHEMA_WHITESPACE_REPLACE: 24392 return (xmlSchemaWhiteSpaceReplace(value)); 24393 default: 24394 return (NULL); 24395 } 24396} 24397 24398static int 24399xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt, 24400 const xmlChar *value, 24401 xmlSchemaValPtr *val, 24402 int valNeeded) 24403{ 24404 int ret; 24405 const xmlChar *nsName; 24406 xmlChar *local, *prefix = NULL; 24407 24408 ret = xmlValidateQName(value, 1); 24409 if (ret != 0) { 24410 if (ret == -1) { 24411 VERROR_INT("xmlSchemaValidateQName", 24412 "calling xmlValidateQName()"); 24413 return (-1); 24414 } 24415 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1); 24416 } 24417 /* 24418 * NOTE: xmlSplitQName2 will always return a duplicated 24419 * strings. 24420 */ 24421 local = xmlSplitQName2(value, &prefix); 24422 if (local == NULL) 24423 local = xmlStrdup(value); 24424 /* 24425 * OPTIMIZE TODO: Use flags for: 24426 * - is there any namespace binding? 24427 * - is there a default namespace? 24428 */ 24429 nsName = xmlSchemaLookupNamespace(vctxt, prefix); 24430 24431 if (prefix != NULL) { 24432 xmlFree(prefix); 24433 /* 24434 * A namespace must be found if the prefix is 24435 * NOT NULL. 24436 */ 24437 if (nsName == NULL) { 24438 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; 24439 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL, 24440 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 24441 "The QName value '%s' has no " 24442 "corresponding namespace declaration in " 24443 "scope", value, NULL); 24444 if (local != NULL) 24445 xmlFree(local); 24446 return (ret); 24447 } 24448 } 24449 if (valNeeded && val) { 24450 if (nsName != NULL) 24451 *val = xmlSchemaNewQNameValue( 24452 BAD_CAST xmlStrdup(nsName), BAD_CAST local); 24453 else 24454 *val = xmlSchemaNewQNameValue(NULL, 24455 BAD_CAST local); 24456 } else 24457 xmlFree(local); 24458 return (0); 24459} 24460 24461/* 24462* cvc-simple-type 24463*/ 24464static int 24465xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt, 24466 xmlNodePtr node, 24467 xmlSchemaTypePtr type, 24468 const xmlChar *value, 24469 xmlSchemaValPtr *retVal, 24470 int fireErrors, 24471 int normalize, 24472 int isNormalized) 24473{ 24474 int ret = 0, valNeeded = (retVal) ? 1 : 0; 24475 xmlSchemaValPtr val = NULL; 24476 /* xmlSchemaWhitespaceValueType ws; */ 24477 xmlChar *normValue = NULL; 24478 24479#define NORMALIZE(atype) \ 24480 if ((! isNormalized) && \ 24481 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \ 24482 normValue = xmlSchemaNormalizeValue(atype, value); \ 24483 if (normValue != NULL) \ 24484 value = normValue; \ 24485 isNormalized = 1; \ 24486 } 24487 24488 if ((retVal != NULL) && (*retVal != NULL)) { 24489 xmlSchemaFreeValue(*retVal); 24490 *retVal = NULL; 24491 } 24492 /* 24493 * 3.14.4 Simple Type Definition Validation Rules 24494 * Validation Rule: String Valid 24495 */ 24496 /* 24497 * 1 It is schema-valid with respect to that definition as defined 24498 * by Datatype Valid in [XML Schemas: Datatypes]. 24499 */ 24500 /* 24501 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given 24502 * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then 24503 * the string must be a �declared entity name�. 24504 */ 24505 /* 24506 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES 24507 * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), 24508 * then every whitespace-delimited substring of the string must be a �declared 24509 * entity name�. 24510 */ 24511 /* 24512 * 2.3 otherwise no further condition applies. 24513 */ 24514 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)) 24515 valNeeded = 1; 24516 if (value == NULL) 24517 value = BAD_CAST ""; 24518 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) { 24519 xmlSchemaTypePtr biType; /* The built-in type. */ 24520 /* 24521 * SPEC (1.2.1) "if {variety} is �atomic� then the string must �match� 24522 * a literal in the �lexical space� of {base type definition}" 24523 */ 24524 /* 24525 * Whitespace-normalize. 24526 */ 24527 NORMALIZE(type); 24528 if (type->type != XML_SCHEMA_TYPE_BASIC) { 24529 /* 24530 * Get the built-in type. 24531 */ 24532 biType = type->baseType; 24533 while ((biType != NULL) && 24534 (biType->type != XML_SCHEMA_TYPE_BASIC)) 24535 biType = biType->baseType; 24536 24537 if (biType == NULL) { 24538 AERROR_INT("xmlSchemaVCheckCVCSimpleType", 24539 "could not get the built-in type"); 24540 goto internal_error; 24541 } 24542 } else 24543 biType = type; 24544 /* 24545 * NOTATIONs need to be processed here, since they need 24546 * to lookup in the hashtable of NOTATION declarations of the schema. 24547 */ 24548 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) { 24549 switch (biType->builtInType) { 24550 case XML_SCHEMAS_NOTATION: 24551 ret = xmlSchemaValidateNotation( 24552 (xmlSchemaValidCtxtPtr) actxt, 24553 ((xmlSchemaValidCtxtPtr) actxt)->schema, 24554 NULL, value, &val, valNeeded); 24555 break; 24556 case XML_SCHEMAS_QNAME: 24557 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt, 24558 value, &val, valNeeded); 24559 break; 24560 default: 24561 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */ 24562 if (valNeeded) 24563 ret = xmlSchemaValPredefTypeNodeNoNorm(biType, 24564 value, &val, node); 24565 else 24566 ret = xmlSchemaValPredefTypeNodeNoNorm(biType, 24567 value, NULL, node); 24568 break; 24569 } 24570 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) { 24571 switch (biType->builtInType) { 24572 case XML_SCHEMAS_NOTATION: 24573 ret = xmlSchemaValidateNotation(NULL, 24574 ((xmlSchemaParserCtxtPtr) actxt)->schema, node, 24575 value, &val, valNeeded); 24576 break; 24577 default: 24578 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */ 24579 if (valNeeded) 24580 ret = xmlSchemaValPredefTypeNodeNoNorm(biType, 24581 value, &val, node); 24582 else 24583 ret = xmlSchemaValPredefTypeNodeNoNorm(biType, 24584 value, NULL, node); 24585 break; 24586 } 24587 } else { 24588 /* 24589 * Validation via a public API is not implemented yet. 24590 */ 24591 TODO 24592 goto internal_error; 24593 } 24594 if (ret != 0) { 24595 if (ret < 0) { 24596 AERROR_INT("xmlSchemaVCheckCVCSimpleType", 24597 "validating against a built-in type"); 24598 goto internal_error; 24599 } 24600 if (WXS_IS_LIST(type)) 24601 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; 24602 else 24603 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; 24604 } 24605 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) { 24606 /* 24607 * Check facets. 24608 */ 24609 ret = xmlSchemaValidateFacets(actxt, node, type, 24610 (xmlSchemaValType) biType->builtInType, value, val, 24611 0, fireErrors); 24612 if (ret != 0) { 24613 if (ret < 0) { 24614 AERROR_INT("xmlSchemaVCheckCVCSimpleType", 24615 "validating facets of atomic simple type"); 24616 goto internal_error; 24617 } 24618 if (WXS_IS_LIST(type)) 24619 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; 24620 else 24621 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; 24622 } 24623 } 24624 if (fireErrors && (ret > 0)) 24625 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1); 24626 } else if (WXS_IS_LIST(type)) { 24627 24628 xmlSchemaTypePtr itemType; 24629 const xmlChar *cur, *end; 24630 xmlChar *tmpValue = NULL; 24631 unsigned long len = 0; 24632 xmlSchemaValPtr prevVal = NULL, curVal = NULL; 24633 /* 1.2.2 if {variety} is �list� then the string must be a sequence 24634 * of white space separated tokens, each of which �match�es a literal 24635 * in the �lexical space� of {item type definition} 24636 */ 24637 /* 24638 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if 24639 * the list type has an enum or pattern facet. 24640 */ 24641 NORMALIZE(type); 24642 /* 24643 * VAL TODO: Optimize validation of empty values. 24644 * VAL TODO: We do not have computed values for lists. 24645 */ 24646 itemType = WXS_LIST_ITEMTYPE(type); 24647 cur = value; 24648 do { 24649 while (IS_BLANK_CH(*cur)) 24650 cur++; 24651 end = cur; 24652 while ((*end != 0) && (!(IS_BLANK_CH(*end)))) 24653 end++; 24654 if (end == cur) 24655 break; 24656 tmpValue = xmlStrndup(cur, end - cur); 24657 len++; 24658 24659 if (valNeeded) 24660 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType, 24661 tmpValue, &curVal, fireErrors, 0, 1); 24662 else 24663 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType, 24664 tmpValue, NULL, fireErrors, 0, 1); 24665 FREE_AND_NULL(tmpValue); 24666 if (curVal != NULL) { 24667 /* 24668 * Add to list of computed values. 24669 */ 24670 if (val == NULL) 24671 val = curVal; 24672 else 24673 xmlSchemaValueAppend(prevVal, curVal); 24674 prevVal = curVal; 24675 curVal = NULL; 24676 } 24677 if (ret != 0) { 24678 if (ret < 0) { 24679 AERROR_INT("xmlSchemaVCheckCVCSimpleType", 24680 "validating an item of list simple type"); 24681 goto internal_error; 24682 } 24683 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; 24684 break; 24685 } 24686 cur = end; 24687 } while (*cur != 0); 24688 FREE_AND_NULL(tmpValue); 24689 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) { 24690 /* 24691 * Apply facets (pattern, enumeration). 24692 */ 24693 ret = xmlSchemaValidateFacets(actxt, node, type, 24694 XML_SCHEMAS_UNKNOWN, value, val, 24695 len, fireErrors); 24696 if (ret != 0) { 24697 if (ret < 0) { 24698 AERROR_INT("xmlSchemaVCheckCVCSimpleType", 24699 "validating facets of list simple type"); 24700 goto internal_error; 24701 } 24702 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; 24703 } 24704 } 24705 if (fireErrors && (ret > 0)) { 24706 /* 24707 * Report the normalized value. 24708 */ 24709 normalize = 1; 24710 NORMALIZE(type); 24711 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1); 24712 } 24713 } else if (WXS_IS_UNION(type)) { 24714 xmlSchemaTypeLinkPtr memberLink; 24715 /* 24716 * TODO: For all datatypes �derived� by �union� whiteSpace does 24717 * not apply directly; however, the normalization behavior of �union� 24718 * types is controlled by the value of whiteSpace on that one of the 24719 * �memberTypes� against which the �union� is successfully validated. 24720 * 24721 * This means that the value is normalized by the first validating 24722 * member type, then the facets of the union type are applied. This 24723 * needs changing of the value! 24724 */ 24725 24726 /* 24727 * 1.2.3 if {variety} is �union� then the string must �match� a 24728 * literal in the �lexical space� of at least one member of 24729 * {member type definitions} 24730 */ 24731 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type); 24732 if (memberLink == NULL) { 24733 AERROR_INT("xmlSchemaVCheckCVCSimpleType", 24734 "union simple type has no member types"); 24735 goto internal_error; 24736 } 24737 /* 24738 * Always normalize union type values, since we currently 24739 * cannot store the whitespace information with the value 24740 * itself; otherwise a later value-comparison would be 24741 * not possible. 24742 */ 24743 while (memberLink != NULL) { 24744 if (valNeeded) 24745 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, 24746 memberLink->type, value, &val, 0, 1, 0); 24747 else 24748 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, 24749 memberLink->type, value, NULL, 0, 1, 0); 24750 if (ret <= 0) 24751 break; 24752 memberLink = memberLink->next; 24753 } 24754 if (ret != 0) { 24755 if (ret < 0) { 24756 AERROR_INT("xmlSchemaVCheckCVCSimpleType", 24757 "validating members of union simple type"); 24758 goto internal_error; 24759 } 24760 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3; 24761 } 24762 /* 24763 * Apply facets (pattern, enumeration). 24764 */ 24765 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) { 24766 /* 24767 * The normalization behavior of �union� types is controlled by 24768 * the value of whiteSpace on that one of the �memberTypes� 24769 * against which the �union� is successfully validated. 24770 */ 24771 NORMALIZE(memberLink->type); 24772 ret = xmlSchemaValidateFacets(actxt, node, type, 24773 XML_SCHEMAS_UNKNOWN, value, val, 24774 0, fireErrors); 24775 if (ret != 0) { 24776 if (ret < 0) { 24777 AERROR_INT("xmlSchemaVCheckCVCSimpleType", 24778 "validating facets of union simple type"); 24779 goto internal_error; 24780 } 24781 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3; 24782 } 24783 } 24784 if (fireErrors && (ret > 0)) 24785 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1); 24786 } 24787 24788 if (normValue != NULL) 24789 xmlFree(normValue); 24790 if (ret == 0) { 24791 if (retVal != NULL) 24792 *retVal = val; 24793 else if (val != NULL) 24794 xmlSchemaFreeValue(val); 24795 } else if (val != NULL) 24796 xmlSchemaFreeValue(val); 24797 return (ret); 24798internal_error: 24799 if (normValue != NULL) 24800 xmlFree(normValue); 24801 if (val != NULL) 24802 xmlSchemaFreeValue(val); 24803 return (-1); 24804} 24805 24806static int 24807xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt, 24808 const xmlChar *value, 24809 const xmlChar **nsName, 24810 const xmlChar **localName) 24811{ 24812 int ret = 0; 24813 24814 if ((nsName == NULL) || (localName == NULL)) 24815 return (-1); 24816 *nsName = NULL; 24817 *localName = NULL; 24818 24819 ret = xmlValidateQName(value, 1); 24820 if (ret == -1) 24821 return (-1); 24822 if (ret > 0) { 24823 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt, 24824 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL, 24825 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1); 24826 return (1); 24827 } 24828 { 24829 xmlChar *local = NULL; 24830 xmlChar *prefix; 24831 24832 /* 24833 * NOTE: xmlSplitQName2 will return a duplicated 24834 * string. 24835 */ 24836 local = xmlSplitQName2(value, &prefix); 24837 if (local == NULL) 24838 *localName = xmlDictLookup(vctxt->dict, value, -1); 24839 else { 24840 *localName = xmlDictLookup(vctxt->dict, local, -1); 24841 xmlFree(local); 24842 } 24843 24844 *nsName = xmlSchemaLookupNamespace(vctxt, prefix); 24845 24846 if (prefix != NULL) { 24847 xmlFree(prefix); 24848 /* 24849 * A namespace must be found if the prefix is NOT NULL. 24850 */ 24851 if (*nsName == NULL) { 24852 xmlSchemaCustomErr(ACTXT_CAST vctxt, 24853 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL, 24854 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 24855 "The QName value '%s' has no " 24856 "corresponding namespace declaration in scope", 24857 value, NULL); 24858 return (2); 24859 } 24860 } 24861 } 24862 return (0); 24863} 24864 24865static int 24866xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt, 24867 xmlSchemaAttrInfoPtr iattr, 24868 xmlSchemaTypePtr *localType, 24869 xmlSchemaElementPtr elemDecl) 24870{ 24871 int ret = 0; 24872 /* 24873 * cvc-elt (3.3.4) : (4) 24874 * AND 24875 * Schema-Validity Assessment (Element) (cvc-assess-elt) 24876 * (1.2.1.2.1) - (1.2.1.2.4) 24877 * Handle 'xsi:type'. 24878 */ 24879 if (localType == NULL) 24880 return (-1); 24881 *localType = NULL; 24882 if (iattr == NULL) 24883 return (0); 24884 else { 24885 const xmlChar *nsName = NULL, *local = NULL; 24886 /* 24887 * TODO: We should report a *warning* that the type was overriden 24888 * by the instance. 24889 */ 24890 ACTIVATE_ATTRIBUTE(iattr); 24891 /* 24892 * (cvc-elt) (3.3.4) : (4.1) 24893 * (cvc-assess-elt) (1.2.1.2.2) 24894 */ 24895 ret = xmlSchemaVExpandQName(vctxt, iattr->value, 24896 &nsName, &local); 24897 if (ret != 0) { 24898 if (ret < 0) { 24899 VERROR_INT("xmlSchemaValidateElementByDeclaration", 24900 "calling xmlSchemaQNameExpand() to validate the " 24901 "attribute 'xsi:type'"); 24902 goto internal_error; 24903 } 24904 goto exit; 24905 } 24906 /* 24907 * (cvc-elt) (3.3.4) : (4.2) 24908 * (cvc-assess-elt) (1.2.1.2.3) 24909 */ 24910 *localType = xmlSchemaGetType(vctxt->schema, local, nsName); 24911 if (*localType == NULL) { 24912 xmlChar *str = NULL; 24913 24914 xmlSchemaCustomErr(ACTXT_CAST vctxt, 24915 XML_SCHEMAV_CVC_ELT_4_2, NULL, 24916 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 24917 "The QName value '%s' of the xsi:type attribute does not " 24918 "resolve to a type definition", 24919 xmlSchemaFormatQName(&str, nsName, local), NULL); 24920 FREE_AND_NULL(str); 24921 ret = vctxt->err; 24922 goto exit; 24923 } 24924 if (elemDecl != NULL) { 24925 int set = 0; 24926 24927 /* 24928 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK) 24929 * "The �local type definition� must be validly 24930 * derived from the {type definition} given the union of 24931 * the {disallowed substitutions} and the {type definition}'s 24932 * {prohibited substitutions}, as defined in 24933 * Type Derivation OK (Complex) (�3.4.6) 24934 * (if it is a complex type definition), 24935 * or given {disallowed substitutions} as defined in Type 24936 * Derivation OK (Simple) (�3.14.6) (if it is a simple type 24937 * definition)." 24938 * 24939 * {disallowed substitutions}: the "block" on the element decl. 24940 * {prohibited substitutions}: the "block" on the type def. 24941 */ 24942 /* 24943 * OPTIMIZE TODO: We could map types already evaluated 24944 * to be validly derived from other types to avoid checking 24945 * this over and over for the same types. 24946 */ 24947 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) || 24948 (elemDecl->subtypes->flags & 24949 XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) 24950 set |= SUBSET_EXTENSION; 24951 24952 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) || 24953 (elemDecl->subtypes->flags & 24954 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)) 24955 set |= SUBSET_RESTRICTION; 24956 24957 /* 24958 * REMOVED and CHANGED since this produced a parser context 24959 * which adds to the string dict of the schema. So this would 24960 * change the schema and we don't want this. We don't need 24961 * the parser context anymore. 24962 * 24963 * if ((vctxt->pctxt == NULL) && 24964 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) 24965 * return (-1); 24966 */ 24967 24968 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType, 24969 elemDecl->subtypes, set) != 0) { 24970 xmlChar *str = NULL; 24971 24972 xmlSchemaCustomErr(ACTXT_CAST vctxt, 24973 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL, 24974 "The type definition '%s', specified by xsi:type, is " 24975 "blocked or not validly derived from the type definition " 24976 "of the element declaration", 24977 xmlSchemaFormatQName(&str, 24978 (*localType)->targetNamespace, 24979 (*localType)->name), 24980 NULL); 24981 FREE_AND_NULL(str); 24982 ret = vctxt->err; 24983 *localType = NULL; 24984 } 24985 } 24986 } 24987exit: 24988 ACTIVATE_ELEM; 24989 return (ret); 24990internal_error: 24991 ACTIVATE_ELEM; 24992 return (-1); 24993} 24994 24995static int 24996xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt) 24997{ 24998 xmlSchemaElementPtr elemDecl = vctxt->inode->decl; 24999 xmlSchemaTypePtr actualType; 25000 25001 /* 25002 * cvc-elt (3.3.4) : 1 25003 */ 25004 if (elemDecl == NULL) { 25005 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, 25006 "No matching declaration available"); 25007 return (vctxt->err); 25008 } 25009 actualType = WXS_ELEM_TYPEDEF(elemDecl); 25010 /* 25011 * cvc-elt (3.3.4) : 2 25012 */ 25013 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) { 25014 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL, 25015 "The element declaration is abstract"); 25016 return (vctxt->err); 25017 } 25018 if (actualType == NULL) { 25019 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL, 25020 "The type definition is absent"); 25021 return (XML_SCHEMAV_CVC_TYPE_1); 25022 } 25023 if (vctxt->nbAttrInfos != 0) { 25024 int ret; 25025 xmlSchemaAttrInfoPtr iattr; 25026 /* 25027 * cvc-elt (3.3.4) : 3 25028 * Handle 'xsi:nil'. 25029 */ 25030 iattr = xmlSchemaGetMetaAttrInfo(vctxt, 25031 XML_SCHEMA_ATTR_INFO_META_XSI_NIL); 25032 if (iattr) { 25033 ACTIVATE_ATTRIBUTE(iattr); 25034 /* 25035 * Validate the value. 25036 */ 25037 ret = xmlSchemaVCheckCVCSimpleType( 25038 ACTXT_CAST vctxt, NULL, 25039 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN), 25040 iattr->value, &(iattr->val), 1, 0, 0); 25041 ACTIVATE_ELEM; 25042 if (ret < 0) { 25043 VERROR_INT("xmlSchemaValidateElemDecl", 25044 "calling xmlSchemaVCheckCVCSimpleType() to " 25045 "validate the attribute 'xsi:nil'"); 25046 return (-1); 25047 } 25048 if (ret == 0) { 25049 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) { 25050 /* 25051 * cvc-elt (3.3.4) : 3.1 25052 */ 25053 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL, 25054 "The element is not 'nillable'"); 25055 /* Does not return an error on purpose. */ 25056 } else { 25057 if (xmlSchemaValueGetAsBoolean(iattr->val)) { 25058 /* 25059 * cvc-elt (3.3.4) : 3.2.2 25060 */ 25061 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && 25062 (elemDecl->value != NULL)) { 25063 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL, 25064 "The element cannot be 'nilled' because " 25065 "there is a fixed value constraint defined " 25066 "for it"); 25067 /* Does not return an error on purpose. */ 25068 } else 25069 vctxt->inode->flags |= 25070 XML_SCHEMA_ELEM_INFO_NILLED; 25071 } 25072 } 25073 } 25074 } 25075 /* 25076 * cvc-elt (3.3.4) : 4 25077 * Handle 'xsi:type'. 25078 */ 25079 iattr = xmlSchemaGetMetaAttrInfo(vctxt, 25080 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE); 25081 if (iattr) { 25082 xmlSchemaTypePtr localType = NULL; 25083 25084 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType, 25085 elemDecl); 25086 if (ret != 0) { 25087 if (ret == -1) { 25088 VERROR_INT("xmlSchemaValidateElemDecl", 25089 "calling xmlSchemaProcessXSIType() to " 25090 "process the attribute 'xsi:type'"); 25091 return (-1); 25092 } 25093 /* Does not return an error on purpose. */ 25094 } 25095 if (localType != NULL) { 25096 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE; 25097 actualType = localType; 25098 } 25099 } 25100 } 25101 /* 25102 * IDC: Register identity-constraint XPath matchers. 25103 */ 25104 if ((elemDecl->idcs != NULL) && 25105 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1)) 25106 return (-1); 25107 /* 25108 * No actual type definition. 25109 */ 25110 if (actualType == NULL) { 25111 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL, 25112 "The type definition is absent"); 25113 return (XML_SCHEMAV_CVC_TYPE_1); 25114 } 25115 /* 25116 * Remember the actual type definition. 25117 */ 25118 vctxt->inode->typeDef = actualType; 25119 25120 return (0); 25121} 25122 25123static int 25124xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt) 25125{ 25126 xmlSchemaAttrInfoPtr iattr; 25127 int ret = 0, i; 25128 25129 /* 25130 * SPEC cvc-type (3.1.1) 25131 * "The attributes of must be empty, excepting those whose namespace 25132 * name is identical to http://www.w3.org/2001/XMLSchema-instance and 25133 * whose local name is one of type, nil, schemaLocation or 25134 * noNamespaceSchemaLocation." 25135 */ 25136 if (vctxt->nbAttrInfos == 0) 25137 return (0); 25138 for (i = 0; i < vctxt->nbAttrInfos; i++) { 25139 iattr = vctxt->attrInfos[i]; 25140 if (! iattr->metaType) { 25141 ACTIVATE_ATTRIBUTE(iattr) 25142 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt, 25143 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL); 25144 ret = XML_SCHEMAV_CVC_TYPE_3_1_1; 25145 } 25146 } 25147 ACTIVATE_ELEM 25148 return (ret); 25149} 25150 25151/* 25152* Cleanup currently used attribute infos. 25153*/ 25154static void 25155xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt) 25156{ 25157 int i; 25158 xmlSchemaAttrInfoPtr attr; 25159 25160 if (vctxt->nbAttrInfos == 0) 25161 return; 25162 for (i = 0; i < vctxt->nbAttrInfos; i++) { 25163 attr = vctxt->attrInfos[i]; 25164 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) { 25165 if (attr->localName != NULL) 25166 xmlFree((xmlChar *) attr->localName); 25167 if (attr->nsName != NULL) 25168 xmlFree((xmlChar *) attr->nsName); 25169 } 25170 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) { 25171 if (attr->value != NULL) 25172 xmlFree((xmlChar *) attr->value); 25173 } 25174 if (attr->val != NULL) { 25175 xmlSchemaFreeValue(attr->val); 25176 attr->val = NULL; 25177 } 25178 memset(attr, 0, sizeof(xmlSchemaAttrInfo)); 25179 } 25180 vctxt->nbAttrInfos = 0; 25181} 25182 25183/* 25184* 3.4.4 Complex Type Definition Validation Rules 25185* Element Locally Valid (Complex Type) (cvc-complex-type) 25186* 3.2.4 Attribute Declaration Validation Rules 25187* Validation Rule: Attribute Locally Valid (cvc-attribute) 25188* Attribute Locally Valid (Use) (cvc-au) 25189* 25190* Only "assessed" attribute information items will be visible to 25191* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes. 25192*/ 25193static int 25194xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt) 25195{ 25196 xmlSchemaTypePtr type = vctxt->inode->typeDef; 25197 xmlSchemaItemListPtr attrUseList; 25198 xmlSchemaAttributeUsePtr attrUse = NULL; 25199 xmlSchemaAttributePtr attrDecl = NULL; 25200 xmlSchemaAttrInfoPtr iattr, tmpiattr; 25201 int i, j, found, nbAttrs, nbUses; 25202 int xpathRes = 0, res, wildIDs = 0, fixed; 25203 xmlNodePtr defAttrOwnerElem = NULL; 25204 25205 /* 25206 * SPEC (cvc-attribute) 25207 * (1) "The declaration must not be �absent� (see Missing 25208 * Sub-components (�5.3) for how this can fail to be 25209 * the case)." 25210 * (2) "Its {type definition} must not be absent." 25211 * 25212 * NOTE (1) + (2): This is not handled here, since we currently do not 25213 * allow validation against schemas which have missing sub-components. 25214 * 25215 * SPEC (cvc-complex-type) 25216 * (3) "For each attribute information item in the element information 25217 * item's [attributes] excepting those whose [namespace name] is 25218 * identical to http://www.w3.org/2001/XMLSchema-instance and whose 25219 * [local name] is one of type, nil, schemaLocation or 25220 * noNamespaceSchemaLocation, the appropriate case among the following 25221 * must be true: 25222 * 25223 */ 25224 attrUseList = (xmlSchemaItemListPtr) type->attrUses; 25225 /* 25226 * @nbAttrs is the number of attributes present in the instance. 25227 */ 25228 nbAttrs = vctxt->nbAttrInfos; 25229 if (attrUseList != NULL) 25230 nbUses = attrUseList->nbItems; 25231 else 25232 nbUses = 0; 25233 for (i = 0; i < nbUses; i++) { 25234 found = 0; 25235 attrUse = attrUseList->items[i]; 25236 attrDecl = WXS_ATTRUSE_DECL(attrUse); 25237 for (j = 0; j < nbAttrs; j++) { 25238 iattr = vctxt->attrInfos[j]; 25239 /* 25240 * SPEC (cvc-complex-type) (3) 25241 * Skip meta attributes. 25242 */ 25243 if (iattr->metaType) 25244 continue; 25245 if (iattr->localName[0] != attrDecl->name[0]) 25246 continue; 25247 if (!xmlStrEqual(iattr->localName, attrDecl->name)) 25248 continue; 25249 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace)) 25250 continue; 25251 found = 1; 25252 /* 25253 * SPEC (cvc-complex-type) 25254 * (3.1) "If there is among the {attribute uses} an attribute 25255 * use with an {attribute declaration} whose {name} matches 25256 * the attribute information item's [local name] and whose 25257 * {target namespace} is identical to the attribute information 25258 * item's [namespace name] (where an �absent� {target namespace} 25259 * is taken to be identical to a [namespace name] with no value), 25260 * then the attribute information must be �valid� with respect 25261 * to that attribute use as per Attribute Locally Valid (Use) 25262 * (�3.5.4). In this case the {attribute declaration} of that 25263 * attribute use is the �context-determined declaration� for the 25264 * attribute information item with respect to Schema-Validity 25265 * Assessment (Attribute) (�3.2.4) and 25266 * Assessment Outcome (Attribute) (�3.2.5). 25267 */ 25268 iattr->state = XML_SCHEMAS_ATTR_ASSESSED; 25269 iattr->use = attrUse; 25270 /* 25271 * Context-determined declaration. 25272 */ 25273 iattr->decl = attrDecl; 25274 iattr->typeDef = attrDecl->subtypes; 25275 break; 25276 } 25277 25278 if (found) 25279 continue; 25280 25281 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) { 25282 /* 25283 * Handle non-existent, required attributes. 25284 * 25285 * SPEC (cvc-complex-type) 25286 * (4) "The {attribute declaration} of each attribute use in 25287 * the {attribute uses} whose {required} is true matches one 25288 * of the attribute information items in the element information 25289 * item's [attributes] as per clause 3.1 above." 25290 */ 25291 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt); 25292 if (tmpiattr == NULL) { 25293 VERROR_INT( 25294 "xmlSchemaVAttributesComplex", 25295 "calling xmlSchemaGetFreshAttrInfo()"); 25296 return (-1); 25297 } 25298 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING; 25299 tmpiattr->use = attrUse; 25300 tmpiattr->decl = attrDecl; 25301 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) && 25302 ((attrUse->defValue != NULL) || 25303 (attrDecl->defValue != NULL))) { 25304 /* 25305 * Handle non-existent, optional, default/fixed attributes. 25306 */ 25307 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt); 25308 if (tmpiattr == NULL) { 25309 VERROR_INT( 25310 "xmlSchemaVAttributesComplex", 25311 "calling xmlSchemaGetFreshAttrInfo()"); 25312 return (-1); 25313 } 25314 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT; 25315 tmpiattr->use = attrUse; 25316 tmpiattr->decl = attrDecl; 25317 tmpiattr->typeDef = attrDecl->subtypes; 25318 tmpiattr->localName = attrDecl->name; 25319 tmpiattr->nsName = attrDecl->targetNamespace; 25320 } 25321 } 25322 25323 if (vctxt->nbAttrInfos == 0) 25324 return (0); 25325 /* 25326 * Validate against the wildcard. 25327 */ 25328 if (type->attributeWildcard != NULL) { 25329 /* 25330 * SPEC (cvc-complex-type) 25331 * (3.2.1) "There must be an {attribute wildcard}." 25332 */ 25333 for (i = 0; i < nbAttrs; i++) { 25334 iattr = vctxt->attrInfos[i]; 25335 /* 25336 * SPEC (cvc-complex-type) (3) 25337 * Skip meta attributes. 25338 */ 25339 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN) 25340 continue; 25341 /* 25342 * SPEC (cvc-complex-type) 25343 * (3.2.2) "The attribute information item must be �valid� with 25344 * respect to it as defined in Item Valid (Wildcard) (�3.10.4)." 25345 * 25346 * SPEC Item Valid (Wildcard) (cvc-wildcard) 25347 * "... its [namespace name] must be �valid� with respect to 25348 * the wildcard constraint, as defined in Wildcard allows 25349 * Namespace Name (�3.10.4)." 25350 */ 25351 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard, 25352 iattr->nsName) == 0) { 25353 /* 25354 * Handle processContents. 25355 * 25356 * SPEC (cvc-wildcard): 25357 * processContents | context-determined declaration: 25358 * "strict" "mustFind" 25359 * "lax" "none" 25360 * "skip" "skip" 25361 */ 25362 if (type->attributeWildcard->processContents == 25363 XML_SCHEMAS_ANY_SKIP) { 25364 /* 25365 * context-determined declaration = "skip" 25366 * 25367 * SPEC PSVI Assessment Outcome (Attribute) 25368 * [validity] = "notKnown" 25369 * [validation attempted] = "none" 25370 */ 25371 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP; 25372 continue; 25373 } 25374 /* 25375 * Find an attribute declaration. 25376 */ 25377 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema, 25378 iattr->localName, iattr->nsName); 25379 if (iattr->decl != NULL) { 25380 iattr->state = XML_SCHEMAS_ATTR_ASSESSED; 25381 /* 25382 * SPEC (cvc-complex-type) 25383 * (5) "Let [Definition:] the wild IDs be the set of 25384 * all attribute information item to which clause 3.2 25385 * applied and whose �validation� resulted in a 25386 * �context-determined declaration� of mustFind or no 25387 * �context-determined declaration� at all, and whose 25388 * [local name] and [namespace name] resolve (as 25389 * defined by QName resolution (Instance) (�3.15.4)) to 25390 * an attribute declaration whose {type definition} is 25391 * or is derived from ID. Then all of the following 25392 * must be true:" 25393 */ 25394 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl); 25395 if (xmlSchemaIsDerivedFromBuiltInType( 25396 iattr->typeDef, XML_SCHEMAS_ID)) { 25397 /* 25398 * SPEC (5.1) "There must be no more than one 25399 * item in �wild IDs�." 25400 */ 25401 if (wildIDs != 0) { 25402 /* VAL TODO */ 25403 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID; 25404 TODO 25405 continue; 25406 } 25407 wildIDs++; 25408 /* 25409 * SPEC (cvc-complex-type) 25410 * (5.2) "If �wild IDs� is non-empty, there must not 25411 * be any attribute uses among the {attribute uses} 25412 * whose {attribute declaration}'s {type definition} 25413 * is or is derived from ID." 25414 */ 25415 if (attrUseList != NULL) { 25416 for (j = 0; j < attrUseList->nbItems; j++) { 25417 if (xmlSchemaIsDerivedFromBuiltInType( 25418 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]), 25419 XML_SCHEMAS_ID)) { 25420 /* URGENT VAL TODO: implement */ 25421 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID; 25422 TODO 25423 break; 25424 } 25425 } 25426 } 25427 } 25428 } else if (type->attributeWildcard->processContents == 25429 XML_SCHEMAS_ANY_LAX) { 25430 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL; 25431 /* 25432 * SPEC PSVI Assessment Outcome (Attribute) 25433 * [validity] = "notKnown" 25434 * [validation attempted] = "none" 25435 */ 25436 } else { 25437 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL; 25438 } 25439 } 25440 } 25441 } 25442 25443 if (vctxt->nbAttrInfos == 0) 25444 return (0); 25445 25446 /* 25447 * Get the owner element; needed for creation of default attributes. 25448 * This fixes bug #341337, reported by David Grohmann. 25449 */ 25450 if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) { 25451 xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth]; 25452 if (ielem && ielem->node && ielem->node->doc) 25453 defAttrOwnerElem = ielem->node; 25454 } 25455 /* 25456 * Validate values, create default attributes, evaluate IDCs. 25457 */ 25458 for (i = 0; i < vctxt->nbAttrInfos; i++) { 25459 iattr = vctxt->attrInfos[i]; 25460 /* 25461 * VAL TODO: Note that we won't try to resolve IDCs to 25462 * "lax" and "skip" validated attributes. Check what to 25463 * do in this case. 25464 */ 25465 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) && 25466 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT)) 25467 continue; 25468 /* 25469 * VAL TODO: What to do if the type definition is missing? 25470 */ 25471 if (iattr->typeDef == NULL) { 25472 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE; 25473 continue; 25474 } 25475 25476 ACTIVATE_ATTRIBUTE(iattr); 25477 fixed = 0; 25478 xpathRes = 0; 25479 25480 if (vctxt->xpathStates != NULL) { 25481 /* 25482 * Evaluate IDCs. 25483 */ 25484 xpathRes = xmlSchemaXPathEvaluate(vctxt, 25485 XML_ATTRIBUTE_NODE); 25486 if (xpathRes == -1) { 25487 VERROR_INT("xmlSchemaVAttributesComplex", 25488 "calling xmlSchemaXPathEvaluate()"); 25489 goto internal_error; 25490 } 25491 } 25492 25493 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) { 25494 /* 25495 * Default/fixed attributes. 25496 * We need the value only if we need to resolve IDCs or 25497 * will create default attributes. 25498 */ 25499 if ((xpathRes) || (defAttrOwnerElem)) { 25500 if (iattr->use->defValue != NULL) { 25501 iattr->value = (xmlChar *) iattr->use->defValue; 25502 iattr->val = iattr->use->defVal; 25503 } else { 25504 iattr->value = (xmlChar *) iattr->decl->defValue; 25505 iattr->val = iattr->decl->defVal; 25506 } 25507 /* 25508 * IDCs will consume the precomputed default value, 25509 * so we need to clone it. 25510 */ 25511 if (iattr->val == NULL) { 25512 VERROR_INT("xmlSchemaVAttributesComplex", 25513 "default/fixed value on an attribute use was " 25514 "not precomputed"); 25515 goto internal_error; 25516 } 25517 iattr->val = xmlSchemaCopyValue(iattr->val); 25518 if (iattr->val == NULL) { 25519 VERROR_INT("xmlSchemaVAttributesComplex", 25520 "calling xmlSchemaCopyValue()"); 25521 goto internal_error; 25522 } 25523 } 25524 /* 25525 * PSVI: Add the default attribute to the current element. 25526 * VAL TODO: Should we use the *normalized* value? This currently 25527 * uses the *initial* value. 25528 */ 25529 25530 if (defAttrOwnerElem) { 25531 xmlChar *normValue; 25532 const xmlChar *value; 25533 25534 value = iattr->value; 25535 /* 25536 * Normalize the value. 25537 */ 25538 normValue = xmlSchemaNormalizeValue(iattr->typeDef, 25539 iattr->value); 25540 if (normValue != NULL) 25541 value = BAD_CAST normValue; 25542 25543 if (iattr->nsName == NULL) { 25544 if (xmlNewProp(defAttrOwnerElem, 25545 iattr->localName, value) == NULL) { 25546 VERROR_INT("xmlSchemaVAttributesComplex", 25547 "callling xmlNewProp()"); 25548 if (normValue != NULL) 25549 xmlFree(normValue); 25550 goto internal_error; 25551 } 25552 } else { 25553 xmlNsPtr ns; 25554 25555 ns = xmlSearchNsByHref(defAttrOwnerElem->doc, 25556 defAttrOwnerElem, iattr->nsName); 25557 if (ns == NULL) { 25558 xmlChar prefix[12]; 25559 int counter = 0; 25560 25561 /* 25562 * Create a namespace declaration on the validation 25563 * root node if no namespace declaration is in scope. 25564 */ 25565 do { 25566 snprintf((char *) prefix, 12, "p%d", counter++); 25567 ns = xmlSearchNs(defAttrOwnerElem->doc, 25568 defAttrOwnerElem, BAD_CAST prefix); 25569 if (counter > 1000) { 25570 VERROR_INT( 25571 "xmlSchemaVAttributesComplex", 25572 "could not compute a ns prefix for a " 25573 "default/fixed attribute"); 25574 if (normValue != NULL) 25575 xmlFree(normValue); 25576 goto internal_error; 25577 } 25578 } while (ns != NULL); 25579 ns = xmlNewNs(vctxt->validationRoot, 25580 iattr->nsName, BAD_CAST prefix); 25581 } 25582 /* 25583 * TODO: 25584 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html 25585 * If we have QNames: do we need to ensure there's a 25586 * prefix defined for the QName? 25587 */ 25588 xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value); 25589 } 25590 if (normValue != NULL) 25591 xmlFree(normValue); 25592 } 25593 /* 25594 * Go directly to IDC evaluation. 25595 */ 25596 goto eval_idcs; 25597 } 25598 /* 25599 * Validate the value. 25600 */ 25601 if (vctxt->value != NULL) { 25602 /* 25603 * Free last computed value; just for safety reasons. 25604 */ 25605 xmlSchemaFreeValue(vctxt->value); 25606 vctxt->value = NULL; 25607 } 25608 /* 25609 * Note that the attribute *use* can be unavailable, if 25610 * the attribute was a wild attribute. 25611 */ 25612 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) || 25613 ((iattr->use != NULL) && 25614 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED))) 25615 fixed = 1; 25616 else 25617 fixed = 0; 25618 /* 25619 * SPEC (cvc-attribute) 25620 * (3) "The item's �normalized value� must be locally �valid� 25621 * with respect to that {type definition} as per 25622 * String Valid (�3.14.4)." 25623 * 25624 * VAL TODO: Do we already have the 25625 * "normalized attribute value" here? 25626 */ 25627 if (xpathRes || fixed) { 25628 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED; 25629 /* 25630 * Request a computed value. 25631 */ 25632 res = xmlSchemaVCheckCVCSimpleType( 25633 ACTXT_CAST vctxt, 25634 iattr->node, iattr->typeDef, iattr->value, &(iattr->val), 25635 1, 1, 0); 25636 } else { 25637 res = xmlSchemaVCheckCVCSimpleType( 25638 ACTXT_CAST vctxt, 25639 iattr->node, iattr->typeDef, iattr->value, NULL, 25640 1, 0, 0); 25641 } 25642 25643 if (res != 0) { 25644 if (res == -1) { 25645 VERROR_INT("xmlSchemaVAttributesComplex", 25646 "calling xmlSchemaStreamValidateSimpleTypeValue()"); 25647 goto internal_error; 25648 } 25649 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE; 25650 /* 25651 * SPEC PSVI Assessment Outcome (Attribute) 25652 * [validity] = "invalid" 25653 */ 25654 goto eval_idcs; 25655 } 25656 25657 if (fixed) { 25658 /* 25659 * SPEC Attribute Locally Valid (Use) (cvc-au) 25660 * "For an attribute information item to be�valid� 25661 * with respect to an attribute use its *normalized* 25662 * value� must match the *canonical* lexical 25663 * representation of the attribute use's {value 25664 * constraint}value, if it is present and fixed." 25665 * 25666 * VAL TODO: The requirement for the *canonical* value 25667 * will be removed in XML Schema 1.1. 25668 */ 25669 /* 25670 * SPEC Attribute Locally Valid (cvc-attribute) 25671 * (4) "The item's *actual* value� must match the *value* of 25672 * the {value constraint}, if it is present and fixed." 25673 */ 25674 if (iattr->val == NULL) { 25675 /* VAL TODO: A value was not precomputed. */ 25676 TODO 25677 goto eval_idcs; 25678 } 25679 if ((iattr->use != NULL) && 25680 (iattr->use->defValue != NULL)) { 25681 if (iattr->use->defVal == NULL) { 25682 /* VAL TODO: A default value was not precomputed. */ 25683 TODO 25684 goto eval_idcs; 25685 } 25686 iattr->vcValue = iattr->use->defValue; 25687 /* 25688 if (xmlSchemaCompareValuesWhtsp(attr->val, 25689 (xmlSchemaWhitespaceValueType) ws, 25690 attr->use->defVal, 25691 (xmlSchemaWhitespaceValueType) ws) != 0) { 25692 */ 25693 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal)) 25694 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE; 25695 } else { 25696 if (iattr->decl->defVal == NULL) { 25697 /* VAL TODO: A default value was not precomputed. */ 25698 TODO 25699 goto eval_idcs; 25700 } 25701 iattr->vcValue = iattr->decl->defValue; 25702 /* 25703 if (xmlSchemaCompareValuesWhtsp(attr->val, 25704 (xmlSchemaWhitespaceValueType) ws, 25705 attrDecl->defVal, 25706 (xmlSchemaWhitespaceValueType) ws) != 0) { 25707 */ 25708 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal)) 25709 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE; 25710 } 25711 /* 25712 * [validity] = "valid" 25713 */ 25714 } 25715eval_idcs: 25716 /* 25717 * Evaluate IDCs. 25718 */ 25719 if (xpathRes) { 25720 if (xmlSchemaXPathProcessHistory(vctxt, 25721 vctxt->depth +1) == -1) { 25722 VERROR_INT("xmlSchemaVAttributesComplex", 25723 "calling xmlSchemaXPathEvaluate()"); 25724 goto internal_error; 25725 } 25726 } else if (vctxt->xpathStates != NULL) 25727 xmlSchemaXPathPop(vctxt); 25728 } 25729 25730 /* 25731 * Report errors. 25732 */ 25733 for (i = 0; i < vctxt->nbAttrInfos; i++) { 25734 iattr = vctxt->attrInfos[i]; 25735 if ((iattr->state == XML_SCHEMAS_ATTR_META) || 25736 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) || 25737 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) || 25738 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL)) 25739 continue; 25740 ACTIVATE_ATTRIBUTE(iattr); 25741 switch (iattr->state) { 25742 case XML_SCHEMAS_ATTR_ERR_MISSING: { 25743 xmlChar *str = NULL; 25744 ACTIVATE_ELEM; 25745 xmlSchemaCustomErr(ACTXT_CAST vctxt, 25746 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL, 25747 "The attribute '%s' is required but missing", 25748 xmlSchemaFormatQName(&str, 25749 iattr->decl->targetNamespace, 25750 iattr->decl->name), 25751 NULL); 25752 FREE_AND_NULL(str) 25753 break; 25754 } 25755 case XML_SCHEMAS_ATTR_ERR_NO_TYPE: 25756 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL, 25757 "The type definition is absent"); 25758 break; 25759 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE: 25760 xmlSchemaCustomErr(ACTXT_CAST vctxt, 25761 XML_SCHEMAV_CVC_AU, NULL, NULL, 25762 "The value '%s' does not match the fixed " 25763 "value constraint '%s'", 25764 iattr->value, iattr->vcValue); 25765 break; 25766 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL: 25767 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL, 25768 "No matching global attribute declaration available, but " 25769 "demanded by the strict wildcard"); 25770 break; 25771 case XML_SCHEMAS_ATTR_UNKNOWN: 25772 if (iattr->metaType) 25773 break; 25774 /* 25775 * MAYBE VAL TODO: One might report different error messages 25776 * for the following errors. 25777 */ 25778 if (type->attributeWildcard == NULL) { 25779 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt, 25780 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL); 25781 } else { 25782 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt, 25783 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL); 25784 } 25785 break; 25786 default: 25787 break; 25788 } 25789 } 25790 25791 ACTIVATE_ELEM; 25792 return (0); 25793internal_error: 25794 ACTIVATE_ELEM; 25795 return (-1); 25796} 25797 25798static int 25799xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt, 25800 int *skip) 25801{ 25802 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl; 25803 /* 25804 * The namespace of the element was already identified to be 25805 * matching the wildcard. 25806 */ 25807 if ((skip == NULL) || (wild == NULL) || 25808 (wild->type != XML_SCHEMA_TYPE_ANY)) { 25809 VERROR_INT("xmlSchemaValidateElemWildcard", 25810 "bad arguments"); 25811 return (-1); 25812 } 25813 *skip = 0; 25814 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) { 25815 /* 25816 * URGENT VAL TODO: Either we need to position the stream to the 25817 * next sibling, or walk the whole subtree. 25818 */ 25819 *skip = 1; 25820 return (0); 25821 } 25822 { 25823 xmlSchemaElementPtr decl = NULL; 25824 25825 decl = xmlSchemaGetElem(vctxt->schema, 25826 vctxt->inode->localName, vctxt->inode->nsName); 25827 if (decl != NULL) { 25828 vctxt->inode->decl = decl; 25829 return (0); 25830 } 25831 } 25832 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) { 25833 /* VAL TODO: Change to proper error code. */ 25834 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */ 25835 "No matching global element declaration available, but " 25836 "demanded by the strict wildcard"); 25837 return (vctxt->err); 25838 } 25839 if (vctxt->nbAttrInfos != 0) { 25840 xmlSchemaAttrInfoPtr iattr; 25841 /* 25842 * SPEC Validation Rule: Schema-Validity Assessment (Element) 25843 * (1.2.1.2.1) - (1.2.1.2.3 ) 25844 * 25845 * Use the xsi:type attribute for the type definition. 25846 */ 25847 iattr = xmlSchemaGetMetaAttrInfo(vctxt, 25848 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE); 25849 if (iattr != NULL) { 25850 if (xmlSchemaProcessXSIType(vctxt, iattr, 25851 &(vctxt->inode->typeDef), NULL) == -1) { 25852 VERROR_INT("xmlSchemaValidateElemWildcard", 25853 "calling xmlSchemaProcessXSIType() to " 25854 "process the attribute 'xsi:nil'"); 25855 return (-1); 25856 } 25857 /* 25858 * Don't return an error on purpose. 25859 */ 25860 return (0); 25861 } 25862 } 25863 /* 25864 * SPEC Validation Rule: Schema-Validity Assessment (Element) 25865 * 25866 * Fallback to "anyType". 25867 */ 25868 vctxt->inode->typeDef = 25869 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); 25870 return (0); 25871} 25872 25873/* 25874* xmlSchemaCheckCOSValidDefault: 25875* 25876* This will be called if: not nilled, no content and a default/fixed 25877* value is provided. 25878*/ 25879 25880static int 25881xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt, 25882 const xmlChar *value, 25883 xmlSchemaValPtr *val) 25884{ 25885 int ret = 0; 25886 xmlSchemaNodeInfoPtr inode = vctxt->inode; 25887 25888 /* 25889 * cos-valid-default: 25890 * Schema Component Constraint: Element Default Valid (Immediate) 25891 * For a string to be a valid default with respect to a type 25892 * definition the appropriate case among the following must be true: 25893 */ 25894 if WXS_IS_COMPLEX(inode->typeDef) { 25895 /* 25896 * Complex type. 25897 * 25898 * SPEC (2.1) "its {content type} must be a simple type definition 25899 * or mixed." 25900 * SPEC (2.2.2) "If the {content type} is mixed, then the {content 25901 * type}'s particle must be �emptiable� as defined by 25902 * Particle Emptiable (�3.9.6)." 25903 */ 25904 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) && 25905 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) || 25906 (! WXS_EMPTIABLE(inode->typeDef)))) { 25907 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1; 25908 /* NOTE that this covers (2.2.2) as well. */ 25909 VERROR(ret, NULL, 25910 "For a string to be a valid default, the type definition " 25911 "must be a simple type or a complex type with simple content " 25912 "or mixed content and a particle emptiable"); 25913 return(ret); 25914 } 25915 } 25916 /* 25917 * 1 If the type definition is a simple type definition, then the string 25918 * must be �valid� with respect to that definition as defined by String 25919 * Valid (�3.14.4). 25920 * 25921 * AND 25922 * 25923 * 2.2.1 If the {content type} is a simple type definition, then the 25924 * string must be �valid� with respect to that simple type definition 25925 * as defined by String Valid (�3.14.4). 25926 */ 25927 if (WXS_IS_SIMPLE(inode->typeDef)) { 25928 25929 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt, 25930 NULL, inode->typeDef, value, val, 1, 1, 0); 25931 25932 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { 25933 25934 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt, 25935 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0); 25936 } 25937 if (ret < 0) { 25938 VERROR_INT("xmlSchemaCheckCOSValidDefault", 25939 "calling xmlSchemaVCheckCVCSimpleType()"); 25940 } 25941 return (ret); 25942} 25943 25944static void 25945xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED, 25946 const xmlChar * name ATTRIBUTE_UNUSED, 25947 xmlSchemaElementPtr item, 25948 xmlSchemaNodeInfoPtr inode) 25949{ 25950 inode->decl = item; 25951#ifdef DEBUG_CONTENT 25952 { 25953 xmlChar *str = NULL; 25954 25955 if (item->type == XML_SCHEMA_TYPE_ELEMENT) { 25956 xmlGenericError(xmlGenericErrorContext, 25957 "AUTOMATON callback for '%s' [declaration]\n", 25958 xmlSchemaFormatQName(&str, 25959 inode->localName, inode->nsName)); 25960 } else { 25961 xmlGenericError(xmlGenericErrorContext, 25962 "AUTOMATON callback for '%s' [wildcard]\n", 25963 xmlSchemaFormatQName(&str, 25964 inode->localName, inode->nsName)); 25965 25966 } 25967 FREE_AND_NULL(str) 25968 } 25969#endif 25970} 25971 25972static int 25973xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt) 25974{ 25975 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt); 25976 if (vctxt->inode == NULL) { 25977 VERROR_INT("xmlSchemaValidatorPushElem", 25978 "calling xmlSchemaGetFreshElemInfo()"); 25979 return (-1); 25980 } 25981 vctxt->nbAttrInfos = 0; 25982 return (0); 25983} 25984 25985static int 25986xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt, 25987 xmlSchemaNodeInfoPtr inode, 25988 xmlSchemaTypePtr type, 25989 const xmlChar *value) 25990{ 25991 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED) 25992 return (xmlSchemaVCheckCVCSimpleType( 25993 ACTXT_CAST vctxt, NULL, 25994 type, value, &(inode->val), 1, 1, 0)); 25995 else 25996 return (xmlSchemaVCheckCVCSimpleType( 25997 ACTXT_CAST vctxt, NULL, 25998 type, value, NULL, 1, 0, 0)); 25999} 26000 26001 26002 26003/* 26004* Process END of element. 26005*/ 26006static int 26007xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt) 26008{ 26009 int ret = 0; 26010 xmlSchemaNodeInfoPtr inode = vctxt->inode; 26011 26012 if (vctxt->nbAttrInfos != 0) 26013 xmlSchemaClearAttrInfos(vctxt); 26014 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) { 26015 /* 26016 * This element was not expected; 26017 * we will not validate child elements of broken parents. 26018 * Skip validation of all content of the parent. 26019 */ 26020 vctxt->skipDepth = vctxt->depth -1; 26021 goto end_elem; 26022 } 26023 if ((inode->typeDef == NULL) || 26024 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) { 26025 /* 26026 * 1. the type definition might be missing if the element was 26027 * error prone 26028 * 2. it might be abstract. 26029 */ 26030 goto end_elem; 26031 } 26032 /* 26033 * Check the content model. 26034 */ 26035 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) || 26036 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) { 26037 26038 /* 26039 * Workaround for "anyType". 26040 */ 26041 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE) 26042 goto character_content; 26043 26044 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) { 26045 xmlChar *values[10]; 26046 int terminal, nbval = 10, nbneg; 26047 26048 if (inode->regexCtxt == NULL) { 26049 /* 26050 * Create the regex context. 26051 */ 26052 inode->regexCtxt = 26053 xmlRegNewExecCtxt(inode->typeDef->contModel, 26054 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback, 26055 vctxt); 26056 if (inode->regexCtxt == NULL) { 26057 VERROR_INT("xmlSchemaValidatorPopElem", 26058 "failed to create a regex context"); 26059 goto internal_error; 26060 } 26061#ifdef DEBUG_AUTOMATA 26062 xmlGenericError(xmlGenericErrorContext, 26063 "AUTOMATON create on '%s'\n", inode->localName); 26064#endif 26065 } 26066 26067 /* 26068 * Do not check further content if the node has been nilled 26069 */ 26070 if (INODE_NILLED(inode)) { 26071 ret = 0; 26072#ifdef DEBUG_AUTOMATA 26073 xmlGenericError(xmlGenericErrorContext, 26074 "AUTOMATON succeeded on nilled '%s'\n", 26075 inode->localName); 26076#endif 26077 goto skip_nilled; 26078 } 26079 26080 /* 26081 * Get hold of the still expected content, since a further 26082 * call to xmlRegExecPushString() will loose this information. 26083 */ 26084 xmlRegExecNextValues(inode->regexCtxt, 26085 &nbval, &nbneg, &values[0], &terminal); 26086 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL); 26087 if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) { 26088 /* 26089 * Still missing something. 26090 */ 26091 ret = 1; 26092 inode->flags |= 26093 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT; 26094 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt, 26095 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL, 26096 "Missing child element(s)", 26097 nbval, nbneg, values); 26098#ifdef DEBUG_AUTOMATA 26099 xmlGenericError(xmlGenericErrorContext, 26100 "AUTOMATON missing ERROR on '%s'\n", 26101 inode->localName); 26102#endif 26103 } else { 26104 /* 26105 * Content model is satisfied. 26106 */ 26107 ret = 0; 26108#ifdef DEBUG_AUTOMATA 26109 xmlGenericError(xmlGenericErrorContext, 26110 "AUTOMATON succeeded on '%s'\n", 26111 inode->localName); 26112#endif 26113 } 26114 26115 } 26116 } 26117 26118skip_nilled: 26119 26120 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS) 26121 goto end_elem; 26122 26123character_content: 26124 26125 if (vctxt->value != NULL) { 26126 xmlSchemaFreeValue(vctxt->value); 26127 vctxt->value = NULL; 26128 } 26129 /* 26130 * Check character content. 26131 */ 26132 if (inode->decl == NULL) { 26133 /* 26134 * Speedup if no declaration exists. 26135 */ 26136 if (WXS_IS_SIMPLE(inode->typeDef)) { 26137 ret = xmlSchemaVCheckINodeDataType(vctxt, 26138 inode, inode->typeDef, inode->value); 26139 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { 26140 ret = xmlSchemaVCheckINodeDataType(vctxt, 26141 inode, inode->typeDef->contentTypeDef, 26142 inode->value); 26143 } 26144 if (ret < 0) { 26145 VERROR_INT("xmlSchemaValidatorPopElem", 26146 "calling xmlSchemaVCheckCVCSimpleType()"); 26147 goto internal_error; 26148 } 26149 goto end_elem; 26150 } 26151 /* 26152 * cvc-elt (3.3.4) : 5 26153 * The appropriate case among the following must be true: 26154 */ 26155 /* 26156 * cvc-elt (3.3.4) : 5.1 26157 * If the declaration has a {value constraint}, 26158 * the item has neither element nor character [children] and 26159 * clause 3.2 has not applied, then all of the following must be true: 26160 */ 26161 if ((inode->decl->value != NULL) && 26162 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) && 26163 (! INODE_NILLED(inode))) { 26164 /* 26165 * cvc-elt (3.3.4) : 5.1.1 26166 * If the �actual type definition� is a �local type definition� 26167 * then the canonical lexical representation of the {value constraint} 26168 * value must be a valid default for the �actual type definition� as 26169 * defined in Element Default Valid (Immediate) (�3.3.6). 26170 */ 26171 /* 26172 * NOTE: 'local' above means types acquired by xsi:type. 26173 * NOTE: Although the *canonical* value is stated, it is not 26174 * relevant if canonical or not. Additionally XML Schema 1.1 26175 * will removed this requirement as well. 26176 */ 26177 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) { 26178 26179 ret = xmlSchemaCheckCOSValidDefault(vctxt, 26180 inode->decl->value, &(inode->val)); 26181 if (ret != 0) { 26182 if (ret < 0) { 26183 VERROR_INT("xmlSchemaValidatorPopElem", 26184 "calling xmlSchemaCheckCOSValidDefault()"); 26185 goto internal_error; 26186 } 26187 goto end_elem; 26188 } 26189 /* 26190 * Stop here, to avoid redundant validation of the value 26191 * (see following). 26192 */ 26193 goto default_psvi; 26194 } 26195 /* 26196 * cvc-elt (3.3.4) : 5.1.2 26197 * The element information item with the canonical lexical 26198 * representation of the {value constraint} value used as its 26199 * �normalized value� must be �valid� with respect to the 26200 * �actual type definition� as defined by Element Locally Valid (Type) 26201 * (�3.3.4). 26202 */ 26203 if (WXS_IS_SIMPLE(inode->typeDef)) { 26204 ret = xmlSchemaVCheckINodeDataType(vctxt, 26205 inode, inode->typeDef, inode->decl->value); 26206 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { 26207 ret = xmlSchemaVCheckINodeDataType(vctxt, 26208 inode, inode->typeDef->contentTypeDef, 26209 inode->decl->value); 26210 } 26211 if (ret != 0) { 26212 if (ret < 0) { 26213 VERROR_INT("xmlSchemaValidatorPopElem", 26214 "calling xmlSchemaVCheckCVCSimpleType()"); 26215 goto internal_error; 26216 } 26217 goto end_elem; 26218 } 26219 26220default_psvi: 26221 /* 26222 * PSVI: Create a text node on the instance element. 26223 */ 26224 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) && 26225 (inode->node != NULL)) { 26226 xmlNodePtr textChild; 26227 xmlChar *normValue; 26228 /* 26229 * VAL TODO: Normalize the value. 26230 */ 26231 normValue = xmlSchemaNormalizeValue(inode->typeDef, 26232 inode->decl->value); 26233 if (normValue != NULL) { 26234 textChild = xmlNewText(BAD_CAST normValue); 26235 xmlFree(normValue); 26236 } else 26237 textChild = xmlNewText(inode->decl->value); 26238 if (textChild == NULL) { 26239 VERROR_INT("xmlSchemaValidatorPopElem", 26240 "calling xmlNewText()"); 26241 goto internal_error; 26242 } else 26243 xmlAddChild(inode->node, textChild); 26244 } 26245 26246 } else if (! INODE_NILLED(inode)) { 26247 /* 26248 * 5.2.1 The element information item must be �valid� with respect 26249 * to the �actual type definition� as defined by Element Locally 26250 * Valid (Type) (�3.3.4). 26251 */ 26252 if (WXS_IS_SIMPLE(inode->typeDef)) { 26253 /* 26254 * SPEC (cvc-type) (3.1) 26255 * "If the type definition is a simple type definition, ..." 26256 * (3.1.3) "If clause 3.2 of Element Locally Valid 26257 * (Element) (�3.3.4) did not apply, then the �normalized value� 26258 * must be �valid� with respect to the type definition as defined 26259 * by String Valid (�3.14.4). 26260 */ 26261 ret = xmlSchemaVCheckINodeDataType(vctxt, 26262 inode, inode->typeDef, inode->value); 26263 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { 26264 /* 26265 * SPEC (cvc-type) (3.2) "If the type definition is a complex type 26266 * definition, then the element information item must be 26267 * �valid� with respect to the type definition as per 26268 * Element Locally Valid (Complex Type) (�3.4.4);" 26269 * 26270 * SPEC (cvc-complex-type) (2.2) 26271 * "If the {content type} is a simple type definition, ... 26272 * the �normalized value� of the element information item is 26273 * �valid� with respect to that simple type definition as 26274 * defined by String Valid (�3.14.4)." 26275 */ 26276 ret = xmlSchemaVCheckINodeDataType(vctxt, 26277 inode, inode->typeDef->contentTypeDef, inode->value); 26278 } 26279 if (ret != 0) { 26280 if (ret < 0) { 26281 VERROR_INT("xmlSchemaValidatorPopElem", 26282 "calling xmlSchemaVCheckCVCSimpleType()"); 26283 goto internal_error; 26284 } 26285 goto end_elem; 26286 } 26287 /* 26288 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has 26289 * not applied, all of the following must be true: 26290 */ 26291 if ((inode->decl->value != NULL) && 26292 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) { 26293 26294 /* 26295 * TODO: We will need a computed value, when comparison is 26296 * done on computed values. 26297 */ 26298 /* 26299 * 5.2.2.1 The element information item must have no element 26300 * information item [children]. 26301 */ 26302 if (inode->flags & 26303 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) { 26304 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1; 26305 VERROR(ret, NULL, 26306 "The content must not containt element nodes since " 26307 "there is a fixed value constraint"); 26308 goto end_elem; 26309 } else { 26310 /* 26311 * 5.2.2.2 The appropriate case among the following must 26312 * be true: 26313 */ 26314 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) { 26315 /* 26316 * 5.2.2.2.1 If the {content type} of the �actual type 26317 * definition� is mixed, then the *initial value* of the 26318 * item must match the canonical lexical representation 26319 * of the {value constraint} value. 26320 * 26321 * ... the *initial value* of an element information 26322 * item is the string composed of, in order, the 26323 * [character code] of each character information item in 26324 * the [children] of that element information item. 26325 */ 26326 if (! xmlStrEqual(inode->value, inode->decl->value)){ 26327 /* 26328 * VAL TODO: Report invalid & expected values as well. 26329 * VAL TODO: Implement the canonical stuff. 26330 */ 26331 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1; 26332 xmlSchemaCustomErr(ACTXT_CAST vctxt, 26333 ret, NULL, NULL, 26334 "The initial value '%s' does not match the fixed " 26335 "value constraint '%s'", 26336 inode->value, inode->decl->value); 26337 goto end_elem; 26338 } 26339 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { 26340 /* 26341 * 5.2.2.2.2 If the {content type} of the �actual type 26342 * definition� is a simple type definition, then the 26343 * *actual value* of the item must match the canonical 26344 * lexical representation of the {value constraint} value. 26345 */ 26346 /* 26347 * VAL TODO: *actual value* is the normalized value, impl. 26348 * this. 26349 * VAL TODO: Report invalid & expected values as well. 26350 * VAL TODO: Implement a comparison with the computed values. 26351 */ 26352 if (! xmlStrEqual(inode->value, 26353 inode->decl->value)) { 26354 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2; 26355 xmlSchemaCustomErr(ACTXT_CAST vctxt, 26356 ret, NULL, NULL, 26357 "The actual value '%s' does not match the fixed " 26358 "value constraint '%s'", 26359 inode->value, 26360 inode->decl->value); 26361 goto end_elem; 26362 } 26363 } 26364 } 26365 } 26366 } 26367 26368end_elem: 26369 if (vctxt->depth < 0) { 26370 /* TODO: raise error? */ 26371 return (0); 26372 } 26373 if (vctxt->depth == vctxt->skipDepth) 26374 vctxt->skipDepth = -1; 26375 /* 26376 * Evaluate the history of XPath state objects. 26377 */ 26378 if (inode->appliedXPath && 26379 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)) 26380 goto internal_error; 26381 /* 26382 * MAYBE TODO: 26383 * SPEC (6) "The element information item must be �valid� with 26384 * respect to each of the {identity-constraint definitions} as per 26385 * Identity-constraint Satisfied (�3.11.4)." 26386 */ 26387 /* 26388 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables 26389 * need to be built in any case. 26390 * We will currently build IDC node-tables and bubble them only if 26391 * keyrefs do exist. 26392 */ 26393 26394 /* 26395 * Add the current IDC target-nodes to the IDC node-tables. 26396 */ 26397 if ((inode->idcMatchers != NULL) && 26398 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables)) 26399 { 26400 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1) 26401 goto internal_error; 26402 } 26403 /* 26404 * Validate IDC keyrefs. 26405 */ 26406 if (vctxt->inode->hasKeyrefs) 26407 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1) 26408 goto internal_error; 26409 /* 26410 * Merge/free the IDC table. 26411 */ 26412 if (inode->idcTable != NULL) { 26413#ifdef DEBUG_IDC_NODE_TABLE 26414 xmlSchemaDebugDumpIDCTable(stdout, 26415 inode->nsName, 26416 inode->localName, 26417 inode->idcTable); 26418#endif 26419 if ((vctxt->depth > 0) && 26420 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables)) 26421 { 26422 /* 26423 * Merge the IDC node table with the table of the parent node. 26424 */ 26425 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1) 26426 goto internal_error; 26427 } 26428 } 26429 /* 26430 * Clear the current ielem. 26431 * VAL TODO: Don't free the PSVI IDC tables if they are 26432 * requested for the PSVI. 26433 */ 26434 xmlSchemaClearElemInfo(vctxt, inode); 26435 /* 26436 * Skip further processing if we are on the validation root. 26437 */ 26438 if (vctxt->depth == 0) { 26439 vctxt->depth--; 26440 vctxt->inode = NULL; 26441 return (0); 26442 } 26443 /* 26444 * Reset the keyrefDepth if needed. 26445 */ 26446 if (vctxt->aidcs != NULL) { 26447 xmlSchemaIDCAugPtr aidc = vctxt->aidcs; 26448 do { 26449 if (aidc->keyrefDepth == vctxt->depth) { 26450 /* 26451 * A 'keyrefDepth' of a key/unique IDC matches the current 26452 * depth, this means that we are leaving the scope of the 26453 * top-most keyref IDC which refers to this IDC. 26454 */ 26455 aidc->keyrefDepth = -1; 26456 } 26457 aidc = aidc->next; 26458 } while (aidc != NULL); 26459 } 26460 vctxt->depth--; 26461 vctxt->inode = vctxt->elemInfos[vctxt->depth]; 26462 /* 26463 * VAL TODO: 7 If the element information item is the �validation root�, it must be 26464 * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4). 26465 */ 26466 return (ret); 26467 26468internal_error: 26469 vctxt->err = -1; 26470 return (-1); 26471} 26472 26473/* 26474* 3.4.4 Complex Type Definition Validation Rules 26475* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type) 26476*/ 26477static int 26478xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt) 26479{ 26480 xmlSchemaNodeInfoPtr pielem; 26481 xmlSchemaTypePtr ptype; 26482 int ret = 0; 26483 26484 if (vctxt->depth <= 0) { 26485 VERROR_INT("xmlSchemaValidateChildElem", 26486 "not intended for the validation root"); 26487 return (-1); 26488 } 26489 pielem = vctxt->elemInfos[vctxt->depth -1]; 26490 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) 26491 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; 26492 /* 26493 * Handle 'nilled' elements. 26494 */ 26495 if (INODE_NILLED(pielem)) { 26496 /* 26497 * SPEC (cvc-elt) (3.3.4) : (3.2.1) 26498 */ 26499 ACTIVATE_PARENT_ELEM; 26500 ret = XML_SCHEMAV_CVC_ELT_3_2_1; 26501 VERROR(ret, NULL, 26502 "Neither character nor element content is allowed, " 26503 "because the element was 'nilled'"); 26504 ACTIVATE_ELEM; 26505 goto unexpected_elem; 26506 } 26507 26508 ptype = pielem->typeDef; 26509 26510 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) { 26511 /* 26512 * Workaround for "anyType": we have currently no content model 26513 * assigned for "anyType", so handle it explicitely. 26514 * "anyType" has an unbounded, lax "any" wildcard. 26515 */ 26516 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema, 26517 vctxt->inode->localName, 26518 vctxt->inode->nsName); 26519 26520 if (vctxt->inode->decl == NULL) { 26521 xmlSchemaAttrInfoPtr iattr; 26522 /* 26523 * Process "xsi:type". 26524 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3) 26525 */ 26526 iattr = xmlSchemaGetMetaAttrInfo(vctxt, 26527 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE); 26528 if (iattr != NULL) { 26529 ret = xmlSchemaProcessXSIType(vctxt, iattr, 26530 &(vctxt->inode->typeDef), NULL); 26531 if (ret != 0) { 26532 if (ret == -1) { 26533 VERROR_INT("xmlSchemaValidateChildElem", 26534 "calling xmlSchemaProcessXSIType() to " 26535 "process the attribute 'xsi:nil'"); 26536 return (-1); 26537 } 26538 return (ret); 26539 } 26540 } else { 26541 /* 26542 * Fallback to "anyType". 26543 * 26544 * SPEC (cvc-assess-elt) 26545 * "If the item cannot be �strictly assessed�, [...] 26546 * an element information item's schema validity may be laxly 26547 * assessed if its �context-determined declaration� is not 26548 * skip by �validating� with respect to the �ur-type 26549 * definition� as per Element Locally Valid (Type) (�3.3.4)." 26550 */ 26551 vctxt->inode->typeDef = 26552 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); 26553 } 26554 } 26555 return (0); 26556 } 26557 26558 switch (ptype->contentType) { 26559 case XML_SCHEMA_CONTENT_EMPTY: 26560 /* 26561 * SPEC (2.1) "If the {content type} is empty, then the 26562 * element information item has no character or element 26563 * information item [children]." 26564 */ 26565 ACTIVATE_PARENT_ELEM 26566 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1; 26567 VERROR(ret, NULL, 26568 "Element content is not allowed, " 26569 "because the content type is empty"); 26570 ACTIVATE_ELEM 26571 goto unexpected_elem; 26572 break; 26573 26574 case XML_SCHEMA_CONTENT_MIXED: 26575 case XML_SCHEMA_CONTENT_ELEMENTS: { 26576 xmlRegExecCtxtPtr regexCtxt; 26577 xmlChar *values[10]; 26578 int terminal, nbval = 10, nbneg; 26579 26580 /* VAL TODO: Optimized "anyType" validation.*/ 26581 26582 if (ptype->contModel == NULL) { 26583 VERROR_INT("xmlSchemaValidateChildElem", 26584 "type has elem content but no content model"); 26585 return (-1); 26586 } 26587 /* 26588 * Safety belf for evaluation if the cont. model was already 26589 * examined to be invalid. 26590 */ 26591 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) { 26592 VERROR_INT("xmlSchemaValidateChildElem", 26593 "validating elem, but elem content is already invalid"); 26594 return (-1); 26595 } 26596 26597 regexCtxt = pielem->regexCtxt; 26598 if (regexCtxt == NULL) { 26599 /* 26600 * Create the regex context. 26601 */ 26602 regexCtxt = xmlRegNewExecCtxt(ptype->contModel, 26603 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback, 26604 vctxt); 26605 if (regexCtxt == NULL) { 26606 VERROR_INT("xmlSchemaValidateChildElem", 26607 "failed to create a regex context"); 26608 return (-1); 26609 } 26610 pielem->regexCtxt = regexCtxt; 26611#ifdef DEBUG_AUTOMATA 26612 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n", 26613 pielem->localName); 26614#endif 26615 } 26616 26617 /* 26618 * SPEC (2.4) "If the {content type} is element-only or mixed, 26619 * then the sequence of the element information item's 26620 * element information item [children], if any, taken in 26621 * order, is �valid� with respect to the {content type}'s 26622 * particle, as defined in Element Sequence Locally Valid 26623 * (Particle) (�3.9.4)." 26624 */ 26625 ret = xmlRegExecPushString2(regexCtxt, 26626 vctxt->inode->localName, 26627 vctxt->inode->nsName, 26628 vctxt->inode); 26629#ifdef DEBUG_AUTOMATA 26630 if (ret < 0) 26631 xmlGenericError(xmlGenericErrorContext, 26632 "AUTOMATON push ERROR for '%s' on '%s'\n", 26633 vctxt->inode->localName, pielem->localName); 26634 else 26635 xmlGenericError(xmlGenericErrorContext, 26636 "AUTOMATON push OK for '%s' on '%s'\n", 26637 vctxt->inode->localName, pielem->localName); 26638#endif 26639 if (vctxt->err == XML_SCHEMAV_INTERNAL) { 26640 VERROR_INT("xmlSchemaValidateChildElem", 26641 "calling xmlRegExecPushString2()"); 26642 return (-1); 26643 } 26644 if (ret < 0) { 26645 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg, 26646 &values[0], &terminal); 26647 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt, 26648 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL, 26649 "This element is not expected", 26650 nbval, nbneg, values); 26651 ret = vctxt->err; 26652 goto unexpected_elem; 26653 } else 26654 ret = 0; 26655 } 26656 break; 26657 case XML_SCHEMA_CONTENT_SIMPLE: 26658 case XML_SCHEMA_CONTENT_BASIC: 26659 ACTIVATE_PARENT_ELEM 26660 if (WXS_IS_COMPLEX(ptype)) { 26661 /* 26662 * SPEC (cvc-complex-type) (2.2) 26663 * "If the {content type} is a simple type definition, then 26664 * the element information item has no element information 26665 * item [children], ..." 26666 */ 26667 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2; 26668 VERROR(ret, NULL, "Element content is not allowed, " 26669 "because the content type is a simple type definition"); 26670 } else { 26671 /* 26672 * SPEC (cvc-type) (3.1.2) "The element information item must 26673 * have no element information item [children]." 26674 */ 26675 ret = XML_SCHEMAV_CVC_TYPE_3_1_2; 26676 VERROR(ret, NULL, "Element content is not allowed, " 26677 "because the type definition is simple"); 26678 } 26679 ACTIVATE_ELEM 26680 ret = vctxt->err; 26681 goto unexpected_elem; 26682 break; 26683 26684 default: 26685 break; 26686 } 26687 return (ret); 26688unexpected_elem: 26689 /* 26690 * Pop this element and set the skipDepth to skip 26691 * all further content of the parent element. 26692 */ 26693 vctxt->skipDepth = vctxt->depth; 26694 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED; 26695 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT; 26696 return (ret); 26697} 26698 26699#define XML_SCHEMA_PUSH_TEXT_PERSIST 1 26700#define XML_SCHEMA_PUSH_TEXT_CREATED 2 26701#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3 26702 26703static int 26704xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt, 26705 int nodeType, const xmlChar *value, int len, 26706 int mode, int *consumed) 26707{ 26708 /* 26709 * Unfortunately we have to duplicate the text sometimes. 26710 * OPTIMIZE: Maybe we could skip it, if: 26711 * 1. content type is simple 26712 * 2. whitespace is "collapse" 26713 * 3. it consists of whitespace only 26714 * 26715 * Process character content. 26716 */ 26717 if (consumed != NULL) 26718 *consumed = 0; 26719 if (INODE_NILLED(vctxt->inode)) { 26720 /* 26721 * SPEC cvc-elt (3.3.4 - 3.2.1) 26722 * "The element information item must have no character or 26723 * element information item [children]." 26724 */ 26725 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL, 26726 "Neither character nor element content is allowed " 26727 "because the element is 'nilled'"); 26728 return (vctxt->err); 26729 } 26730 /* 26731 * SPEC (2.1) "If the {content type} is empty, then the 26732 * element information item has no character or element 26733 * information item [children]." 26734 */ 26735 if (vctxt->inode->typeDef->contentType == 26736 XML_SCHEMA_CONTENT_EMPTY) { 26737 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL, 26738 "Character content is not allowed, " 26739 "because the content type is empty"); 26740 return (vctxt->err); 26741 } 26742 26743 if (vctxt->inode->typeDef->contentType == 26744 XML_SCHEMA_CONTENT_ELEMENTS) { 26745 if ((nodeType != XML_TEXT_NODE) || 26746 (! xmlSchemaIsBlank((xmlChar *) value, len))) { 26747 /* 26748 * SPEC cvc-complex-type (2.3) 26749 * "If the {content type} is element-only, then the 26750 * element information item has no character information 26751 * item [children] other than those whose [character 26752 * code] is defined as a white space in [XML 1.0 (Second 26753 * Edition)]." 26754 */ 26755 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL, 26756 "Character content other than whitespace is not allowed " 26757 "because the content type is 'element-only'"); 26758 return (vctxt->err); 26759 } 26760 return (0); 26761 } 26762 26763 if ((value == NULL) || (value[0] == 0)) 26764 return (0); 26765 /* 26766 * Save the value. 26767 * NOTE that even if the content type is *mixed*, we need the 26768 * *initial value* for default/fixed value constraints. 26769 */ 26770 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) && 26771 ((vctxt->inode->decl == NULL) || 26772 (vctxt->inode->decl->value == NULL))) 26773 return (0); 26774 26775 if (vctxt->inode->value == NULL) { 26776 /* 26777 * Set the value. 26778 */ 26779 switch (mode) { 26780 case XML_SCHEMA_PUSH_TEXT_PERSIST: 26781 /* 26782 * When working on a tree. 26783 */ 26784 vctxt->inode->value = value; 26785 break; 26786 case XML_SCHEMA_PUSH_TEXT_CREATED: 26787 /* 26788 * When working with the reader. 26789 * The value will be freed by the element info. 26790 */ 26791 vctxt->inode->value = value; 26792 if (consumed != NULL) 26793 *consumed = 1; 26794 vctxt->inode->flags |= 26795 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; 26796 break; 26797 case XML_SCHEMA_PUSH_TEXT_VOLATILE: 26798 /* 26799 * When working with SAX. 26800 * The value will be freed by the element info. 26801 */ 26802 if (len != -1) 26803 vctxt->inode->value = BAD_CAST xmlStrndup(value, len); 26804 else 26805 vctxt->inode->value = BAD_CAST xmlStrdup(value); 26806 vctxt->inode->flags |= 26807 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; 26808 break; 26809 default: 26810 break; 26811 } 26812 } else { 26813 if (len < 0) 26814 len = xmlStrlen(value); 26815 /* 26816 * Concat the value. 26817 */ 26818 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) { 26819 vctxt->inode->value = BAD_CAST xmlStrncat( 26820 (xmlChar *) vctxt->inode->value, value, len); 26821 } else { 26822 vctxt->inode->value = 26823 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len); 26824 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; 26825 } 26826 } 26827 26828 return (0); 26829} 26830 26831static int 26832xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt) 26833{ 26834 int ret = 0; 26835 26836 if ((vctxt->skipDepth != -1) && 26837 (vctxt->depth >= vctxt->skipDepth)) { 26838 VERROR_INT("xmlSchemaValidateElem", 26839 "in skip-state"); 26840 goto internal_error; 26841 } 26842 if (vctxt->xsiAssemble) { 26843 /* 26844 * We will stop validation if there was an error during 26845 * dynamic schema construction. 26846 * Note that we simply set @skipDepth to 0, this could 26847 * mean that a streaming document via SAX would be 26848 * still read to the end but it won't be validated any more. 26849 * TODO: If we are sure how to stop the validation at once 26850 * for all input scenarios, then this should be changed to 26851 * instantly stop the validation. 26852 */ 26853 ret = xmlSchemaAssembleByXSI(vctxt); 26854 if (ret != 0) { 26855 if (ret == -1) 26856 goto internal_error; 26857 vctxt->skipDepth = 0; 26858 return(ret); 26859 } 26860 /* 26861 * Augment the IDC definitions for the main schema and all imported ones 26862 * NOTE: main schema is the first in the imported list 26863 */ 26864 xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt); 26865 } 26866 if (vctxt->depth > 0) { 26867 /* 26868 * Validate this element against the content model 26869 * of the parent. 26870 */ 26871 ret = xmlSchemaValidateChildElem(vctxt); 26872 if (ret != 0) { 26873 if (ret < 0) { 26874 VERROR_INT("xmlSchemaValidateElem", 26875 "calling xmlSchemaStreamValidateChildElement()"); 26876 goto internal_error; 26877 } 26878 goto exit; 26879 } 26880 if (vctxt->depth == vctxt->skipDepth) 26881 goto exit; 26882 if ((vctxt->inode->decl == NULL) && 26883 (vctxt->inode->typeDef == NULL)) { 26884 VERROR_INT("xmlSchemaValidateElem", 26885 "the child element was valid but neither the " 26886 "declaration nor the type was set"); 26887 goto internal_error; 26888 } 26889 } else { 26890 /* 26891 * Get the declaration of the validation root. 26892 */ 26893 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema, 26894 vctxt->inode->localName, 26895 vctxt->inode->nsName); 26896 if (vctxt->inode->decl == NULL) { 26897 ret = XML_SCHEMAV_CVC_ELT_1; 26898 VERROR(ret, NULL, 26899 "No matching global declaration available " 26900 "for the validation root"); 26901 goto exit; 26902 } 26903 } 26904 26905 if (vctxt->inode->decl == NULL) 26906 goto type_validation; 26907 26908 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) { 26909 int skip; 26910 /* 26911 * Wildcards. 26912 */ 26913 ret = xmlSchemaValidateElemWildcard(vctxt, &skip); 26914 if (ret != 0) { 26915 if (ret < 0) { 26916 VERROR_INT("xmlSchemaValidateElem", 26917 "calling xmlSchemaValidateElemWildcard()"); 26918 goto internal_error; 26919 } 26920 goto exit; 26921 } 26922 if (skip) { 26923 vctxt->skipDepth = vctxt->depth; 26924 goto exit; 26925 } 26926 /* 26927 * The declaration might be set by the wildcard validation, 26928 * when the processContents is "lax" or "strict". 26929 */ 26930 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) { 26931 /* 26932 * Clear the "decl" field to not confuse further processing. 26933 */ 26934 vctxt->inode->decl = NULL; 26935 goto type_validation; 26936 } 26937 } 26938 /* 26939 * Validate against the declaration. 26940 */ 26941 ret = xmlSchemaValidateElemDecl(vctxt); 26942 if (ret != 0) { 26943 if (ret < 0) { 26944 VERROR_INT("xmlSchemaValidateElem", 26945 "calling xmlSchemaValidateElemDecl()"); 26946 goto internal_error; 26947 } 26948 goto exit; 26949 } 26950 /* 26951 * Validate against the type definition. 26952 */ 26953type_validation: 26954 26955 if (vctxt->inode->typeDef == NULL) { 26956 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE; 26957 ret = XML_SCHEMAV_CVC_TYPE_1; 26958 VERROR(ret, NULL, 26959 "The type definition is absent"); 26960 goto exit; 26961 } 26962 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) { 26963 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE; 26964 ret = XML_SCHEMAV_CVC_TYPE_2; 26965 VERROR(ret, NULL, 26966 "The type definition is abstract"); 26967 goto exit; 26968 } 26969 /* 26970 * Evaluate IDCs. Do it here, since new IDC matchers are registered 26971 * during validation against the declaration. This must be done 26972 * _before_ attribute validation. 26973 */ 26974 if (vctxt->xpathStates != NULL) { 26975 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE); 26976 vctxt->inode->appliedXPath = 1; 26977 if (ret == -1) { 26978 VERROR_INT("xmlSchemaValidateElem", 26979 "calling xmlSchemaXPathEvaluate()"); 26980 goto internal_error; 26981 } 26982 } 26983 /* 26984 * Validate attributes. 26985 */ 26986 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) { 26987 if ((vctxt->nbAttrInfos != 0) || 26988 (vctxt->inode->typeDef->attrUses != NULL)) { 26989 26990 ret = xmlSchemaVAttributesComplex(vctxt); 26991 } 26992 } else if (vctxt->nbAttrInfos != 0) { 26993 26994 ret = xmlSchemaVAttributesSimple(vctxt); 26995 } 26996 /* 26997 * Clear registered attributes. 26998 */ 26999 if (vctxt->nbAttrInfos != 0) 27000 xmlSchemaClearAttrInfos(vctxt); 27001 if (ret == -1) { 27002 VERROR_INT("xmlSchemaValidateElem", 27003 "calling attributes validation"); 27004 goto internal_error; 27005 } 27006 /* 27007 * Don't return an error if attributes are invalid on purpose. 27008 */ 27009 ret = 0; 27010 27011exit: 27012 if (ret != 0) 27013 vctxt->skipDepth = vctxt->depth; 27014 return (ret); 27015internal_error: 27016 return (-1); 27017} 27018 27019#ifdef XML_SCHEMA_READER_ENABLED 27020static int 27021xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt) 27022{ 27023 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15; 27024 int depth, nodeType, ret = 0, consumed; 27025 xmlSchemaNodeInfoPtr ielem; 27026 27027 vctxt->depth = -1; 27028 ret = xmlTextReaderRead(vctxt->reader); 27029 /* 27030 * Move to the document element. 27031 */ 27032 while (ret == 1) { 27033 nodeType = xmlTextReaderNodeType(vctxt->reader); 27034 if (nodeType == XML_ELEMENT_NODE) 27035 goto root_found; 27036 ret = xmlTextReaderRead(vctxt->reader); 27037 } 27038 goto exit; 27039 27040root_found: 27041 27042 do { 27043 depth = xmlTextReaderDepth(vctxt->reader); 27044 nodeType = xmlTextReaderNodeType(vctxt->reader); 27045 27046 if (nodeType == XML_ELEMENT_NODE) { 27047 27048 vctxt->depth++; 27049 if (xmlSchemaValidatorPushElem(vctxt) == -1) { 27050 VERROR_INT("xmlSchemaVReaderWalk", 27051 "calling xmlSchemaValidatorPushElem()"); 27052 goto internal_error; 27053 } 27054 ielem = vctxt->inode; 27055 ielem->localName = xmlTextReaderLocalName(vctxt->reader); 27056 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader); 27057 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES; 27058 /* 27059 * Is the element empty? 27060 */ 27061 ret = xmlTextReaderIsEmptyElement(vctxt->reader); 27062 if (ret == -1) { 27063 VERROR_INT("xmlSchemaVReaderWalk", 27064 "calling xmlTextReaderIsEmptyElement()"); 27065 goto internal_error; 27066 } 27067 if (ret) { 27068 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY; 27069 } 27070 /* 27071 * Register attributes. 27072 */ 27073 vctxt->nbAttrInfos = 0; 27074 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader); 27075 if (ret == -1) { 27076 VERROR_INT("xmlSchemaVReaderWalk", 27077 "calling xmlTextReaderMoveToFirstAttribute()"); 27078 goto internal_error; 27079 } 27080 if (ret == 1) { 27081 do { 27082 /* 27083 * VAL TODO: How do we know that the reader works on a 27084 * node tree, to be able to pass a node here? 27085 */ 27086 if (xmlSchemaValidatorPushAttribute(vctxt, NULL, 27087 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader), 27088 xmlTextReaderNamespaceUri(vctxt->reader), 1, 27089 xmlTextReaderValue(vctxt->reader), 1) == -1) { 27090 27091 VERROR_INT("xmlSchemaVReaderWalk", 27092 "calling xmlSchemaValidatorPushAttribute()"); 27093 goto internal_error; 27094 } 27095 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader); 27096 if (ret == -1) { 27097 VERROR_INT("xmlSchemaVReaderWalk", 27098 "calling xmlTextReaderMoveToFirstAttribute()"); 27099 goto internal_error; 27100 } 27101 } while (ret == 1); 27102 /* 27103 * Back to element position. 27104 */ 27105 ret = xmlTextReaderMoveToElement(vctxt->reader); 27106 if (ret == -1) { 27107 VERROR_INT("xmlSchemaVReaderWalk", 27108 "calling xmlTextReaderMoveToElement()"); 27109 goto internal_error; 27110 } 27111 } 27112 /* 27113 * Validate the element. 27114 */ 27115 ret= xmlSchemaValidateElem(vctxt); 27116 if (ret != 0) { 27117 if (ret == -1) { 27118 VERROR_INT("xmlSchemaVReaderWalk", 27119 "calling xmlSchemaValidateElem()"); 27120 goto internal_error; 27121 } 27122 goto exit; 27123 } 27124 if (vctxt->depth == vctxt->skipDepth) { 27125 int curDepth; 27126 /* 27127 * Skip all content. 27128 */ 27129 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) { 27130 ret = xmlTextReaderRead(vctxt->reader); 27131 curDepth = xmlTextReaderDepth(vctxt->reader); 27132 while ((ret == 1) && (curDepth != depth)) { 27133 ret = xmlTextReaderRead(vctxt->reader); 27134 curDepth = xmlTextReaderDepth(vctxt->reader); 27135 } 27136 if (ret < 0) { 27137 /* 27138 * VAL TODO: A reader error occured; what to do here? 27139 */ 27140 ret = 1; 27141 goto exit; 27142 } 27143 } 27144 goto leave_elem; 27145 } 27146 /* 27147 * READER VAL TODO: Is an END_ELEM really never called 27148 * if the elem is empty? 27149 */ 27150 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) 27151 goto leave_elem; 27152 } else if (nodeType == END_ELEM) { 27153 /* 27154 * Process END of element. 27155 */ 27156leave_elem: 27157 ret = xmlSchemaValidatorPopElem(vctxt); 27158 if (ret != 0) { 27159 if (ret < 0) { 27160 VERROR_INT("xmlSchemaVReaderWalk", 27161 "calling xmlSchemaValidatorPopElem()"); 27162 goto internal_error; 27163 } 27164 goto exit; 27165 } 27166 if (vctxt->depth >= 0) 27167 ielem = vctxt->inode; 27168 else 27169 ielem = NULL; 27170 } else if ((nodeType == XML_TEXT_NODE) || 27171 (nodeType == XML_CDATA_SECTION_NODE) || 27172 (nodeType == WHTSP) || 27173 (nodeType == SIGN_WHTSP)) { 27174 /* 27175 * Process character content. 27176 */ 27177 xmlChar *value; 27178 27179 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP)) 27180 nodeType = XML_TEXT_NODE; 27181 27182 value = xmlTextReaderValue(vctxt->reader); 27183 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value, 27184 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed); 27185 if (! consumed) 27186 xmlFree(value); 27187 if (ret == -1) { 27188 VERROR_INT("xmlSchemaVReaderWalk", 27189 "calling xmlSchemaVPushText()"); 27190 goto internal_error; 27191 } 27192 } else if ((nodeType == XML_ENTITY_NODE) || 27193 (nodeType == XML_ENTITY_REF_NODE)) { 27194 /* 27195 * VAL TODO: What to do with entities? 27196 */ 27197 TODO 27198 } 27199 /* 27200 * Read next node. 27201 */ 27202 ret = xmlTextReaderRead(vctxt->reader); 27203 } while (ret == 1); 27204 27205exit: 27206 return (ret); 27207internal_error: 27208 return (-1); 27209} 27210#endif 27211 27212/************************************************************************ 27213 * * 27214 * SAX validation handlers * 27215 * * 27216 ************************************************************************/ 27217 27218/* 27219* Process text content. 27220*/ 27221static void 27222xmlSchemaSAXHandleText(void *ctx, 27223 const xmlChar * ch, 27224 int len) 27225{ 27226 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; 27227 27228 if (vctxt->depth < 0) 27229 return; 27230 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) 27231 return; 27232 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) 27233 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; 27234 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len, 27235 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) { 27236 VERROR_INT("xmlSchemaSAXHandleCDataSection", 27237 "calling xmlSchemaVPushText()"); 27238 vctxt->err = -1; 27239 xmlStopParser(vctxt->parserCtxt); 27240 } 27241} 27242 27243/* 27244* Process CDATA content. 27245*/ 27246static void 27247xmlSchemaSAXHandleCDataSection(void *ctx, 27248 const xmlChar * ch, 27249 int len) 27250{ 27251 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; 27252 27253 if (vctxt->depth < 0) 27254 return; 27255 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) 27256 return; 27257 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) 27258 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; 27259 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len, 27260 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) { 27261 VERROR_INT("xmlSchemaSAXHandleCDataSection", 27262 "calling xmlSchemaVPushText()"); 27263 vctxt->err = -1; 27264 xmlStopParser(vctxt->parserCtxt); 27265 } 27266} 27267 27268static void 27269xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED, 27270 const xmlChar * name ATTRIBUTE_UNUSED) 27271{ 27272 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; 27273 27274 if (vctxt->depth < 0) 27275 return; 27276 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) 27277 return; 27278 /* SAX VAL TODO: What to do here? */ 27279 TODO 27280} 27281 27282static void 27283xmlSchemaSAXHandleStartElementNs(void *ctx, 27284 const xmlChar * localname, 27285 const xmlChar * prefix ATTRIBUTE_UNUSED, 27286 const xmlChar * URI, 27287 int nb_namespaces, 27288 const xmlChar ** namespaces, 27289 int nb_attributes, 27290 int nb_defaulted ATTRIBUTE_UNUSED, 27291 const xmlChar ** attributes) 27292{ 27293 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; 27294 int ret; 27295 xmlSchemaNodeInfoPtr ielem; 27296 int i, j; 27297 27298 /* 27299 * SAX VAL TODO: What to do with nb_defaulted? 27300 */ 27301 /* 27302 * Skip elements if inside a "skip" wildcard or invalid. 27303 */ 27304 vctxt->depth++; 27305 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) 27306 return; 27307 /* 27308 * Push the element. 27309 */ 27310 if (xmlSchemaValidatorPushElem(vctxt) == -1) { 27311 VERROR_INT("xmlSchemaSAXHandleStartElementNs", 27312 "calling xmlSchemaValidatorPushElem()"); 27313 goto internal_error; 27314 } 27315 ielem = vctxt->inode; 27316 /* 27317 * TODO: Is this OK? 27318 */ 27319 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt); 27320 ielem->localName = localname; 27321 ielem->nsName = URI; 27322 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY; 27323 /* 27324 * Register namespaces on the elem info. 27325 */ 27326 if (nb_namespaces != 0) { 27327 /* 27328 * Although the parser builds its own namespace list, 27329 * we have no access to it, so we'll use an own one. 27330 */ 27331 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) { 27332 /* 27333 * Store prefix and namespace name. 27334 */ 27335 if (ielem->nsBindings == NULL) { 27336 ielem->nsBindings = 27337 (const xmlChar **) xmlMalloc(10 * 27338 sizeof(const xmlChar *)); 27339 if (ielem->nsBindings == NULL) { 27340 xmlSchemaVErrMemory(vctxt, 27341 "allocating namespace bindings for SAX validation", 27342 NULL); 27343 goto internal_error; 27344 } 27345 ielem->nbNsBindings = 0; 27346 ielem->sizeNsBindings = 5; 27347 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) { 27348 ielem->sizeNsBindings *= 2; 27349 ielem->nsBindings = 27350 (const xmlChar **) xmlRealloc( 27351 (void *) ielem->nsBindings, 27352 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *)); 27353 if (ielem->nsBindings == NULL) { 27354 xmlSchemaVErrMemory(vctxt, 27355 "re-allocating namespace bindings for SAX validation", 27356 NULL); 27357 goto internal_error; 27358 } 27359 } 27360 27361 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j]; 27362 if (namespaces[j+1][0] == 0) { 27363 /* 27364 * Handle xmlns="". 27365 */ 27366 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL; 27367 } else 27368 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = 27369 namespaces[j+1]; 27370 ielem->nbNsBindings++; 27371 } 27372 } 27373 /* 27374 * Register attributes. 27375 * SAX VAL TODO: We are not adding namespace declaration 27376 * attributes yet. 27377 */ 27378 if (nb_attributes != 0) { 27379 xmlChar *value; 27380 27381 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) { 27382 /* 27383 * Duplicate the value. 27384 */ 27385 value = xmlStrndup(attributes[j+3], 27386 attributes[j+4] - attributes[j+3]); 27387 /* 27388 * TODO: Set the node line. 27389 */ 27390 ret = xmlSchemaValidatorPushAttribute(vctxt, 27391 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0, 27392 value, 1); 27393 if (ret == -1) { 27394 VERROR_INT("xmlSchemaSAXHandleStartElementNs", 27395 "calling xmlSchemaValidatorPushAttribute()"); 27396 goto internal_error; 27397 } 27398 } 27399 } 27400 /* 27401 * Validate the element. 27402 */ 27403 ret = xmlSchemaValidateElem(vctxt); 27404 if (ret != 0) { 27405 if (ret == -1) { 27406 VERROR_INT("xmlSchemaSAXHandleStartElementNs", 27407 "calling xmlSchemaValidateElem()"); 27408 goto internal_error; 27409 } 27410 goto exit; 27411 } 27412 27413exit: 27414 return; 27415internal_error: 27416 vctxt->err = -1; 27417 xmlStopParser(vctxt->parserCtxt); 27418 return; 27419} 27420 27421static void 27422xmlSchemaSAXHandleEndElementNs(void *ctx, 27423 const xmlChar * localname ATTRIBUTE_UNUSED, 27424 const xmlChar * prefix ATTRIBUTE_UNUSED, 27425 const xmlChar * URI ATTRIBUTE_UNUSED) 27426{ 27427 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; 27428 int res; 27429 27430 /* 27431 * Skip elements if inside a "skip" wildcard or if invalid. 27432 */ 27433 if (vctxt->skipDepth != -1) { 27434 if (vctxt->depth > vctxt->skipDepth) { 27435 vctxt->depth--; 27436 return; 27437 } else 27438 vctxt->skipDepth = -1; 27439 } 27440 /* 27441 * SAX VAL TODO: Just a temporary check. 27442 */ 27443 if ((!xmlStrEqual(vctxt->inode->localName, localname)) || 27444 (!xmlStrEqual(vctxt->inode->nsName, URI))) { 27445 VERROR_INT("xmlSchemaSAXHandleEndElementNs", 27446 "elem pop mismatch"); 27447 } 27448 res = xmlSchemaValidatorPopElem(vctxt); 27449 if (res != 0) { 27450 if (res < 0) { 27451 VERROR_INT("xmlSchemaSAXHandleEndElementNs", 27452 "calling xmlSchemaValidatorPopElem()"); 27453 goto internal_error; 27454 } 27455 goto exit; 27456 } 27457exit: 27458 return; 27459internal_error: 27460 vctxt->err = -1; 27461 xmlStopParser(vctxt->parserCtxt); 27462 return; 27463} 27464 27465/************************************************************************ 27466 * * 27467 * Validation interfaces * 27468 * * 27469 ************************************************************************/ 27470 27471/** 27472 * xmlSchemaNewValidCtxt: 27473 * @schema: a precompiled XML Schemas 27474 * 27475 * Create an XML Schemas validation context based on the given schema. 27476 * 27477 * Returns the validation context or NULL in case of error 27478 */ 27479xmlSchemaValidCtxtPtr 27480xmlSchemaNewValidCtxt(xmlSchemaPtr schema) 27481{ 27482 xmlSchemaValidCtxtPtr ret; 27483 27484 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt)); 27485 if (ret == NULL) { 27486 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL); 27487 return (NULL); 27488 } 27489 memset(ret, 0, sizeof(xmlSchemaValidCtxt)); 27490 ret->type = XML_SCHEMA_CTXT_VALIDATOR; 27491 ret->dict = xmlDictCreate(); 27492 ret->nodeQNames = xmlSchemaItemListCreate(); 27493 ret->schema = schema; 27494 return (ret); 27495} 27496 27497/** 27498 * xmlSchemaValidateSetFilename: 27499 * @vctxt: the schema validation context 27500 * @filename: the file name 27501 * 27502 * Workaround to provide file error reporting information when this is 27503 * not provided by current APIs 27504 */ 27505void 27506xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) { 27507 if (vctxt == NULL) 27508 return; 27509 if (vctxt->filename != NULL) 27510 xmlFree(vctxt->filename); 27511 if (filename != NULL) 27512 vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename); 27513 else 27514 vctxt->filename = NULL; 27515} 27516 27517/** 27518 * xmlSchemaClearValidCtxt: 27519 * @vctxt: the schema validation context 27520 * 27521 * Free the resources associated to the schema validation context; 27522 * leaves some fields alive intended for reuse of the context. 27523 */ 27524static void 27525xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt) 27526{ 27527 if (vctxt == NULL) 27528 return; 27529 27530 /* 27531 * TODO: Should we clear the flags? 27532 * Might be problematic if one reuses the context 27533 * and assumes that the options remain the same. 27534 */ 27535 vctxt->flags = 0; 27536 vctxt->validationRoot = NULL; 27537 vctxt->doc = NULL; 27538#ifdef LIBXML_READER_ENABLED 27539 vctxt->reader = NULL; 27540#endif 27541 vctxt->hasKeyrefs = 0; 27542 27543 if (vctxt->value != NULL) { 27544 xmlSchemaFreeValue(vctxt->value); 27545 vctxt->value = NULL; 27546 } 27547 /* 27548 * Augmented IDC information. 27549 */ 27550 if (vctxt->aidcs != NULL) { 27551 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next; 27552 do { 27553 next = cur->next; 27554 xmlFree(cur); 27555 cur = next; 27556 } while (cur != NULL); 27557 vctxt->aidcs = NULL; 27558 } 27559 if (vctxt->idcMatcherCache != NULL) { 27560 xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp; 27561 27562 while (matcher) { 27563 tmp = matcher; 27564 matcher = matcher->nextCached; 27565 xmlSchemaIDCFreeMatcherList(tmp); 27566 } 27567 vctxt->idcMatcherCache = NULL; 27568 } 27569 27570 27571 if (vctxt->idcNodes != NULL) { 27572 int i; 27573 xmlSchemaPSVIIDCNodePtr item; 27574 27575 for (i = 0; i < vctxt->nbIdcNodes; i++) { 27576 item = vctxt->idcNodes[i]; 27577 xmlFree(item->keys); 27578 xmlFree(item); 27579 } 27580 xmlFree(vctxt->idcNodes); 27581 vctxt->idcNodes = NULL; 27582 vctxt->nbIdcNodes = 0; 27583 vctxt->sizeIdcNodes = 0; 27584 } 27585 /* 27586 * Note that we won't delete the XPath state pool here. 27587 */ 27588 if (vctxt->xpathStates != NULL) { 27589 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates); 27590 vctxt->xpathStates = NULL; 27591 } 27592 /* 27593 * Attribute info. 27594 */ 27595 if (vctxt->nbAttrInfos != 0) { 27596 xmlSchemaClearAttrInfos(vctxt); 27597 } 27598 /* 27599 * Element info. 27600 */ 27601 if (vctxt->elemInfos != NULL) { 27602 int i; 27603 xmlSchemaNodeInfoPtr ei; 27604 27605 for (i = 0; i < vctxt->sizeElemInfos; i++) { 27606 ei = vctxt->elemInfos[i]; 27607 if (ei == NULL) 27608 break; 27609 xmlSchemaClearElemInfo(vctxt, ei); 27610 } 27611 } 27612 xmlSchemaItemListClear(vctxt->nodeQNames); 27613 /* Recreate the dict. */ 27614 xmlDictFree(vctxt->dict); 27615 /* 27616 * TODO: Is is save to recreate it? Do we have a scenario 27617 * where the user provides the dict? 27618 */ 27619 vctxt->dict = xmlDictCreate(); 27620 27621 if (vctxt->filename != NULL) { 27622 xmlFree(vctxt->filename); 27623 vctxt->filename = NULL; 27624 } 27625} 27626 27627/** 27628 * xmlSchemaFreeValidCtxt: 27629 * @ctxt: the schema validation context 27630 * 27631 * Free the resources associated to the schema validation context 27632 */ 27633void 27634xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) 27635{ 27636 if (ctxt == NULL) 27637 return; 27638 if (ctxt->value != NULL) 27639 xmlSchemaFreeValue(ctxt->value); 27640 if (ctxt->pctxt != NULL) 27641 xmlSchemaFreeParserCtxt(ctxt->pctxt); 27642 if (ctxt->idcNodes != NULL) { 27643 int i; 27644 xmlSchemaPSVIIDCNodePtr item; 27645 27646 for (i = 0; i < ctxt->nbIdcNodes; i++) { 27647 item = ctxt->idcNodes[i]; 27648 xmlFree(item->keys); 27649 xmlFree(item); 27650 } 27651 xmlFree(ctxt->idcNodes); 27652 } 27653 if (ctxt->idcKeys != NULL) { 27654 int i; 27655 for (i = 0; i < ctxt->nbIdcKeys; i++) 27656 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]); 27657 xmlFree(ctxt->idcKeys); 27658 } 27659 27660 if (ctxt->xpathStates != NULL) { 27661 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates); 27662 ctxt->xpathStates = NULL; 27663 } 27664 if (ctxt->xpathStatePool != NULL) { 27665 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool); 27666 ctxt->xpathStatePool = NULL; 27667 } 27668 27669 /* 27670 * Augmented IDC information. 27671 */ 27672 if (ctxt->aidcs != NULL) { 27673 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next; 27674 do { 27675 next = cur->next; 27676 xmlFree(cur); 27677 cur = next; 27678 } while (cur != NULL); 27679 } 27680 if (ctxt->attrInfos != NULL) { 27681 int i; 27682 xmlSchemaAttrInfoPtr attr; 27683 27684 /* Just a paranoid call to the cleanup. */ 27685 if (ctxt->nbAttrInfos != 0) 27686 xmlSchemaClearAttrInfos(ctxt); 27687 for (i = 0; i < ctxt->sizeAttrInfos; i++) { 27688 attr = ctxt->attrInfos[i]; 27689 xmlFree(attr); 27690 } 27691 xmlFree(ctxt->attrInfos); 27692 } 27693 if (ctxt->elemInfos != NULL) { 27694 int i; 27695 xmlSchemaNodeInfoPtr ei; 27696 27697 for (i = 0; i < ctxt->sizeElemInfos; i++) { 27698 ei = ctxt->elemInfos[i]; 27699 if (ei == NULL) 27700 break; 27701 xmlSchemaClearElemInfo(ctxt, ei); 27702 xmlFree(ei); 27703 } 27704 xmlFree(ctxt->elemInfos); 27705 } 27706 if (ctxt->nodeQNames != NULL) 27707 xmlSchemaItemListFree(ctxt->nodeQNames); 27708 if (ctxt->dict != NULL) 27709 xmlDictFree(ctxt->dict); 27710 if (ctxt->filename != NULL) 27711 xmlFree(ctxt->filename); 27712 xmlFree(ctxt); 27713} 27714 27715/** 27716 * xmlSchemaIsValid: 27717 * @ctxt: the schema validation context 27718 * 27719 * Check if any error was detected during validation. 27720 * 27721 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case 27722 * of internal error. 27723 */ 27724int 27725xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt) 27726{ 27727 if (ctxt == NULL) 27728 return(-1); 27729 return(ctxt->err == 0); 27730} 27731 27732/** 27733 * xmlSchemaSetValidErrors: 27734 * @ctxt: a schema validation context 27735 * @err: the error function 27736 * @warn: the warning function 27737 * @ctx: the functions context 27738 * 27739 * Set the error and warning callback informations 27740 */ 27741void 27742xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt, 27743 xmlSchemaValidityErrorFunc err, 27744 xmlSchemaValidityWarningFunc warn, void *ctx) 27745{ 27746 if (ctxt == NULL) 27747 return; 27748 ctxt->error = err; 27749 ctxt->warning = warn; 27750 ctxt->errCtxt = ctx; 27751 if (ctxt->pctxt != NULL) 27752 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx); 27753} 27754 27755/** 27756 * xmlSchemaSetValidStructuredErrors: 27757 * @ctxt: a schema validation context 27758 * @serror: the structured error function 27759 * @ctx: the functions context 27760 * 27761 * Set the structured error callback 27762 */ 27763void 27764xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt, 27765 xmlStructuredErrorFunc serror, void *ctx) 27766{ 27767 if (ctxt == NULL) 27768 return; 27769 ctxt->serror = serror; 27770 ctxt->error = NULL; 27771 ctxt->warning = NULL; 27772 ctxt->errCtxt = ctx; 27773 if (ctxt->pctxt != NULL) 27774 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx); 27775} 27776 27777/** 27778 * xmlSchemaGetValidErrors: 27779 * @ctxt: a XML-Schema validation context 27780 * @err: the error function result 27781 * @warn: the warning function result 27782 * @ctx: the functions context result 27783 * 27784 * Get the error and warning callback informations 27785 * 27786 * Returns -1 in case of error and 0 otherwise 27787 */ 27788int 27789xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt, 27790 xmlSchemaValidityErrorFunc * err, 27791 xmlSchemaValidityWarningFunc * warn, void **ctx) 27792{ 27793 if (ctxt == NULL) 27794 return (-1); 27795 if (err != NULL) 27796 *err = ctxt->error; 27797 if (warn != NULL) 27798 *warn = ctxt->warning; 27799 if (ctx != NULL) 27800 *ctx = ctxt->errCtxt; 27801 return (0); 27802} 27803 27804 27805/** 27806 * xmlSchemaSetValidOptions: 27807 * @ctxt: a schema validation context 27808 * @options: a combination of xmlSchemaValidOption 27809 * 27810 * Sets the options to be used during the validation. 27811 * 27812 * Returns 0 in case of success, -1 in case of an 27813 * API error. 27814 */ 27815int 27816xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt, 27817 int options) 27818 27819{ 27820 int i; 27821 27822 if (ctxt == NULL) 27823 return (-1); 27824 /* 27825 * WARNING: Change the start value if adding to the 27826 * xmlSchemaValidOption. 27827 * TODO: Is there an other, more easy to maintain, 27828 * way? 27829 */ 27830 for (i = 1; i < (int) sizeof(int) * 8; i++) { 27831 if (options & 1<<i) 27832 return (-1); 27833 } 27834 ctxt->options = options; 27835 return (0); 27836} 27837 27838/** 27839 * xmlSchemaValidCtxtGetOptions: 27840 * @ctxt: a schema validation context 27841 * 27842 * Get the validation context options. 27843 * 27844 * Returns the option combination or -1 on error. 27845 */ 27846int 27847xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt) 27848 27849{ 27850 if (ctxt == NULL) 27851 return (-1); 27852 else 27853 return (ctxt->options); 27854} 27855 27856static int 27857xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt) 27858{ 27859 xmlAttrPtr attr; 27860 int ret = 0; 27861 xmlSchemaNodeInfoPtr ielem = NULL; 27862 xmlNodePtr node, valRoot; 27863 const xmlChar *nsName; 27864 27865 /* DOC VAL TODO: Move this to the start function. */ 27866 if (vctxt->validationRoot != NULL) 27867 valRoot = vctxt->validationRoot; 27868 else 27869 valRoot = xmlDocGetRootElement(vctxt->doc); 27870 if (valRoot == NULL) { 27871 /* VAL TODO: Error code? */ 27872 VERROR(1, NULL, "The document has no document element"); 27873 return (1); 27874 } 27875 vctxt->depth = -1; 27876 vctxt->validationRoot = valRoot; 27877 node = valRoot; 27878 while (node != NULL) { 27879 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) 27880 goto next_sibling; 27881 if (node->type == XML_ELEMENT_NODE) { 27882 27883 /* 27884 * Init the node-info. 27885 */ 27886 vctxt->depth++; 27887 if (xmlSchemaValidatorPushElem(vctxt) == -1) 27888 goto internal_error; 27889 ielem = vctxt->inode; 27890 ielem->node = node; 27891 ielem->nodeLine = node->line; 27892 ielem->localName = node->name; 27893 if (node->ns != NULL) 27894 ielem->nsName = node->ns->href; 27895 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY; 27896 /* 27897 * Register attributes. 27898 * DOC VAL TODO: We do not register namespace declaration 27899 * attributes yet. 27900 */ 27901 vctxt->nbAttrInfos = 0; 27902 if (node->properties != NULL) { 27903 attr = node->properties; 27904 do { 27905 if (attr->ns != NULL) 27906 nsName = attr->ns->href; 27907 else 27908 nsName = NULL; 27909 ret = xmlSchemaValidatorPushAttribute(vctxt, 27910 (xmlNodePtr) attr, 27911 /* 27912 * Note that we give it the line number of the 27913 * parent element. 27914 */ 27915 ielem->nodeLine, 27916 attr->name, nsName, 0, 27917 xmlNodeListGetString(attr->doc, attr->children, 1), 1); 27918 if (ret == -1) { 27919 VERROR_INT("xmlSchemaDocWalk", 27920 "calling xmlSchemaValidatorPushAttribute()"); 27921 goto internal_error; 27922 } 27923 attr = attr->next; 27924 } while (attr); 27925 } 27926 /* 27927 * Validate the element. 27928 */ 27929 ret = xmlSchemaValidateElem(vctxt); 27930 if (ret != 0) { 27931 if (ret == -1) { 27932 VERROR_INT("xmlSchemaDocWalk", 27933 "calling xmlSchemaValidateElem()"); 27934 goto internal_error; 27935 } 27936 /* 27937 * Don't stop validation; just skip the content 27938 * of this element. 27939 */ 27940 goto leave_node; 27941 } 27942 if ((vctxt->skipDepth != -1) && 27943 (vctxt->depth >= vctxt->skipDepth)) 27944 goto leave_node; 27945 } else if ((node->type == XML_TEXT_NODE) || 27946 (node->type == XML_CDATA_SECTION_NODE)) { 27947 /* 27948 * Process character content. 27949 */ 27950 if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)) 27951 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; 27952 ret = xmlSchemaVPushText(vctxt, node->type, node->content, 27953 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL); 27954 if (ret < 0) { 27955 VERROR_INT("xmlSchemaVDocWalk", 27956 "calling xmlSchemaVPushText()"); 27957 goto internal_error; 27958 } 27959 /* 27960 * DOC VAL TODO: Should we skip further validation of the 27961 * element content here? 27962 */ 27963 } else if ((node->type == XML_ENTITY_NODE) || 27964 (node->type == XML_ENTITY_REF_NODE)) { 27965 /* 27966 * DOC VAL TODO: What to do with entities? 27967 */ 27968 VERROR_INT("xmlSchemaVDocWalk", 27969 "there is at least one entity reference in the node-tree " 27970 "currently being validated. Processing of entities with " 27971 "this XML Schema processor is not supported (yet). Please " 27972 "substitute entities before validation."); 27973 goto internal_error; 27974 } else { 27975 goto leave_node; 27976 /* 27977 * DOC VAL TODO: XInclude nodes, etc. 27978 */ 27979 } 27980 /* 27981 * Walk the doc. 27982 */ 27983 if (node->children != NULL) { 27984 node = node->children; 27985 continue; 27986 } 27987leave_node: 27988 if (node->type == XML_ELEMENT_NODE) { 27989 /* 27990 * Leaving the scope of an element. 27991 */ 27992 if (node != vctxt->inode->node) { 27993 VERROR_INT("xmlSchemaVDocWalk", 27994 "element position mismatch"); 27995 goto internal_error; 27996 } 27997 ret = xmlSchemaValidatorPopElem(vctxt); 27998 if (ret != 0) { 27999 if (ret < 0) { 28000 VERROR_INT("xmlSchemaVDocWalk", 28001 "calling xmlSchemaValidatorPopElem()"); 28002 goto internal_error; 28003 } 28004 } 28005 if (node == valRoot) 28006 goto exit; 28007 } 28008next_sibling: 28009 if (node->next != NULL) 28010 node = node->next; 28011 else { 28012 node = node->parent; 28013 goto leave_node; 28014 } 28015 } 28016 28017exit: 28018 return (ret); 28019internal_error: 28020 return (-1); 28021} 28022 28023static int 28024xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) { 28025 /* 28026 * Some initialization. 28027 */ 28028 vctxt->err = 0; 28029 vctxt->nberrors = 0; 28030 vctxt->depth = -1; 28031 vctxt->skipDepth = -1; 28032 vctxt->xsiAssemble = 0; 28033 vctxt->hasKeyrefs = 0; 28034#ifdef ENABLE_IDC_NODE_TABLES_TEST 28035 vctxt->createIDCNodeTables = 1; 28036#else 28037 vctxt->createIDCNodeTables = 0; 28038#endif 28039 /* 28040 * Create a schema + parser if necessary. 28041 */ 28042 if (vctxt->schema == NULL) { 28043 xmlSchemaParserCtxtPtr pctxt; 28044 28045 vctxt->xsiAssemble = 1; 28046 /* 28047 * If not schema was given then we will create a schema 28048 * dynamically using XSI schema locations. 28049 * 28050 * Create the schema parser context. 28051 */ 28052 if ((vctxt->pctxt == NULL) && 28053 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) 28054 return (-1); 28055 pctxt = vctxt->pctxt; 28056 pctxt->xsiAssemble = 1; 28057 /* 28058 * Create the schema. 28059 */ 28060 vctxt->schema = xmlSchemaNewSchema(pctxt); 28061 if (vctxt->schema == NULL) 28062 return (-1); 28063 /* 28064 * Create the schema construction context. 28065 */ 28066 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict); 28067 if (pctxt->constructor == NULL) 28068 return(-1); 28069 pctxt->constructor->mainSchema = vctxt->schema; 28070 /* 28071 * Take ownership of the constructor to be able to free it. 28072 */ 28073 pctxt->ownsConstructor = 1; 28074 } 28075 /* 28076 * Augment the IDC definitions for the main schema and all imported ones 28077 * NOTE: main schema if the first in the imported list 28078 */ 28079 xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt); 28080 28081 return(0); 28082} 28083 28084static void 28085xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) { 28086 if (vctxt->xsiAssemble) { 28087 if (vctxt->schema != NULL) { 28088 xmlSchemaFree(vctxt->schema); 28089 vctxt->schema = NULL; 28090 } 28091 } 28092 xmlSchemaClearValidCtxt(vctxt); 28093} 28094 28095static int 28096xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt) 28097{ 28098 int ret = 0; 28099 28100 if (xmlSchemaPreRun(vctxt) < 0) 28101 return(-1); 28102 28103 if (vctxt->doc != NULL) { 28104 /* 28105 * Tree validation. 28106 */ 28107 ret = xmlSchemaVDocWalk(vctxt); 28108#ifdef LIBXML_READER_ENABLED 28109 } else if (vctxt->reader != NULL) { 28110 /* 28111 * XML Reader validation. 28112 */ 28113#ifdef XML_SCHEMA_READER_ENABLED 28114 ret = xmlSchemaVReaderWalk(vctxt); 28115#endif 28116#endif 28117 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) { 28118 /* 28119 * SAX validation. 28120 */ 28121 ret = xmlParseDocument(vctxt->parserCtxt); 28122 } else { 28123 VERROR_INT("xmlSchemaVStart", 28124 "no instance to validate"); 28125 ret = -1; 28126 } 28127 28128 xmlSchemaPostRun(vctxt); 28129 if (ret == 0) 28130 ret = vctxt->err; 28131 return (ret); 28132} 28133 28134/** 28135 * xmlSchemaValidateOneElement: 28136 * @ctxt: a schema validation context 28137 * @elem: an element node 28138 * 28139 * Validate a branch of a tree, starting with the given @elem. 28140 * 28141 * Returns 0 if the element and its subtree is valid, a positive error 28142 * code number otherwise and -1 in case of an internal or API error. 28143 */ 28144int 28145xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem) 28146{ 28147 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE)) 28148 return (-1); 28149 28150 if (ctxt->schema == NULL) 28151 return (-1); 28152 28153 ctxt->doc = elem->doc; 28154 ctxt->node = elem; 28155 ctxt->validationRoot = elem; 28156 return(xmlSchemaVStart(ctxt)); 28157} 28158 28159/** 28160 * xmlSchemaValidateDoc: 28161 * @ctxt: a schema validation context 28162 * @doc: a parsed document tree 28163 * 28164 * Validate a document tree in memory. 28165 * 28166 * Returns 0 if the document is schemas valid, a positive error code 28167 * number otherwise and -1 in case of internal or API error. 28168 */ 28169int 28170xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) 28171{ 28172 if ((ctxt == NULL) || (doc == NULL)) 28173 return (-1); 28174 28175 ctxt->doc = doc; 28176 ctxt->node = xmlDocGetRootElement(doc); 28177 if (ctxt->node == NULL) { 28178 xmlSchemaCustomErr(ACTXT_CAST ctxt, 28179 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING, 28180 (xmlNodePtr) doc, NULL, 28181 "The document has no document element", NULL, NULL); 28182 return (ctxt->err); 28183 } 28184 ctxt->validationRoot = ctxt->node; 28185 return (xmlSchemaVStart(ctxt)); 28186} 28187 28188 28189/************************************************************************ 28190 * * 28191 * Function and data for SAX streaming API * 28192 * * 28193 ************************************************************************/ 28194typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData; 28195typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr; 28196 28197struct _xmlSchemaSplitSAXData { 28198 xmlSAXHandlerPtr user_sax; 28199 void *user_data; 28200 xmlSchemaValidCtxtPtr ctxt; 28201 xmlSAXHandlerPtr schemas_sax; 28202}; 28203 28204#define XML_SAX_PLUG_MAGIC 0xdc43ba21 28205 28206struct _xmlSchemaSAXPlug { 28207 unsigned int magic; 28208 28209 /* the original callbacks informations */ 28210 xmlSAXHandlerPtr *user_sax_ptr; 28211 xmlSAXHandlerPtr user_sax; 28212 void **user_data_ptr; 28213 void *user_data; 28214 28215 /* the block plugged back and validation informations */ 28216 xmlSAXHandler schemas_sax; 28217 xmlSchemaValidCtxtPtr ctxt; 28218}; 28219 28220/* All those functions just bounces to the user provided SAX handlers */ 28221static void 28222internalSubsetSplit(void *ctx, const xmlChar *name, 28223 const xmlChar *ExternalID, const xmlChar *SystemID) 28224{ 28225 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28226 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28227 (ctxt->user_sax->internalSubset != NULL)) 28228 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID, 28229 SystemID); 28230} 28231 28232static int 28233isStandaloneSplit(void *ctx) 28234{ 28235 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28236 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28237 (ctxt->user_sax->isStandalone != NULL)) 28238 return(ctxt->user_sax->isStandalone(ctxt->user_data)); 28239 return(0); 28240} 28241 28242static int 28243hasInternalSubsetSplit(void *ctx) 28244{ 28245 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28246 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28247 (ctxt->user_sax->hasInternalSubset != NULL)) 28248 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data)); 28249 return(0); 28250} 28251 28252static int 28253hasExternalSubsetSplit(void *ctx) 28254{ 28255 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28256 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28257 (ctxt->user_sax->hasExternalSubset != NULL)) 28258 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data)); 28259 return(0); 28260} 28261 28262static void 28263externalSubsetSplit(void *ctx, const xmlChar *name, 28264 const xmlChar *ExternalID, const xmlChar *SystemID) 28265{ 28266 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28267 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28268 (ctxt->user_sax->externalSubset != NULL)) 28269 ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID, 28270 SystemID); 28271} 28272 28273static xmlParserInputPtr 28274resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId) 28275{ 28276 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28277 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28278 (ctxt->user_sax->resolveEntity != NULL)) 28279 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId, 28280 systemId)); 28281 return(NULL); 28282} 28283 28284static xmlEntityPtr 28285getEntitySplit(void *ctx, const xmlChar *name) 28286{ 28287 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28288 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28289 (ctxt->user_sax->getEntity != NULL)) 28290 return(ctxt->user_sax->getEntity(ctxt->user_data, name)); 28291 return(NULL); 28292} 28293 28294static xmlEntityPtr 28295getParameterEntitySplit(void *ctx, const xmlChar *name) 28296{ 28297 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28298 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28299 (ctxt->user_sax->getParameterEntity != NULL)) 28300 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name)); 28301 return(NULL); 28302} 28303 28304 28305static void 28306entityDeclSplit(void *ctx, const xmlChar *name, int type, 28307 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) 28308{ 28309 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28310 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28311 (ctxt->user_sax->entityDecl != NULL)) 28312 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId, 28313 systemId, content); 28314} 28315 28316static void 28317attributeDeclSplit(void *ctx, const xmlChar * elem, 28318 const xmlChar * name, int type, int def, 28319 const xmlChar * defaultValue, xmlEnumerationPtr tree) 28320{ 28321 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28322 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28323 (ctxt->user_sax->attributeDecl != NULL)) { 28324 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type, 28325 def, defaultValue, tree); 28326 } else { 28327 xmlFreeEnumeration(tree); 28328 } 28329} 28330 28331static void 28332elementDeclSplit(void *ctx, const xmlChar *name, int type, 28333 xmlElementContentPtr content) 28334{ 28335 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28336 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28337 (ctxt->user_sax->elementDecl != NULL)) 28338 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content); 28339} 28340 28341static void 28342notationDeclSplit(void *ctx, const xmlChar *name, 28343 const xmlChar *publicId, const xmlChar *systemId) 28344{ 28345 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28346 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28347 (ctxt->user_sax->notationDecl != NULL)) 28348 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId, 28349 systemId); 28350} 28351 28352static void 28353unparsedEntityDeclSplit(void *ctx, const xmlChar *name, 28354 const xmlChar *publicId, const xmlChar *systemId, 28355 const xmlChar *notationName) 28356{ 28357 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28358 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28359 (ctxt->user_sax->unparsedEntityDecl != NULL)) 28360 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId, 28361 systemId, notationName); 28362} 28363 28364static void 28365setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc) 28366{ 28367 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28368 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28369 (ctxt->user_sax->setDocumentLocator != NULL)) 28370 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc); 28371} 28372 28373static void 28374startDocumentSplit(void *ctx) 28375{ 28376 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28377 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28378 (ctxt->user_sax->startDocument != NULL)) 28379 ctxt->user_sax->startDocument(ctxt->user_data); 28380} 28381 28382static void 28383endDocumentSplit(void *ctx) 28384{ 28385 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28386 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28387 (ctxt->user_sax->endDocument != NULL)) 28388 ctxt->user_sax->endDocument(ctxt->user_data); 28389} 28390 28391static void 28392processingInstructionSplit(void *ctx, const xmlChar *target, 28393 const xmlChar *data) 28394{ 28395 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28396 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28397 (ctxt->user_sax->processingInstruction != NULL)) 28398 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data); 28399} 28400 28401static void 28402commentSplit(void *ctx, const xmlChar *value) 28403{ 28404 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28405 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28406 (ctxt->user_sax->comment != NULL)) 28407 ctxt->user_sax->comment(ctxt->user_data, value); 28408} 28409 28410/* 28411 * Varargs error callbacks to the user application, harder ... 28412 */ 28413 28414static void XMLCDECL 28415warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { 28416 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28417 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28418 (ctxt->user_sax->warning != NULL)) { 28419 TODO 28420 } 28421} 28422static void XMLCDECL 28423errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { 28424 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28425 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28426 (ctxt->user_sax->error != NULL)) { 28427 TODO 28428 } 28429} 28430static void XMLCDECL 28431fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { 28432 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28433 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28434 (ctxt->user_sax->fatalError != NULL)) { 28435 TODO 28436 } 28437} 28438 28439/* 28440 * Those are function where both the user handler and the schemas handler 28441 * need to be called. 28442 */ 28443static void 28444charactersSplit(void *ctx, const xmlChar *ch, int len) 28445{ 28446 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28447 if (ctxt == NULL) 28448 return; 28449 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL)) 28450 ctxt->user_sax->characters(ctxt->user_data, ch, len); 28451 if (ctxt->ctxt != NULL) 28452 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len); 28453} 28454 28455static void 28456ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len) 28457{ 28458 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28459 if (ctxt == NULL) 28460 return; 28461 if ((ctxt->user_sax != NULL) && 28462 (ctxt->user_sax->ignorableWhitespace != NULL)) 28463 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len); 28464 if (ctxt->ctxt != NULL) 28465 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len); 28466} 28467 28468static void 28469cdataBlockSplit(void *ctx, const xmlChar *value, int len) 28470{ 28471 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28472 if (ctxt == NULL) 28473 return; 28474 if ((ctxt->user_sax != NULL) && 28475 (ctxt->user_sax->cdataBlock != NULL)) 28476 ctxt->user_sax->cdataBlock(ctxt->user_data, value, len); 28477 if (ctxt->ctxt != NULL) 28478 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len); 28479} 28480 28481static void 28482referenceSplit(void *ctx, const xmlChar *name) 28483{ 28484 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28485 if (ctxt == NULL) 28486 return; 28487 if ((ctxt != NULL) && (ctxt->user_sax != NULL) && 28488 (ctxt->user_sax->reference != NULL)) 28489 ctxt->user_sax->reference(ctxt->user_data, name); 28490 if (ctxt->ctxt != NULL) 28491 xmlSchemaSAXHandleReference(ctxt->user_data, name); 28492} 28493 28494static void 28495startElementNsSplit(void *ctx, const xmlChar * localname, 28496 const xmlChar * prefix, const xmlChar * URI, 28497 int nb_namespaces, const xmlChar ** namespaces, 28498 int nb_attributes, int nb_defaulted, 28499 const xmlChar ** attributes) { 28500 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28501 if (ctxt == NULL) 28502 return; 28503 if ((ctxt->user_sax != NULL) && 28504 (ctxt->user_sax->startElementNs != NULL)) 28505 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix, 28506 URI, nb_namespaces, namespaces, 28507 nb_attributes, nb_defaulted, 28508 attributes); 28509 if (ctxt->ctxt != NULL) 28510 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix, 28511 URI, nb_namespaces, namespaces, 28512 nb_attributes, nb_defaulted, 28513 attributes); 28514} 28515 28516static void 28517endElementNsSplit(void *ctx, const xmlChar * localname, 28518 const xmlChar * prefix, const xmlChar * URI) { 28519 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; 28520 if (ctxt == NULL) 28521 return; 28522 if ((ctxt->user_sax != NULL) && 28523 (ctxt->user_sax->endElementNs != NULL)) 28524 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI); 28525 if (ctxt->ctxt != NULL) 28526 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI); 28527} 28528 28529/** 28530 * xmlSchemaSAXPlug: 28531 * @ctxt: a schema validation context 28532 * @sax: a pointer to the original xmlSAXHandlerPtr 28533 * @user_data: a pointer to the original SAX user data pointer 28534 * 28535 * Plug a SAX based validation layer in a SAX parsing event flow. 28536 * The original @saxptr and @dataptr data are replaced by new pointers 28537 * but the calls to the original will be maintained. 28538 * 28539 * Returns a pointer to a data structure needed to unplug the validation layer 28540 * or NULL in case of errors. 28541 */ 28542xmlSchemaSAXPlugPtr 28543xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt, 28544 xmlSAXHandlerPtr *sax, void **user_data) 28545{ 28546 xmlSchemaSAXPlugPtr ret; 28547 xmlSAXHandlerPtr old_sax; 28548 28549 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL)) 28550 return(NULL); 28551 28552 /* 28553 * We only allow to plug into SAX2 event streams 28554 */ 28555 old_sax = *sax; 28556 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC)) 28557 return(NULL); 28558 if ((old_sax != NULL) && 28559 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) && 28560 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL))) 28561 return(NULL); 28562 28563 /* 28564 * everything seems right allocate the local data needed for that layer 28565 */ 28566 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct)); 28567 if (ret == NULL) { 28568 return(NULL); 28569 } 28570 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct)); 28571 ret->magic = XML_SAX_PLUG_MAGIC; 28572 ret->schemas_sax.initialized = XML_SAX2_MAGIC; 28573 ret->ctxt = ctxt; 28574 ret->user_sax_ptr = sax; 28575 ret->user_sax = old_sax; 28576 if (old_sax == NULL) { 28577 /* 28578 * go direct, no need for the split block and functions. 28579 */ 28580 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs; 28581 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs; 28582 /* 28583 * Note that we use the same text-function for both, to prevent 28584 * the parser from testing for ignorable whitespace. 28585 */ 28586 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText; 28587 ret->schemas_sax.characters = xmlSchemaSAXHandleText; 28588 28589 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection; 28590 ret->schemas_sax.reference = xmlSchemaSAXHandleReference; 28591 28592 ret->user_data = ctxt; 28593 *user_data = ctxt; 28594 } else { 28595 /* 28596 * for each callback unused by Schemas initialize it to the Split 28597 * routine only if non NULL in the user block, this can speed up 28598 * things at the SAX level. 28599 */ 28600 if (old_sax->internalSubset != NULL) 28601 ret->schemas_sax.internalSubset = internalSubsetSplit; 28602 if (old_sax->isStandalone != NULL) 28603 ret->schemas_sax.isStandalone = isStandaloneSplit; 28604 if (old_sax->hasInternalSubset != NULL) 28605 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit; 28606 if (old_sax->hasExternalSubset != NULL) 28607 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit; 28608 if (old_sax->resolveEntity != NULL) 28609 ret->schemas_sax.resolveEntity = resolveEntitySplit; 28610 if (old_sax->getEntity != NULL) 28611 ret->schemas_sax.getEntity = getEntitySplit; 28612 if (old_sax->entityDecl != NULL) 28613 ret->schemas_sax.entityDecl = entityDeclSplit; 28614 if (old_sax->notationDecl != NULL) 28615 ret->schemas_sax.notationDecl = notationDeclSplit; 28616 if (old_sax->attributeDecl != NULL) 28617 ret->schemas_sax.attributeDecl = attributeDeclSplit; 28618 if (old_sax->elementDecl != NULL) 28619 ret->schemas_sax.elementDecl = elementDeclSplit; 28620 if (old_sax->unparsedEntityDecl != NULL) 28621 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit; 28622 if (old_sax->setDocumentLocator != NULL) 28623 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit; 28624 if (old_sax->startDocument != NULL) 28625 ret->schemas_sax.startDocument = startDocumentSplit; 28626 if (old_sax->endDocument != NULL) 28627 ret->schemas_sax.endDocument = endDocumentSplit; 28628 if (old_sax->processingInstruction != NULL) 28629 ret->schemas_sax.processingInstruction = processingInstructionSplit; 28630 if (old_sax->comment != NULL) 28631 ret->schemas_sax.comment = commentSplit; 28632 if (old_sax->warning != NULL) 28633 ret->schemas_sax.warning = warningSplit; 28634 if (old_sax->error != NULL) 28635 ret->schemas_sax.error = errorSplit; 28636 if (old_sax->fatalError != NULL) 28637 ret->schemas_sax.fatalError = fatalErrorSplit; 28638 if (old_sax->getParameterEntity != NULL) 28639 ret->schemas_sax.getParameterEntity = getParameterEntitySplit; 28640 if (old_sax->externalSubset != NULL) 28641 ret->schemas_sax.externalSubset = externalSubsetSplit; 28642 28643 /* 28644 * the 6 schemas callback have to go to the splitter functions 28645 * Note that we use the same text-function for ignorableWhitespace 28646 * if possible, to prevent the parser from testing for ignorable 28647 * whitespace. 28648 */ 28649 ret->schemas_sax.characters = charactersSplit; 28650 if ((old_sax->ignorableWhitespace != NULL) && 28651 (old_sax->ignorableWhitespace != old_sax->characters)) 28652 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit; 28653 else 28654 ret->schemas_sax.ignorableWhitespace = charactersSplit; 28655 ret->schemas_sax.cdataBlock = cdataBlockSplit; 28656 ret->schemas_sax.reference = referenceSplit; 28657 ret->schemas_sax.startElementNs = startElementNsSplit; 28658 ret->schemas_sax.endElementNs = endElementNsSplit; 28659 28660 ret->user_data_ptr = user_data; 28661 ret->user_data = *user_data; 28662 *user_data = ret; 28663 } 28664 28665 /* 28666 * plug the pointers back. 28667 */ 28668 *sax = &(ret->schemas_sax); 28669 ctxt->sax = *sax; 28670 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM; 28671 xmlSchemaPreRun(ctxt); 28672 return(ret); 28673} 28674 28675/** 28676 * xmlSchemaSAXUnplug: 28677 * @plug: a data structure returned by xmlSchemaSAXPlug 28678 * 28679 * Unplug a SAX based validation layer in a SAX parsing event flow. 28680 * The original pointers used in the call are restored. 28681 * 28682 * Returns 0 in case of success and -1 in case of failure. 28683 */ 28684int 28685xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug) 28686{ 28687 xmlSAXHandlerPtr *sax; 28688 void **user_data; 28689 28690 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC)) 28691 return(-1); 28692 plug->magic = 0; 28693 28694 xmlSchemaPostRun(plug->ctxt); 28695 /* restore the data */ 28696 sax = plug->user_sax_ptr; 28697 *sax = plug->user_sax; 28698 if (plug->user_sax != NULL) { 28699 user_data = plug->user_data_ptr; 28700 *user_data = plug->user_data; 28701 } 28702 28703 /* free and return */ 28704 xmlFree(plug); 28705 return(0); 28706} 28707 28708/** 28709 * xmlSchemaValidateSetLocator: 28710 * @vctxt: a schema validation context 28711 * @f: the locator function pointer 28712 * @ctxt: the locator context 28713 * 28714 * Allows to set a locator function to the validation context, 28715 * which will be used to provide file and line information since 28716 * those are not provided as part of the SAX validation flow 28717 * Setting @f to NULL disable the locator. 28718 */ 28719 28720void 28721xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt, 28722 xmlSchemaValidityLocatorFunc f, 28723 void *ctxt) 28724{ 28725 if (vctxt == NULL) return; 28726 vctxt->locFunc = f; 28727 vctxt->locCtxt = ctxt; 28728} 28729 28730/** 28731 * xmlSchemaValidateStreamLocator: 28732 * @ctx: the xmlTextReaderPtr used 28733 * @file: returned file information 28734 * @line: returned line information 28735 * 28736 * Internal locator function for the readers 28737 * 28738 * Returns 0 in case the Schema validation could be (des)activated and 28739 * -1 in case of error. 28740 */ 28741static int 28742xmlSchemaValidateStreamLocator(void *ctx, const char **file, 28743 unsigned long *line) { 28744 xmlParserCtxtPtr ctxt; 28745 28746 if ((ctx == NULL) || ((file == NULL) && (line == NULL))) 28747 return(-1); 28748 28749 if (file != NULL) 28750 *file = NULL; 28751 if (line != NULL) 28752 *line = 0; 28753 28754 ctxt = (xmlParserCtxtPtr) ctx; 28755 if (ctxt->input != NULL) { 28756 if (file != NULL) 28757 *file = ctxt->input->filename; 28758 if (line != NULL) 28759 *line = ctxt->input->line; 28760 return(0); 28761 } 28762 return(-1); 28763} 28764 28765/** 28766 * xmlSchemaValidateStream: 28767 * @ctxt: a schema validation context 28768 * @input: the input to use for reading the data 28769 * @enc: an optional encoding information 28770 * @sax: a SAX handler for the resulting events 28771 * @user_data: the context to provide to the SAX handler. 28772 * 28773 * Validate an input based on a flow of SAX event from the parser 28774 * and forward the events to the @sax handler with the provided @user_data 28775 * the user provided @sax handler must be a SAX2 one. 28776 * 28777 * Returns 0 if the document is schemas valid, a positive error code 28778 * number otherwise and -1 in case of internal or API error. 28779 */ 28780int 28781xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt, 28782 xmlParserInputBufferPtr input, xmlCharEncoding enc, 28783 xmlSAXHandlerPtr sax, void *user_data) 28784{ 28785 xmlSchemaSAXPlugPtr plug = NULL; 28786 xmlSAXHandlerPtr old_sax = NULL; 28787 xmlParserCtxtPtr pctxt = NULL; 28788 xmlParserInputPtr inputStream = NULL; 28789 int ret; 28790 28791 if ((ctxt == NULL) || (input == NULL)) 28792 return (-1); 28793 28794 /* 28795 * prepare the parser 28796 */ 28797 pctxt = xmlNewParserCtxt(); 28798 if (pctxt == NULL) 28799 return (-1); 28800 old_sax = pctxt->sax; 28801 pctxt->sax = sax; 28802 pctxt->userData = user_data; 28803#if 0 28804 if (options) 28805 xmlCtxtUseOptions(pctxt, options); 28806#endif 28807 pctxt->linenumbers = 1; 28808 xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt); 28809 28810 inputStream = xmlNewIOInputStream(pctxt, input, enc);; 28811 if (inputStream == NULL) { 28812 ret = -1; 28813 goto done; 28814 } 28815 inputPush(pctxt, inputStream); 28816 ctxt->parserCtxt = pctxt; 28817 ctxt->input = input; 28818 28819 /* 28820 * Plug the validation and launch the parsing 28821 */ 28822 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData)); 28823 if (plug == NULL) { 28824 ret = -1; 28825 goto done; 28826 } 28827 ctxt->input = input; 28828 ctxt->enc = enc; 28829 ctxt->sax = pctxt->sax; 28830 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM; 28831 ret = xmlSchemaVStart(ctxt); 28832 28833 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) { 28834 ret = ctxt->parserCtxt->errNo; 28835 if (ret == 0) 28836 ret = 1; 28837 } 28838 28839done: 28840 ctxt->parserCtxt = NULL; 28841 ctxt->sax = NULL; 28842 ctxt->input = NULL; 28843 if (plug != NULL) { 28844 xmlSchemaSAXUnplug(plug); 28845 } 28846 /* cleanup */ 28847 if (pctxt != NULL) { 28848 pctxt->sax = old_sax; 28849 xmlFreeParserCtxt(pctxt); 28850 } 28851 return (ret); 28852} 28853 28854/** 28855 * xmlSchemaValidateFile: 28856 * @ctxt: a schema validation context 28857 * @filename: the URI of the instance 28858 * @options: a future set of options, currently unused 28859 * 28860 * Do a schemas validation of the given resource, it will use the 28861 * SAX streamable validation internally. 28862 * 28863 * Returns 0 if the document is valid, a positive error code 28864 * number otherwise and -1 in case of an internal or API error. 28865 */ 28866int 28867xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt, 28868 const char * filename, 28869 int options ATTRIBUTE_UNUSED) 28870{ 28871 int ret; 28872 xmlParserInputBufferPtr input; 28873 28874 if ((ctxt == NULL) || (filename == NULL)) 28875 return (-1); 28876 28877 input = xmlParserInputBufferCreateFilename(filename, 28878 XML_CHAR_ENCODING_NONE); 28879 if (input == NULL) 28880 return (-1); 28881 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE, 28882 NULL, NULL); 28883 return (ret); 28884} 28885 28886/** 28887 * xmlSchemaValidCtxtGetParserCtxt: 28888 * @ctxt: a schema validation context 28889 * 28890 * allow access to the parser context of the schema validation context 28891 * 28892 * Returns the parser context of the schema validation context or NULL 28893 * in case of error. 28894 */ 28895xmlParserCtxtPtr 28896xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt) 28897{ 28898 if (ctxt == NULL) 28899 return(NULL); 28900 return (ctxt->parserCtxt); 28901} 28902 28903#define bottom_xmlschemas 28904#include "elfgcchack.h" 28905#endif /* LIBXML_SCHEMAS_ENABLED */ 28906