1 //------------------------------------------------------------------------------ 2 // <copyright file="Compiler.cs" company="Microsoft"> 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // </copyright> 5 // <owner current="true" primary="true">Microsoft</owner> 6 //------------------------------------------------------------------------------ 7 8 namespace System.Xml.Schema { 9 10 using System; 11 using System.Collections; 12 using System.Globalization; 13 using System.Text; 14 using System.Diagnostics; 15 16 internal sealed class Compiler : BaseProcessor { 17 string restrictionErrorMsg; 18 XmlSchemaObjectTable attributes = new XmlSchemaObjectTable(); 19 XmlSchemaObjectTable attributeGroups = new XmlSchemaObjectTable(); 20 XmlSchemaObjectTable elements = new XmlSchemaObjectTable(); 21 XmlSchemaObjectTable schemaTypes = new XmlSchemaObjectTable(); 22 XmlSchemaObjectTable groups = new XmlSchemaObjectTable(); 23 XmlSchemaObjectTable notations = new XmlSchemaObjectTable(); 24 XmlSchemaObjectTable examplars = new XmlSchemaObjectTable(); 25 XmlSchemaObjectTable identityConstraints = new XmlSchemaObjectTable(); 26 Stack complexTypeStack = new Stack(); 27 Hashtable schemasToCompile = new Hashtable(); 28 Hashtable importedSchemas = new Hashtable(); 29 30 XmlSchema schemaForSchema; 31 Compiler(XmlNameTable nameTable, ValidationEventHandler eventHandler, XmlSchema schemaForSchema, XmlSchemaCompilationSettings compilationSettings)32 public Compiler(XmlNameTable nameTable, ValidationEventHandler eventHandler, XmlSchema schemaForSchema, XmlSchemaCompilationSettings compilationSettings) : base(nameTable, null, eventHandler, compilationSettings) { 33 this.schemaForSchema = schemaForSchema; 34 } 35 Execute(XmlSchemaSet schemaSet, SchemaInfo schemaCompiledInfo)36 public bool Execute(XmlSchemaSet schemaSet, SchemaInfo schemaCompiledInfo) { 37 Compile(); 38 if (!HasErrors) { 39 Output(schemaCompiledInfo); 40 schemaSet.elements = elements; 41 schemaSet.attributes = attributes; 42 schemaSet.schemaTypes = schemaTypes; 43 schemaSet.substitutionGroups = examplars; 44 } 45 return !HasErrors; 46 } 47 Prepare(XmlSchema schema, bool cleanup)48 internal void Prepare(XmlSchema schema, bool cleanup) { 49 if (schemasToCompile[schema] != null) { 50 return; 51 } 52 schemasToCompile.Add(schema, schema); 53 foreach (XmlSchemaElement element in schema.Elements.Values) { 54 if (cleanup) { 55 CleanupElement(element); 56 } 57 AddToTable(elements, element.QualifiedName, element); 58 } 59 foreach (XmlSchemaAttribute attribute in schema.Attributes.Values) { 60 if (cleanup) { 61 CleanupAttribute(attribute); 62 } 63 AddToTable(attributes, attribute.QualifiedName, attribute); 64 } 65 foreach (XmlSchemaGroup group in schema.Groups.Values) { 66 if (cleanup) { 67 CleanupGroup(group); 68 } 69 AddToTable(groups, group.QualifiedName, group); 70 } 71 foreach (XmlSchemaAttributeGroup attributeGroup in schema.AttributeGroups.Values) { 72 if (cleanup) { 73 CleanupAttributeGroup(attributeGroup); 74 } 75 AddToTable(attributeGroups, attributeGroup.QualifiedName, attributeGroup); 76 } 77 foreach (XmlSchemaType type in schema.SchemaTypes.Values) { 78 if (cleanup) { 79 XmlSchemaComplexType ct = type as XmlSchemaComplexType; 80 if (ct != null) { 81 CleanupComplexType(ct); 82 } 83 else { 84 CleanupSimpleType(type as XmlSchemaSimpleType); 85 } 86 } 87 AddToTable(schemaTypes, type.QualifiedName, type); 88 } 89 foreach (XmlSchemaNotation notation in schema.Notations.Values) { 90 AddToTable(notations, notation.QualifiedName, notation); 91 } 92 foreach (XmlSchemaIdentityConstraint ic in schema.IdentityConstraints.Values) { 93 AddToTable(identityConstraints, ic.QualifiedName, ic); 94 } 95 } 96 UpdateSForSSimpleTypes()97 private void UpdateSForSSimpleTypes() { 98 Debug.Assert(schemaForSchema != null); 99 XmlSchemaSimpleType[] schemaSimpleTypes = DatatypeImplementation.GetBuiltInTypes(); 100 XmlSchemaSimpleType builtInType; 101 //Using enumToTypeCode array; indexed by XmlTypeCode; Start indexing from 12 since schema types start there and iterate till Length - 2 as the last 2 are xquery types 102 int numberOfSchemaTypes = schemaSimpleTypes.Length - 3; //skip last 2 xquery types 103 for (int i = 12; i < numberOfSchemaTypes; i++) { 104 builtInType = schemaSimpleTypes[i]; 105 schemaForSchema.SchemaTypes.Replace(builtInType.QualifiedName, builtInType); 106 this.schemaTypes.Replace(builtInType.QualifiedName, builtInType); 107 } 108 } 109 Output(SchemaInfo schemaInfo)110 private void Output(SchemaInfo schemaInfo) { 111 string tns; 112 foreach(XmlSchema schema in schemasToCompile.Values) { 113 tns = schema.TargetNamespace; 114 if (tns == null) { 115 tns = string.Empty; 116 } 117 schemaInfo.TargetNamespaces[tns] = true; 118 } 119 foreach (XmlSchemaElement element in elements.Values) { 120 schemaInfo.ElementDecls.Add(element.QualifiedName, element.ElementDecl); 121 } 122 foreach (XmlSchemaAttribute attribute in attributes.Values) { 123 schemaInfo.AttributeDecls.Add(attribute.QualifiedName, attribute.AttDef); 124 } 125 foreach (XmlSchemaType type in schemaTypes.Values) { 126 schemaInfo.ElementDeclsByType.Add(type.QualifiedName, type.ElementDecl); 127 } 128 foreach (XmlSchemaNotation notation in notations.Values) { 129 SchemaNotation no = new SchemaNotation(notation.QualifiedName); 130 no.SystemLiteral = notation.System; 131 no.Pubid = notation.Public; 132 if (!schemaInfo.Notations.ContainsKey(no.Name.Name)) { 133 schemaInfo.Notations.Add(no.Name.Name, no); 134 } 135 } 136 137 } 138 ImportAllCompiledSchemas(XmlSchemaSet schemaSet)139 internal void ImportAllCompiledSchemas(XmlSchemaSet schemaSet) { 140 XmlSchema currentSchema; 141 int schemaIndex; 142 SortedList schemas = schemaSet.SortedSchemas; 143 for (schemaIndex = 0; schemaIndex < schemas.Count; schemaIndex++) { 144 currentSchema = (XmlSchema)schemas.GetByIndex(schemaIndex); 145 if (currentSchema.IsCompiledBySet) { //Import already compiled schemas 146 Prepare(currentSchema, false); 147 } 148 } 149 } 150 Compile()151 internal bool Compile() { 152 schemaTypes.Insert(DatatypeImplementation.QnAnyType, XmlSchemaComplexType.AnyType); 153 if (schemaForSchema != null) { //Get our built-in types 154 schemaForSchema.SchemaTypes.Replace(DatatypeImplementation.QnAnyType, XmlSchemaComplexType.AnyType); 155 UpdateSForSSimpleTypes(); 156 } 157 158 foreach(XmlSchemaGroup group in groups.Values) { 159 CompileGroup(group); 160 } 161 foreach(XmlSchemaAttributeGroup attributeGroup in attributeGroups.Values) { 162 CompileAttributeGroup(attributeGroup); 163 } 164 foreach (XmlSchemaType type in schemaTypes.Values) { 165 XmlSchemaComplexType ct = type as XmlSchemaComplexType; 166 if (ct != null) { 167 CompileComplexType(ct); 168 } 169 else { 170 CompileSimpleType((XmlSchemaSimpleType)type); 171 } 172 } 173 foreach (XmlSchemaElement element in elements.Values) { 174 if (element.ElementDecl == null) { 175 CompileElement(element); 176 } 177 } 178 foreach (XmlSchemaAttribute attribute in attributes.Values) { 179 if (attribute.AttDef == null) { 180 CompileAttribute(attribute); 181 } 182 } 183 foreach (XmlSchemaIdentityConstraint identityConstraint in identityConstraints.Values) { 184 if (identityConstraint.CompiledConstraint == null) { 185 CompileIdentityConstraint(identityConstraint); 186 } 187 } 188 while (this.complexTypeStack.Count > 0) { 189 XmlSchemaComplexType type = (XmlSchemaComplexType)complexTypeStack.Pop(); 190 CompileComplexTypeElements(type); 191 } 192 193 ProcessSubstitutionGroups(); 194 195 foreach (XmlSchemaType type in schemaTypes.Values) { 196 XmlSchemaComplexType localType = type as XmlSchemaComplexType; 197 if (localType != null) { 198 CheckParticleDerivation(localType); 199 } 200 } 201 202 foreach (XmlSchemaElement element in elements.Values) { 203 XmlSchemaComplexType localComplexType = element.ElementSchemaType as XmlSchemaComplexType; 204 if (localComplexType != null && element.SchemaTypeName == XmlQualifiedName.Empty) { // only local schemaTypes 205 CheckParticleDerivation(localComplexType); 206 } 207 } 208 foreach (XmlSchemaGroup group in groups.Values) { //Check particle derivation for redefined groups 209 XmlSchemaGroup baseGroup = group.Redefined; 210 if (baseGroup != null) { 211 RecursivelyCheckRedefinedGroups(group, baseGroup); 212 } 213 } 214 215 foreach (XmlSchemaAttributeGroup attributeGroup in attributeGroups.Values) { 216 XmlSchemaAttributeGroup baseAttributeGroup = attributeGroup.Redefined; 217 if (baseAttributeGroup != null) { 218 RecursivelyCheckRedefinedAttributeGroups(attributeGroup, baseAttributeGroup); 219 } 220 } 221 return !HasErrors; 222 } 223 CleanupAttribute(XmlSchemaAttribute attribute)224 private void CleanupAttribute(XmlSchemaAttribute attribute) { 225 if (attribute.SchemaType != null) { 226 CleanupSimpleType((XmlSchemaSimpleType)attribute.SchemaType); 227 } 228 attribute.AttDef = null; 229 } 230 CleanupAttributeGroup(XmlSchemaAttributeGroup attributeGroup)231 private void CleanupAttributeGroup(XmlSchemaAttributeGroup attributeGroup) { 232 CleanupAttributes(attributeGroup.Attributes); 233 attributeGroup.AttributeUses.Clear(); 234 attributeGroup.AttributeWildcard = null; 235 if (attributeGroup.Redefined != null) { 236 CleanupAttributeGroup(attributeGroup.Redefined); 237 } 238 } 239 CleanupComplexType(XmlSchemaComplexType complexType)240 private void CleanupComplexType(XmlSchemaComplexType complexType) { 241 if (complexType.QualifiedName == DatatypeImplementation.QnAnyType) { //if it is built-in anyType dont clean it. 242 return; 243 } 244 if (complexType.ContentModel != null) { //simpleContent or complexContent 245 if (complexType.ContentModel is XmlSchemaSimpleContent) { 246 XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent)complexType.ContentModel; 247 if (simpleContent.Content is XmlSchemaSimpleContentExtension) { 248 XmlSchemaSimpleContentExtension simpleExtension = (XmlSchemaSimpleContentExtension)simpleContent.Content; 249 CleanupAttributes(simpleExtension.Attributes); 250 } 251 else { //simpleContent.Content is XmlSchemaSimpleContentRestriction 252 XmlSchemaSimpleContentRestriction simpleRestriction = (XmlSchemaSimpleContentRestriction)simpleContent.Content; 253 CleanupAttributes(simpleRestriction.Attributes); 254 } 255 } 256 else { // complexType.ContentModel is XmlSchemaComplexContent 257 XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complexType.ContentModel; 258 if (complexContent.Content is XmlSchemaComplexContentExtension) { 259 XmlSchemaComplexContentExtension complexExtension = (XmlSchemaComplexContentExtension)complexContent.Content; 260 CleanupParticle(complexExtension.Particle); 261 CleanupAttributes(complexExtension.Attributes); 262 263 } 264 else { //XmlSchemaComplexContentRestriction 265 XmlSchemaComplexContentRestriction complexRestriction = (XmlSchemaComplexContentRestriction)complexContent.Content; 266 CleanupParticle(complexRestriction.Particle); 267 CleanupAttributes(complexRestriction.Attributes); 268 } 269 } 270 } 271 else { //equals XmlSchemaComplexContent with baseType is anyType 272 CleanupParticle(complexType.Particle); 273 CleanupAttributes(complexType.Attributes); 274 } 275 complexType.LocalElements.Clear(); 276 complexType.AttributeUses.Clear(); 277 complexType.SetAttributeWildcard(null); 278 complexType.SetContentTypeParticle(XmlSchemaParticle.Empty); 279 complexType.ElementDecl = null; 280 complexType.HasWildCard = false; 281 282 //Clean up the original type if this is a redefined type 283 if (complexType.Redefined != null) { 284 CleanupComplexType(complexType.Redefined as XmlSchemaComplexType); 285 } 286 } 287 CleanupSimpleType(XmlSchemaSimpleType simpleType)288 private void CleanupSimpleType(XmlSchemaSimpleType simpleType) { 289 if (simpleType == XmlSchemaType.GetBuiltInSimpleType(simpleType.TypeCode)) { //If it is a built-in simple type dont clean up 290 return; 291 } 292 simpleType.ElementDecl = null; 293 //Clean up the original group if this is a redefined group 294 if (simpleType.Redefined != null) { 295 CleanupSimpleType(simpleType.Redefined as XmlSchemaSimpleType); 296 } 297 } 298 CleanupElement(XmlSchemaElement element)299 private void CleanupElement(XmlSchemaElement element) { 300 if (element.SchemaType != null) { 301 XmlSchemaComplexType complexType = element.SchemaType as XmlSchemaComplexType; 302 if (complexType != null) { 303 CleanupComplexType(complexType); 304 } 305 else { 306 CleanupSimpleType((XmlSchemaSimpleType)element.SchemaType); 307 } 308 } 309 for (int i = 0; i < element.Constraints.Count; ++i) { 310 ((XmlSchemaIdentityConstraint)element.Constraints[i]).CompiledConstraint = null; 311 } 312 element.ElementDecl = null; 313 element.IsLocalTypeDerivationChecked = false; //clear Local element type derivation check 314 } 315 CleanupAttributes(XmlSchemaObjectCollection attributes)316 private void CleanupAttributes(XmlSchemaObjectCollection attributes) { 317 for (int i = 0; i < attributes.Count; ++i) { 318 XmlSchemaAttribute attribute = attributes[i] as XmlSchemaAttribute; 319 if (attribute != null) { 320 CleanupAttribute(attribute); 321 } 322 } 323 } 324 CleanupGroup(XmlSchemaGroup group)325 private void CleanupGroup(XmlSchemaGroup group) { 326 CleanupParticle(group.Particle); 327 group.CanonicalParticle = null; 328 //Clean up the original group if this is a redefined group 329 if (group.Redefined != null) { 330 CleanupGroup(group.Redefined); 331 } 332 } 333 CleanupParticle(XmlSchemaParticle particle)334 private void CleanupParticle(XmlSchemaParticle particle) { 335 XmlSchemaElement element = particle as XmlSchemaElement; 336 if (element != null) { 337 CleanupElement(element); 338 return; 339 } 340 341 XmlSchemaGroupBase groupBase = particle as XmlSchemaGroupBase; 342 if (groupBase != null) { 343 for (int i = 0; i < groupBase.Items.Count; ++i) { 344 CleanupParticle((XmlSchemaParticle)groupBase.Items[i]); 345 } 346 } 347 } 348 ProcessSubstitutionGroups()349 private void ProcessSubstitutionGroups() { 350 foreach (XmlSchemaElement element in this.elements.Values) { 351 if (!element.SubstitutionGroup.IsEmpty) { 352 XmlSchemaElement headElement = this.elements[element.SubstitutionGroup] as XmlSchemaElement; 353 if (headElement == null) { 354 SendValidationEvent(Res.Sch_NoExamplar, element); 355 continue; 356 } 357 //Check derivation of member's type against head's type 358 if (!XmlSchemaType.IsDerivedFrom(element.ElementSchemaType, headElement.ElementSchemaType, headElement.FinalResolved)) { 359 SendValidationEvent(Res.Sch_InvalidSubstitutionMember, (element.QualifiedName).ToString(), (headElement.QualifiedName).ToString(), element); 360 } 361 362 //Create substitutionGroup 363 XmlSchemaSubstitutionGroup substitutionGroup = (XmlSchemaSubstitutionGroup)this.examplars[element.SubstitutionGroup]; 364 if (substitutionGroup == null) { 365 substitutionGroup = new XmlSchemaSubstitutionGroup(); 366 substitutionGroup.Examplar = element.SubstitutionGroup; 367 examplars.Add(element.SubstitutionGroup, substitutionGroup); 368 } 369 ArrayList members = substitutionGroup.Members; 370 if (!members.Contains(element)) { //Members might contain element if the same schema is included and imported through different paths. Imp, hence will be added to set directly 371 members.Add(element); 372 } 373 } 374 } 375 376 //Check the subst groups that we just built 377 foreach (XmlSchemaSubstitutionGroup substitutionGroup in examplars.Values) { 378 CompileSubstitutionGroup(substitutionGroup); 379 } 380 } 381 CompileSubstitutionGroup(XmlSchemaSubstitutionGroup substitutionGroup)382 private void CompileSubstitutionGroup(XmlSchemaSubstitutionGroup substitutionGroup) { 383 if (substitutionGroup.IsProcessing && substitutionGroup.Members.Count > 0) { 384 SendValidationEvent(Res.Sch_SubstitutionCircularRef, (XmlSchemaElement)substitutionGroup.Members[0]); 385 return; 386 } 387 XmlSchemaElement examplar = (XmlSchemaElement)elements[substitutionGroup.Examplar]; 388 Debug.Assert(examplar != null); //Headelement presence is checked while building subst groups 389 if (substitutionGroup.Members.Contains(examplar)) {// already checked 390 return; 391 } 392 substitutionGroup.IsProcessing = true; 393 try { 394 if (examplar.FinalResolved == XmlSchemaDerivationMethod.All) { 395 SendValidationEvent(Res.Sch_InvalidExamplar, examplar); 396 } 397 //Build transitive members 398 ArrayList newMembers = null; 399 for (int i = 0; i < substitutionGroup.Members.Count; ++i) { 400 XmlSchemaElement element = (XmlSchemaElement)substitutionGroup.Members[i]; 401 //Chain to other head's that are members of this head's substGroup 402 if ((element.ElementDecl.Block & XmlSchemaDerivationMethod.Substitution) == 0) { //Chain only if substitution is not blocked 403 XmlSchemaSubstitutionGroup g = (XmlSchemaSubstitutionGroup)examplars[element.QualifiedName]; 404 if (g != null) { 405 CompileSubstitutionGroup(g); 406 for (int j = 0; j < g.Members.Count; ++j) { 407 if (g.Members[j] != element) { //Exclude the head 408 if (newMembers == null) { 409 newMembers = new ArrayList(); 410 } 411 newMembers.Add(g.Members[j]); 412 } 413 } 414 } 415 } 416 } 417 if (newMembers != null) { 418 for (int i = 0; i < newMembers.Count; ++i) { 419 substitutionGroup.Members.Add(newMembers[i]); 420 } 421 } 422 substitutionGroup.Members.Add(examplar); // Compiled mark 423 } 424 finally { 425 substitutionGroup.IsProcessing = false; 426 } 427 } 428 RecursivelyCheckRedefinedGroups(XmlSchemaGroup redefinedGroup, XmlSchemaGroup baseGroup)429 private void RecursivelyCheckRedefinedGroups(XmlSchemaGroup redefinedGroup, XmlSchemaGroup baseGroup) { 430 if (baseGroup.Redefined != null) { 431 RecursivelyCheckRedefinedGroups(baseGroup, baseGroup.Redefined); 432 } 433 if (redefinedGroup.SelfReferenceCount == 0) { 434 if (baseGroup.CanonicalParticle == null) { 435 baseGroup.CanonicalParticle = CannonicalizeParticle(baseGroup.Particle, true); 436 } 437 if (redefinedGroup.CanonicalParticle == null) { 438 redefinedGroup.CanonicalParticle = CannonicalizeParticle(redefinedGroup.Particle, true); 439 } 440 CompileParticleElements(redefinedGroup.CanonicalParticle); 441 CompileParticleElements(baseGroup.CanonicalParticle); 442 CheckParticleDerivation(redefinedGroup.CanonicalParticle, baseGroup.CanonicalParticle); 443 } 444 } 445 RecursivelyCheckRedefinedAttributeGroups(XmlSchemaAttributeGroup attributeGroup, XmlSchemaAttributeGroup baseAttributeGroup)446 private void RecursivelyCheckRedefinedAttributeGroups(XmlSchemaAttributeGroup attributeGroup, XmlSchemaAttributeGroup baseAttributeGroup) { 447 if (baseAttributeGroup.Redefined != null) { 448 RecursivelyCheckRedefinedAttributeGroups(baseAttributeGroup, baseAttributeGroup.Redefined); 449 } 450 if (attributeGroup.SelfReferenceCount == 0) { 451 CompileAttributeGroup(baseAttributeGroup); 452 CompileAttributeGroup(attributeGroup); 453 CheckAtrributeGroupRestriction(baseAttributeGroup, attributeGroup); 454 } 455 } 456 CompileGroup(XmlSchemaGroup group)457 private void CompileGroup(XmlSchemaGroup group) { 458 if (group.IsProcessing) { 459 SendValidationEvent(Res.Sch_GroupCircularRef, group); 460 group.CanonicalParticle = XmlSchemaParticle.Empty; 461 } 462 else { 463 group.IsProcessing = true; 464 if (group.CanonicalParticle == null) { 465 group.CanonicalParticle = CannonicalizeParticle(group.Particle, true); 466 } 467 Debug.Assert(group.CanonicalParticle != null); 468 group.IsProcessing = false; //Not enclosung in try -finally as cannonicalizeParticle will not throw exception 469 } 470 } 471 CompileSimpleType(XmlSchemaSimpleType simpleType)472 private void CompileSimpleType(XmlSchemaSimpleType simpleType) { 473 if (simpleType.IsProcessing) { 474 throw new XmlSchemaException(Res.Sch_TypeCircularRef, simpleType); 475 } 476 if (simpleType.ElementDecl != null) { // already compiled 477 return; 478 } 479 simpleType.IsProcessing = true; 480 try { 481 if (simpleType.Content is XmlSchemaSimpleTypeList) { 482 XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList)simpleType.Content; 483 XmlSchemaDatatype datatype; 484 simpleType.SetBaseSchemaType(DatatypeImplementation.AnySimpleType); 485 if (list.ItemTypeName.IsEmpty) { 486 CompileSimpleType(list.ItemType); 487 list.BaseItemType = list.ItemType; 488 datatype = list.ItemType.Datatype; 489 } 490 else { 491 XmlSchemaSimpleType type = GetSimpleType(list.ItemTypeName); 492 if (type != null) { 493 if ((type.FinalResolved & XmlSchemaDerivationMethod.List) != 0) { 494 SendValidationEvent(Res.Sch_BaseFinalList, simpleType); 495 } 496 list.BaseItemType = type; 497 datatype = type.Datatype; 498 } 499 else { 500 throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, list.ItemTypeName.ToString(), list); 501 } 502 } 503 simpleType.SetDatatype(datatype.DeriveByList(simpleType)); 504 simpleType.SetDerivedBy(XmlSchemaDerivationMethod.List); 505 } 506 else if (simpleType.Content is XmlSchemaSimpleTypeRestriction) { 507 XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)simpleType.Content; 508 XmlSchemaDatatype datatype; 509 if (restriction.BaseTypeName.IsEmpty) { 510 CompileSimpleType(restriction.BaseType); 511 simpleType.SetBaseSchemaType(restriction.BaseType); 512 datatype = restriction.BaseType.Datatype; 513 } 514 else if (simpleType.Redefined != null && restriction.BaseTypeName == simpleType.Redefined.QualifiedName) { 515 CompileSimpleType((XmlSchemaSimpleType)simpleType.Redefined); 516 simpleType.SetBaseSchemaType(simpleType.Redefined.BaseXmlSchemaType); 517 datatype = simpleType.Redefined.Datatype; 518 } 519 else { 520 if (restriction.BaseTypeName.Equals(DatatypeImplementation.QnAnySimpleType)) { 521 XmlSchema parentSchema = Preprocessor.GetParentSchema(simpleType); 522 if (parentSchema.TargetNamespace != XmlSchema.Namespace) { //If it is not SForS, then error 523 throw new XmlSchemaException(Res.Sch_InvalidSimpleTypeRestriction, restriction.BaseTypeName.ToString(), simpleType); 524 } 525 } 526 XmlSchemaSimpleType type = GetSimpleType(restriction.BaseTypeName); 527 if (type != null) { 528 if ((type.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) { 529 SendValidationEvent(Res.Sch_BaseFinalRestriction, simpleType); 530 } 531 simpleType.SetBaseSchemaType(type); 532 datatype = type.Datatype; 533 } 534 else { 535 throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, restriction.BaseTypeName.ToString(), restriction); 536 } 537 } 538 simpleType.SetDatatype(datatype.DeriveByRestriction(restriction.Facets, NameTable, simpleType)); 539 simpleType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction); 540 } 541 else { //simpleType.Content is XmlSchemaSimpleTypeUnion 542 XmlSchemaSimpleType[] baseTypes = CompileBaseMemberTypes(simpleType); 543 simpleType.SetBaseSchemaType(DatatypeImplementation.AnySimpleType); 544 simpleType.SetDatatype(XmlSchemaDatatype.DeriveByUnion(baseTypes, simpleType)); 545 simpleType.SetDerivedBy(XmlSchemaDerivationMethod.Union); 546 } 547 } 548 catch (XmlSchemaException e) { 549 if (e.SourceSchemaObject == null) { 550 e.SetSource(simpleType); 551 } 552 SendValidationEvent(e); 553 simpleType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype); 554 } 555 finally { 556 SchemaElementDecl decl = new SchemaElementDecl(); 557 decl.ContentValidator = ContentValidator.TextOnly; 558 decl.SchemaType = simpleType; 559 decl.Datatype = simpleType.Datatype; 560 simpleType.ElementDecl = decl; 561 simpleType.IsProcessing = false; 562 } 563 } 564 CompileBaseMemberTypes(XmlSchemaSimpleType simpleType)565 private XmlSchemaSimpleType[] CompileBaseMemberTypes(XmlSchemaSimpleType simpleType) { 566 XmlSchemaSimpleType unionMember; 567 ArrayList memberTypeDefinitions = new ArrayList(); 568 569 XmlSchemaSimpleTypeUnion mainUnion = (XmlSchemaSimpleTypeUnion)simpleType.Content; 570 571 XmlQualifiedName[] mainMemberTypes = mainUnion.MemberTypes; 572 if (mainMemberTypes != null) { 573 for (int i = 0; i < mainMemberTypes.Length; ++i) { 574 unionMember = GetSimpleType(mainMemberTypes[i]); 575 if (unionMember != null) { 576 if (unionMember.Datatype.Variety == XmlSchemaDatatypeVariety.Union) { //union of union 577 CheckUnionType(unionMember, memberTypeDefinitions, simpleType); 578 } 579 else { //its list or atomic 580 memberTypeDefinitions.Add(unionMember); 581 } 582 //Check derivation method of the member that is referenced 583 if ((unionMember.FinalResolved & XmlSchemaDerivationMethod.Union) != 0) { 584 SendValidationEvent(Res.Sch_BaseFinalUnion, simpleType); 585 } 586 } 587 else { 588 throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, mainMemberTypes[i].ToString(), mainUnion); 589 } 590 } 591 } 592 593 //Now add the baseTypes that are defined inside the union itself 594 XmlSchemaObjectCollection mainBaseTypes = mainUnion.BaseTypes; // 595 if (mainBaseTypes != null) { 596 for (int i = 0; i < mainBaseTypes.Count; ++i) { 597 XmlSchemaSimpleType st = (XmlSchemaSimpleType)mainBaseTypes[i]; 598 CompileSimpleType(st); 599 if (st.Datatype.Variety == XmlSchemaDatatypeVariety.Union) { //union of union 600 CheckUnionType(st, memberTypeDefinitions, simpleType); 601 } 602 else { //its list or atomic 603 memberTypeDefinitions.Add(st); 604 } 605 } 606 } 607 //set all types 608 mainUnion.SetBaseMemberTypes(memberTypeDefinitions.ToArray(typeof(XmlSchemaSimpleType)) as XmlSchemaSimpleType[]); 609 return mainUnion.BaseMemberTypes; 610 } 611 CheckUnionType(XmlSchemaSimpleType unionMember, ArrayList memberTypeDefinitions, XmlSchemaSimpleType parentType)612 private void CheckUnionType(XmlSchemaSimpleType unionMember, ArrayList memberTypeDefinitions, XmlSchemaSimpleType parentType) { 613 XmlSchemaDatatype unionDatatype = unionMember.Datatype; 614 if (unionMember.DerivedBy == XmlSchemaDerivationMethod.Restriction && (unionDatatype.HasLexicalFacets || unionDatatype.HasValueFacets) ) { 615 SendValidationEvent(Res.Sch_UnionFromUnion, parentType); 616 } 617 else { 618 Datatype_union uniondt = unionMember.Datatype as Datatype_union; 619 memberTypeDefinitions.AddRange(uniondt.BaseMemberTypes); 620 } 621 } 622 CompileComplexType(XmlSchemaComplexType complexType)623 private void CompileComplexType(XmlSchemaComplexType complexType) { 624 if (complexType.ElementDecl != null) { //already compiled 625 return; 626 } 627 if (complexType.IsProcessing) { 628 SendValidationEvent(Res.Sch_TypeCircularRef, complexType); 629 return; 630 } 631 complexType.IsProcessing = true; 632 try { 633 if (complexType.ContentModel != null) { //simpleContent or complexContent 634 if (complexType.ContentModel is XmlSchemaSimpleContent) { 635 XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent)complexType.ContentModel; 636 complexType.SetContentType(XmlSchemaContentType.TextOnly); 637 if (simpleContent.Content is XmlSchemaSimpleContentExtension) { 638 CompileSimpleContentExtension(complexType, (XmlSchemaSimpleContentExtension)simpleContent.Content); 639 } 640 else { //simpleContent.Content is XmlSchemaSimpleContentRestriction 641 CompileSimpleContentRestriction(complexType, (XmlSchemaSimpleContentRestriction)simpleContent.Content); 642 } 643 } 644 else { // complexType.ContentModel is XmlSchemaComplexContent 645 XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complexType.ContentModel; 646 if (complexContent.Content is XmlSchemaComplexContentExtension) { 647 CompileComplexContentExtension(complexType, complexContent, (XmlSchemaComplexContentExtension)complexContent.Content); 648 } 649 else { // complexContent.Content is XmlSchemaComplexContentRestriction 650 CompileComplexContentRestriction(complexType, complexContent, (XmlSchemaComplexContentRestriction)complexContent.Content); 651 } 652 } 653 } 654 else { //equals XmlSchemaComplexContent with baseType is anyType 655 complexType.SetBaseSchemaType(XmlSchemaComplexType.AnyType); 656 CompileLocalAttributes(XmlSchemaComplexType.AnyType, complexType, complexType.Attributes, complexType.AnyAttribute, XmlSchemaDerivationMethod.Restriction); 657 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction); 658 complexType.SetContentTypeParticle(CompileContentTypeParticle(complexType.Particle)); 659 complexType.SetContentType(GetSchemaContentType(complexType, null, complexType.ContentTypeParticle)); 660 } 661 if (complexType.ContainsIdAttribute(true)) { 662 SendValidationEvent(Res.Sch_TwoIdAttrUses, complexType); 663 } 664 SchemaElementDecl decl = new SchemaElementDecl(); 665 decl.ContentValidator = CompileComplexContent(complexType); 666 decl.SchemaType = complexType; 667 decl.IsAbstract = complexType.IsAbstract; 668 decl.Datatype = complexType.Datatype; 669 decl.Block = complexType.BlockResolved; 670 decl.AnyAttribute = complexType.AttributeWildcard; 671 foreach(XmlSchemaAttribute attribute in complexType.AttributeUses.Values) { 672 if (attribute.Use == XmlSchemaUse.Prohibited) { 673 if (!decl.ProhibitedAttributes.ContainsKey(attribute.QualifiedName)) { 674 decl.ProhibitedAttributes.Add(attribute.QualifiedName, attribute.QualifiedName); 675 } 676 } 677 else { 678 if (!decl.AttDefs.ContainsKey(attribute.QualifiedName) && attribute.AttDef != null && attribute.AttDef.Name != XmlQualifiedName.Empty && attribute.AttDef != SchemaAttDef.Empty) { 679 decl.AddAttDef(attribute.AttDef); 680 } 681 } 682 } 683 complexType.ElementDecl = decl; 684 } 685 finally { 686 complexType.IsProcessing = false; 687 } 688 } 689 690 CompileSimpleContentExtension(XmlSchemaComplexType complexType, XmlSchemaSimpleContentExtension simpleExtension)691 private void CompileSimpleContentExtension(XmlSchemaComplexType complexType, XmlSchemaSimpleContentExtension simpleExtension) { 692 XmlSchemaComplexType baseType = null; 693 if (complexType.Redefined != null && simpleExtension.BaseTypeName == complexType.Redefined.QualifiedName) { 694 baseType = (XmlSchemaComplexType)complexType.Redefined; 695 CompileComplexType(baseType); 696 complexType.SetBaseSchemaType(baseType); 697 complexType.SetDatatype(baseType.Datatype); 698 } 699 else { 700 XmlSchemaType bto = GetAnySchemaType(simpleExtension.BaseTypeName); 701 if (bto == null) { 702 SendValidationEvent(Res.Sch_UndeclaredType, simpleExtension.BaseTypeName.ToString(), simpleExtension); 703 } 704 else { 705 complexType.SetBaseSchemaType(bto); 706 complexType.SetDatatype(bto.Datatype); 707 } 708 baseType = bto as XmlSchemaComplexType; 709 } 710 if (baseType != null) { 711 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) { 712 SendValidationEvent(Res.Sch_BaseFinalExtension, complexType); 713 } 714 if (baseType.ContentType != XmlSchemaContentType.TextOnly) { 715 SendValidationEvent(Res.Sch_NotSimpleContent, complexType); 716 } 717 } 718 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension); 719 CompileLocalAttributes(baseType, complexType, simpleExtension.Attributes, simpleExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension); 720 } 721 CompileSimpleContentRestriction(XmlSchemaComplexType complexType, XmlSchemaSimpleContentRestriction simpleRestriction)722 private void CompileSimpleContentRestriction(XmlSchemaComplexType complexType, XmlSchemaSimpleContentRestriction simpleRestriction) { 723 XmlSchemaComplexType baseType = null; 724 XmlSchemaDatatype datatype = null; 725 if (complexType.Redefined != null && simpleRestriction.BaseTypeName == complexType.Redefined.QualifiedName) { 726 baseType = (XmlSchemaComplexType)complexType.Redefined; 727 CompileComplexType(baseType); 728 datatype = baseType.Datatype; 729 } 730 else { 731 baseType = GetComplexType(simpleRestriction.BaseTypeName); 732 if (baseType == null) { 733 SendValidationEvent(Res.Sch_UndefBaseRestriction, simpleRestriction.BaseTypeName.ToString(), simpleRestriction); 734 return; 735 } 736 if (baseType.ContentType == XmlSchemaContentType.TextOnly) { 737 if (simpleRestriction.BaseType == null) { 738 datatype = baseType.Datatype; 739 //There is a bug here. Need to check if simpleRestriction has facets. 740 //If yes, Need tp apply these facets as well. 741 } 742 else { 743 CompileSimpleType(simpleRestriction.BaseType); 744 if(!XmlSchemaType.IsDerivedFromDatatype(simpleRestriction.BaseType.Datatype, baseType.Datatype, XmlSchemaDerivationMethod.None)) { 745 SendValidationEvent(Res.Sch_DerivedNotFromBase, simpleRestriction); 746 } 747 datatype = simpleRestriction.BaseType.Datatype; 748 } 749 } 750 else if (baseType.ContentType == XmlSchemaContentType.Mixed && baseType.ElementDecl.ContentValidator.IsEmptiable) { 751 if (simpleRestriction.BaseType != null) { 752 CompileSimpleType(simpleRestriction.BaseType); 753 complexType.SetBaseSchemaType(simpleRestriction.BaseType); 754 datatype = simpleRestriction.BaseType.Datatype; 755 } 756 else { 757 SendValidationEvent(Res.Sch_NeedSimpleTypeChild, simpleRestriction); 758 } 759 } 760 else { 761 SendValidationEvent(Res.Sch_NotSimpleContent, complexType); 762 } 763 } 764 if (baseType != null && baseType.ElementDecl != null) { 765 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) { 766 SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType); 767 } 768 } 769 if (baseType != null) { 770 complexType.SetBaseSchemaType(baseType); 771 } 772 if (datatype != null) { 773 try { 774 complexType.SetDatatype(datatype.DeriveByRestriction(simpleRestriction.Facets, NameTable, complexType)); 775 } 776 catch (XmlSchemaException e) { 777 if (e.SourceSchemaObject == null) { 778 e.SetSource(complexType); 779 } 780 SendValidationEvent(e); 781 complexType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype); 782 } 783 } 784 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction); 785 CompileLocalAttributes(baseType, complexType, simpleRestriction.Attributes, simpleRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction); 786 } 787 CompileComplexContentExtension(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentExtension complexExtension)788 private void CompileComplexContentExtension(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentExtension complexExtension) { 789 XmlSchemaComplexType baseType = null; 790 if (complexType.Redefined != null && complexExtension.BaseTypeName == complexType.Redefined.QualifiedName) { 791 baseType = (XmlSchemaComplexType)complexType.Redefined; 792 CompileComplexType(baseType); 793 } 794 else { 795 baseType = GetComplexType(complexExtension.BaseTypeName); 796 if (baseType == null) { 797 SendValidationEvent(Res.Sch_UndefBaseExtension, complexExtension.BaseTypeName.ToString(), complexExtension); 798 return; 799 } 800 } 801 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) { 802 SendValidationEvent(Res.Sch_BaseFinalExtension, complexType); 803 } 804 CompileLocalAttributes(baseType, complexType, complexExtension.Attributes, complexExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension); 805 806 XmlSchemaParticle baseParticle = baseType.ContentTypeParticle; 807 XmlSchemaParticle extendedParticle = CannonicalizeParticle(complexExtension.Particle, true); 808 if (baseParticle != XmlSchemaParticle.Empty) { 809 if (extendedParticle != XmlSchemaParticle.Empty) { 810 XmlSchemaSequence compiledParticle = new XmlSchemaSequence(); 811 compiledParticle.Items.Add(baseParticle); 812 compiledParticle.Items.Add(extendedParticle); 813 complexType.SetContentTypeParticle(CompileContentTypeParticle(compiledParticle)); 814 } 815 else { 816 complexType.SetContentTypeParticle(baseParticle); 817 } 818 } 819 else { 820 complexType.SetContentTypeParticle(extendedParticle); 821 } 822 XmlSchemaContentType contentType = GetSchemaContentType(complexType, complexContent, extendedParticle); 823 if (contentType == XmlSchemaContentType.Empty) { //Derived content type is empty, Get ContentType from base 824 contentType = baseType.ContentType; 825 // In case of a simple base type (content type is TextOnly) the derived type 826 // will be the same as the base type. So set the same content type and then also 827 // set the same data type. 828 if (contentType == XmlSchemaContentType.TextOnly) { 829 complexType.SetDatatype(baseType.Datatype); 830 } 831 } 832 complexType.SetContentType(contentType); 833 834 if (baseType.ContentType != XmlSchemaContentType.Empty && complexType.ContentType != baseType.ContentType) { //If base is empty, do not check 835 SendValidationEvent(Res.Sch_DifContentType, complexType); 836 return; 837 } 838 complexType.SetBaseSchemaType(baseType); 839 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension); 840 } 841 CompileComplexContentRestriction(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentRestriction complexRestriction)842 private void CompileComplexContentRestriction(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentRestriction complexRestriction) { 843 XmlSchemaComplexType baseType = null; 844 if (complexType.Redefined != null && complexRestriction.BaseTypeName == complexType.Redefined.QualifiedName) { 845 baseType = (XmlSchemaComplexType)complexType.Redefined; 846 CompileComplexType(baseType); 847 } 848 else { 849 baseType = GetComplexType(complexRestriction.BaseTypeName); 850 if (baseType == null) { 851 SendValidationEvent(Res.Sch_UndefBaseRestriction, complexRestriction.BaseTypeName.ToString(), complexRestriction); 852 return; 853 } 854 } 855 complexType.SetBaseSchemaType(baseType); 856 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) { 857 SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType); 858 } 859 CompileLocalAttributes(baseType, complexType, complexRestriction.Attributes, complexRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction); 860 861 complexType.SetContentTypeParticle(CompileContentTypeParticle(complexRestriction.Particle)); 862 XmlSchemaContentType derivedContentType = GetSchemaContentType(complexType, complexContent, complexType.ContentTypeParticle); 863 complexType.SetContentType(derivedContentType); 864 switch(derivedContentType) { 865 case XmlSchemaContentType.Empty: 866 if (baseType.ElementDecl != null && !baseType.ElementDecl.ContentValidator.IsEmptiable) { //base is either TextOnly or its ElementOnly/Mixed and not emptiable 867 SendValidationEvent(Res.Sch_InvalidContentRestrictionDetailed, Res.GetString(Res.Sch_InvalidBaseToEmpty), complexType); 868 } 869 break; 870 871 case XmlSchemaContentType.Mixed: 872 if (baseType.ContentType != XmlSchemaContentType.Mixed) { 873 SendValidationEvent(Res.Sch_InvalidContentRestrictionDetailed, Res.GetString(Res.Sch_InvalidBaseToMixed), complexType); 874 } 875 break; 876 } 877 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction); 878 } 879 CheckParticleDerivation(XmlSchemaComplexType complexType)880 private void CheckParticleDerivation(XmlSchemaComplexType complexType) { 881 XmlSchemaComplexType baseType = complexType.BaseXmlSchemaType as XmlSchemaComplexType; 882 restrictionErrorMsg = null; 883 if (baseType != null && baseType != XmlSchemaComplexType.AnyType && complexType.DerivedBy == XmlSchemaDerivationMethod.Restriction) { 884 XmlSchemaParticle derivedParticle = CannonicalizePointlessRoot(complexType.ContentTypeParticle); 885 XmlSchemaParticle baseParticle = CannonicalizePointlessRoot(baseType.ContentTypeParticle); 886 if (!IsValidRestriction(derivedParticle, baseParticle)) { 887 #if DEBUG 888 if(complexType.ContentTypeParticle != null && baseType.ContentTypeParticle != null) { 889 string position = string.Empty; 890 if (complexType.SourceUri != null) { 891 position = " in " + complexType.SourceUri + "(" + complexType.LineNumber + ", " + complexType.LinePosition + ")"; 892 } 893 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType content restriction" + position); 894 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, " Base " + DumpContentModel(baseType.ContentTypeParticle)); 895 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, " Derived " + DumpContentModel(complexType.ContentTypeParticle)); 896 } 897 #endif 898 if (restrictionErrorMsg != null) { 899 SendValidationEvent(Res.Sch_InvalidParticleRestrictionDetailed, restrictionErrorMsg, complexType); 900 } 901 else { 902 SendValidationEvent(Res.Sch_InvalidParticleRestriction, complexType); 903 } 904 } 905 } 906 else if (baseType == XmlSchemaComplexType.AnyType) { //The complex type itself is not explicitly derived by restriction but it could have local elements which have anonymous types that are derived by restriction 907 foreach(XmlSchemaElement localElement in complexType.LocalElements.Values) { 908 if (localElement.IsLocalTypeDerivationChecked) { //Element already checked 909 continue; 910 } 911 XmlSchemaComplexType localComplexType = localElement.ElementSchemaType as XmlSchemaComplexType; 912 if (localComplexType != null && localElement.SchemaTypeName == XmlQualifiedName.Empty && localElement.RefName == XmlQualifiedName.Empty) { //Only local elements 913 localElement.IsLocalTypeDerivationChecked = true; //Not clearing this flag after recursion to make sure this check is not repeated for multiple references of the same local element (through group refs) 914 CheckParticleDerivation(localComplexType); 915 } 916 } 917 } 918 } 919 CheckParticleDerivation(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle)920 private void CheckParticleDerivation(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) { 921 restrictionErrorMsg = null; 922 derivedParticle = CannonicalizePointlessRoot(derivedParticle); 923 baseParticle = CannonicalizePointlessRoot(baseParticle); 924 if (!IsValidRestriction(derivedParticle, baseParticle)) { 925 if (restrictionErrorMsg != null) { 926 SendValidationEvent(Res.Sch_InvalidParticleRestrictionDetailed, restrictionErrorMsg, derivedParticle); 927 } 928 else { 929 SendValidationEvent(Res.Sch_InvalidParticleRestriction, derivedParticle); 930 } 931 } 932 } 933 CompileContentTypeParticle(XmlSchemaParticle particle)934 private XmlSchemaParticle CompileContentTypeParticle(XmlSchemaParticle particle) { 935 XmlSchemaParticle ctp = CannonicalizeParticle(particle, true); 936 XmlSchemaChoice choice = ctp as XmlSchemaChoice; 937 if (choice != null && choice.Items.Count == 0) { 938 if (choice.MinOccurs != decimal.Zero) { 939 SendValidationEvent(Res.Sch_EmptyChoice, choice, XmlSeverityType.Warning); 940 } 941 return XmlSchemaParticle.Empty; 942 } 943 return ctp; 944 } 945 CannonicalizeParticle(XmlSchemaParticle particle, bool root)946 private XmlSchemaParticle CannonicalizeParticle(XmlSchemaParticle particle, bool root) { 947 if (particle == null || particle.IsEmpty) { 948 return XmlSchemaParticle.Empty; 949 } 950 else if (particle is XmlSchemaElement) { 951 //return CannonicalizeElement((XmlSchemaElement)particle, substitution); 952 return particle; 953 } 954 else if (particle is XmlSchemaGroupRef) { 955 return CannonicalizeGroupRef((XmlSchemaGroupRef)particle, root); 956 } 957 else if (particle is XmlSchemaAll) { 958 return CannonicalizeAll((XmlSchemaAll)particle, root); 959 } 960 else if (particle is XmlSchemaChoice) { 961 return CannonicalizeChoice((XmlSchemaChoice)particle, root); 962 } 963 else if (particle is XmlSchemaSequence) { 964 return CannonicalizeSequence((XmlSchemaSequence)particle, root); 965 } 966 else { 967 return particle; 968 } 969 } 970 CannonicalizeElement(XmlSchemaElement element)971 private XmlSchemaParticle CannonicalizeElement(XmlSchemaElement element) { 972 if (!element.RefName.IsEmpty && (element.ElementDecl.Block & XmlSchemaDerivationMethod.Substitution) == 0) { 973 XmlSchemaSubstitutionGroup substitutionGroup = (XmlSchemaSubstitutionGroup)examplars[element.QualifiedName]; 974 if (substitutionGroup == null) { 975 return element; 976 } 977 else { 978 XmlSchemaChoice choice = new XmlSchemaChoice(); 979 for (int i = 0; i < substitutionGroup.Members.Count; ++i) { 980 choice.Items.Add((XmlSchemaElement)substitutionGroup.Members[i]); 981 } 982 choice.MinOccurs = element.MinOccurs; 983 choice.MaxOccurs = element.MaxOccurs; 984 CopyPosition(choice, element, false); 985 return choice; 986 } 987 } 988 else { 989 return element; 990 } 991 } 992 CannonicalizeGroupRef(XmlSchemaGroupRef groupRef, bool root)993 private XmlSchemaParticle CannonicalizeGroupRef(XmlSchemaGroupRef groupRef, bool root) { 994 XmlSchemaGroup group; 995 if (groupRef.Redefined != null) { 996 group = groupRef.Redefined; 997 } 998 else { 999 group = (XmlSchemaGroup)groups[groupRef.RefName]; 1000 } 1001 if (group == null) { 1002 SendValidationEvent(Res.Sch_UndefGroupRef, groupRef.RefName.ToString(), groupRef); 1003 return XmlSchemaParticle.Empty; 1004 } 1005 if (group.CanonicalParticle == null) { 1006 CompileGroup(group); 1007 } 1008 if (group.CanonicalParticle == XmlSchemaParticle.Empty) { 1009 return XmlSchemaParticle.Empty; 1010 } 1011 XmlSchemaGroupBase groupBase = (XmlSchemaGroupBase)group.CanonicalParticle; 1012 if (groupBase is XmlSchemaAll) { 1013 if (!root) { 1014 SendValidationEvent(Res.Sch_AllRefNotRoot, "", groupRef); 1015 return XmlSchemaParticle.Empty; 1016 } 1017 if (groupRef.MinOccurs > decimal.One || groupRef.MaxOccurs != decimal.One) { 1018 SendValidationEvent(Res.Sch_AllRefMinMax, groupRef); 1019 return XmlSchemaParticle.Empty; 1020 } 1021 } 1022 else if (groupBase is XmlSchemaChoice && groupBase.Items.Count == 0) { 1023 if (groupRef.MinOccurs != decimal.Zero) { 1024 SendValidationEvent(Res.Sch_EmptyChoice, groupRef, XmlSeverityType.Warning); 1025 } 1026 return XmlSchemaParticle.Empty; 1027 } 1028 XmlSchemaGroupBase groupRefBase = ( 1029 (groupBase is XmlSchemaSequence) ? (XmlSchemaGroupBase)new XmlSchemaSequence() : 1030 (groupBase is XmlSchemaChoice) ? (XmlSchemaGroupBase)new XmlSchemaChoice() : 1031 (XmlSchemaGroupBase)new XmlSchemaAll() 1032 ); 1033 groupRefBase.MinOccurs = groupRef.MinOccurs; 1034 groupRefBase.MaxOccurs = groupRef.MaxOccurs; 1035 CopyPosition(groupRefBase, groupRef, true); 1036 1037 for (int i = 0; i < groupBase.Items.Count; ++i) { 1038 groupRefBase.Items.Add(groupBase.Items[i]); 1039 } 1040 groupRef.SetParticle(groupRefBase); 1041 return groupRefBase; 1042 } 1043 CannonicalizeAll(XmlSchemaAll all, bool root)1044 private XmlSchemaParticle CannonicalizeAll(XmlSchemaAll all, bool root) { 1045 if (all.Items.Count > 0) { 1046 XmlSchemaAll newAll = new XmlSchemaAll(); 1047 newAll.MinOccurs = all.MinOccurs; 1048 newAll.MaxOccurs = all.MaxOccurs; 1049 CopyPosition(newAll, all, true); 1050 for (int i = 0; i < all.Items.Count; ++i) { 1051 XmlSchemaParticle p = CannonicalizeParticle((XmlSchemaElement)all.Items[i], false); 1052 if (p != XmlSchemaParticle.Empty) { 1053 newAll.Items.Add(p); 1054 } 1055 } 1056 all = newAll; 1057 } 1058 if (all.Items.Count == 0) { 1059 return XmlSchemaParticle.Empty; 1060 } 1061 else if (!root) { 1062 SendValidationEvent(Res.Sch_NotAllAlone, all); 1063 return XmlSchemaParticle.Empty; 1064 } 1065 else { 1066 return all; 1067 } 1068 } 1069 CannonicalizeChoice(XmlSchemaChoice choice, bool root)1070 private XmlSchemaParticle CannonicalizeChoice(XmlSchemaChoice choice, bool root) { 1071 XmlSchemaChoice oldChoice = choice; 1072 if (choice.Items.Count > 0) { 1073 XmlSchemaChoice newChoice = new XmlSchemaChoice(); 1074 newChoice.MinOccurs = choice.MinOccurs; 1075 newChoice.MaxOccurs = choice.MaxOccurs; 1076 CopyPosition(newChoice, choice, true); 1077 for (int i = 0; i < choice.Items.Count; ++i) { 1078 XmlSchemaParticle p1 = CannonicalizeParticle((XmlSchemaParticle)choice.Items[i], false); 1079 if (p1 != XmlSchemaParticle.Empty) { 1080 if (p1.MinOccurs == decimal.One && p1.MaxOccurs == decimal.One && p1 is XmlSchemaChoice) { 1081 XmlSchemaChoice p1Choice = p1 as XmlSchemaChoice; 1082 for (int j = 0; j < p1Choice.Items.Count; ++j) { 1083 newChoice.Items.Add(p1Choice.Items[j]); 1084 } 1085 } 1086 else { 1087 newChoice.Items.Add(p1); 1088 } 1089 } 1090 } 1091 choice = newChoice; 1092 } 1093 if (!root && choice.Items.Count == 0) { 1094 if (choice.MinOccurs != decimal.Zero) { 1095 SendValidationEvent(Res.Sch_EmptyChoice, oldChoice, XmlSeverityType.Warning); 1096 } 1097 return XmlSchemaParticle.Empty; 1098 } 1099 else if (!root && choice.Items.Count == 1 && choice.MinOccurs == decimal.One && choice.MaxOccurs == decimal.One) { 1100 return (XmlSchemaParticle)choice.Items[0]; 1101 } 1102 else { 1103 return choice; 1104 } 1105 } 1106 CannonicalizeSequence(XmlSchemaSequence sequence, bool root)1107 private XmlSchemaParticle CannonicalizeSequence(XmlSchemaSequence sequence, bool root) { 1108 if (sequence.Items.Count > 0) { 1109 XmlSchemaSequence newSequence = new XmlSchemaSequence(); 1110 newSequence.MinOccurs = sequence.MinOccurs; 1111 newSequence.MaxOccurs = sequence.MaxOccurs; 1112 CopyPosition(newSequence, sequence, true); 1113 for (int i = 0; i < sequence.Items.Count; ++i) { 1114 XmlSchemaParticle p1 = CannonicalizeParticle((XmlSchemaParticle)sequence.Items[i], false); 1115 if (p1 != XmlSchemaParticle.Empty) { 1116 XmlSchemaSequence p1Sequence = p1 as XmlSchemaSequence; 1117 if (p1.MinOccurs == decimal.One && p1.MaxOccurs == decimal.One && p1Sequence != null) { 1118 for (int j = 0; j < p1Sequence.Items.Count; ++j) { 1119 newSequence.Items.Add(p1Sequence.Items[j]); 1120 } 1121 } 1122 else { 1123 newSequence.Items.Add(p1); 1124 } 1125 } 1126 } 1127 sequence = newSequence; 1128 } 1129 if (sequence.Items.Count == 0) { 1130 return XmlSchemaParticle.Empty; 1131 } 1132 else if (!root && sequence.Items.Count == 1 && sequence.MinOccurs == decimal.One && sequence.MaxOccurs == decimal.One) { 1133 return (XmlSchemaParticle)sequence.Items[0]; 1134 } 1135 else { 1136 return sequence; 1137 } 1138 } 1139 CannonicalizePointlessRoot(XmlSchemaParticle particle)1140 private XmlSchemaParticle CannonicalizePointlessRoot(XmlSchemaParticle particle) { 1141 if (particle == null) { 1142 return null; 1143 } 1144 XmlSchemaSequence xss; 1145 XmlSchemaChoice xsc; 1146 XmlSchemaAll xsa; 1147 decimal one = decimal.One; 1148 1149 if ( (xss = (particle as XmlSchemaSequence)) != null ) { 1150 XmlSchemaObjectCollection items = xss.Items; 1151 int count = items.Count; 1152 if (count == 1) { 1153 if (xss.MinOccurs == one && xss.MaxOccurs == one) { 1154 return (XmlSchemaParticle)items[0]; 1155 } 1156 } 1157 } 1158 else if ( (xsc = (particle as XmlSchemaChoice)) != null ) { 1159 XmlSchemaObjectCollection items = xsc.Items; 1160 int count = items.Count; 1161 1162 if (count == 1) { 1163 if (xsc.MinOccurs == one && xsc.MaxOccurs == one) { 1164 return (XmlSchemaParticle)items[0]; 1165 } 1166 } 1167 else if (count == 0) { 1168 return XmlSchemaParticle.Empty; 1169 } 1170 } 1171 else if ( (xsa = (particle as XmlSchemaAll)) != null ) { 1172 XmlSchemaObjectCollection items = xsa.Items; 1173 int count = items.Count; 1174 1175 if (count == 1) { 1176 if (xsa.MinOccurs == one && xsa.MaxOccurs == one) { 1177 return (XmlSchemaParticle)items[0]; 1178 } 1179 } 1180 } 1181 1182 return particle; 1183 } 1184 IsValidRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle)1185 private bool IsValidRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) { 1186 if (derivedParticle == baseParticle) { 1187 return true; 1188 } 1189 else if (derivedParticle == null || derivedParticle == XmlSchemaParticle.Empty) { 1190 return IsParticleEmptiable(baseParticle); 1191 } 1192 else if (baseParticle == null || baseParticle == XmlSchemaParticle.Empty) { 1193 return false; 1194 } 1195 if (derivedParticle is XmlSchemaElement) { //check for derived element being head of substitutionGroup 1196 XmlSchemaElement derivedElem = (XmlSchemaElement)derivedParticle; 1197 derivedParticle = CannonicalizeElement(derivedElem); 1198 } 1199 if (baseParticle is XmlSchemaElement) { 1200 XmlSchemaElement baseElem = (XmlSchemaElement)baseParticle; 1201 XmlSchemaParticle newBaseParticle; 1202 newBaseParticle = CannonicalizeElement(baseElem); 1203 if (newBaseParticle is XmlSchemaChoice) { //Base Element is subs grp head. 1204 return IsValidRestriction(derivedParticle, newBaseParticle); 1205 } 1206 else if (derivedParticle is XmlSchemaElement) { 1207 return IsElementFromElement((XmlSchemaElement)derivedParticle, baseElem); 1208 } 1209 else { 1210 restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForElem); 1211 return false; 1212 } 1213 } 1214 else if (baseParticle is XmlSchemaAny) { 1215 if (derivedParticle is XmlSchemaElement) { 1216 return IsElementFromAny((XmlSchemaElement)derivedParticle, (XmlSchemaAny)baseParticle); 1217 } 1218 else if (derivedParticle is XmlSchemaAny) { 1219 return IsAnyFromAny((XmlSchemaAny)derivedParticle, (XmlSchemaAny)baseParticle); 1220 } 1221 else { 1222 return IsGroupBaseFromAny((XmlSchemaGroupBase)derivedParticle, (XmlSchemaAny)baseParticle); 1223 } 1224 } 1225 else if (baseParticle is XmlSchemaAll) { 1226 if (derivedParticle is XmlSchemaElement) { 1227 return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle); 1228 } 1229 else if (derivedParticle is XmlSchemaAll) { 1230 if(IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true)) { 1231 return true; 1232 } 1233 } 1234 else if (derivedParticle is XmlSchemaSequence) { 1235 if(IsSequenceFromAll((XmlSchemaSequence)derivedParticle, (XmlSchemaAll)baseParticle)) { 1236 return true; 1237 } 1238 restrictionErrorMsg = Res.GetString(Res.Sch_SeqFromAll, derivedParticle.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedParticle.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseParticle.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseParticle.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 1239 } 1240 else if (derivedParticle is XmlSchemaChoice || derivedParticle is XmlSchemaAny) { 1241 restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForAll); 1242 } 1243 return false; 1244 } 1245 else if (baseParticle is XmlSchemaChoice ) { 1246 if (derivedParticle is XmlSchemaElement) { 1247 return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase) baseParticle); 1248 } 1249 else if (derivedParticle is XmlSchemaChoice) { 1250 XmlSchemaChoice baseChoice = baseParticle as XmlSchemaChoice; 1251 XmlSchemaChoice derivedChoice = derivedParticle as XmlSchemaChoice; 1252 1253 if (baseChoice.Parent == null || derivedChoice.Parent == null) { //using parent property to indicate this choice was created on the fly for substitutionGroup 1254 return IsChoiceFromChoiceSubstGroup(derivedChoice, baseChoice); 1255 } 1256 if(IsGroupBaseFromGroupBase(derivedChoice, baseChoice, false)) { 1257 return true; 1258 } 1259 } 1260 else if (derivedParticle is XmlSchemaSequence) { 1261 if(IsSequenceFromChoice((XmlSchemaSequence)derivedParticle, (XmlSchemaChoice) baseParticle)) { 1262 return true; 1263 } 1264 restrictionErrorMsg = Res.GetString(Res.Sch_SeqFromChoice, derivedParticle.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedParticle.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseParticle.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseParticle.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 1265 } 1266 else { 1267 restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForChoice); 1268 } 1269 return false; 1270 } 1271 else if (baseParticle is XmlSchemaSequence) { 1272 if (derivedParticle is XmlSchemaElement) { 1273 return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle); 1274 } 1275 else if (derivedParticle is XmlSchemaSequence || (derivedParticle is XmlSchemaAll && ((XmlSchemaGroupBase)derivedParticle).Items.Count ==1)) { 1276 if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true)) { 1277 return true; 1278 } 1279 } 1280 else { 1281 restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForSeq); 1282 } 1283 return false; 1284 } 1285 else { 1286 Debug.Assert(false); 1287 } 1288 1289 return false; 1290 } 1291 IsElementFromElement(XmlSchemaElement derivedElement, XmlSchemaElement baseElement)1292 private bool IsElementFromElement(XmlSchemaElement derivedElement, XmlSchemaElement baseElement) { 1293 // In case of elements the block value '#all' is 100% equivalent to the value of 'substitution restriction extension'. 1294 // Since below we perform a logical operation on the bit fields we need to convert the #all (0xFF) 1295 // to the equivalent set of substitution, restriction and extension, so that the operation works as expected. 1296 // (The goal of the (derived | base) == derived is to fail if the derived is not a bitwise superset of base) 1297 XmlSchemaDerivationMethod baseEffectiveBlock = 1298 baseElement.ElementDecl.Block == XmlSchemaDerivationMethod.All ? 1299 XmlSchemaDerivationMethod.Substitution | XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.Extension : 1300 baseElement.ElementDecl.Block; 1301 XmlSchemaDerivationMethod derivedEffectiveBlock = 1302 derivedElement.ElementDecl.Block == XmlSchemaDerivationMethod.All ? 1303 XmlSchemaDerivationMethod.Substitution | XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.Extension : 1304 derivedElement.ElementDecl.Block; 1305 1306 if(! ((derivedElement.QualifiedName == baseElement.QualifiedName) && 1307 (baseElement.IsNillable || !derivedElement.IsNillable) && 1308 IsValidOccurrenceRangeRestriction(derivedElement, baseElement) && 1309 (baseElement.FixedValue == null || IsFixedEqual(baseElement.ElementDecl, derivedElement.ElementDecl) ) && 1310 ((derivedEffectiveBlock | baseEffectiveBlock) == derivedEffectiveBlock) && 1311 (derivedElement.ElementSchemaType != null) && (baseElement.ElementSchemaType != null) && 1312 XmlSchemaType.IsDerivedFrom(derivedElement.ElementSchemaType, baseElement.ElementSchemaType, ~(XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.List | XmlSchemaDerivationMethod.Union))) ) { 1313 restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromElement, derivedElement.QualifiedName, baseElement.QualifiedName); 1314 return false; 1315 } 1316 return true; 1317 } 1318 IsElementFromAny(XmlSchemaElement derivedElement, XmlSchemaAny baseAny)1319 private bool IsElementFromAny(XmlSchemaElement derivedElement, XmlSchemaAny baseAny) { 1320 if (!baseAny.Allows(derivedElement.QualifiedName)) { 1321 restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromAnyRule1, derivedElement.QualifiedName.ToString()); 1322 return false; 1323 } 1324 if (!IsValidOccurrenceRangeRestriction(derivedElement, baseAny)) { 1325 restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromAnyRule2, derivedElement.QualifiedName.ToString()); 1326 return false; 1327 } 1328 return true; 1329 } 1330 IsAnyFromAny(XmlSchemaAny derivedAny, XmlSchemaAny baseAny)1331 private bool IsAnyFromAny(XmlSchemaAny derivedAny, XmlSchemaAny baseAny) { 1332 if (!IsValidOccurrenceRangeRestriction(derivedAny, baseAny)) { 1333 restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule1); 1334 return false; 1335 } 1336 if (!NamespaceList.IsSubset(derivedAny.NamespaceList, baseAny.NamespaceList)) { 1337 restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule2); 1338 return false; 1339 } 1340 if ((int)derivedAny.ProcessContentsCorrect < (int)baseAny.ProcessContentsCorrect) { 1341 restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule3); 1342 return false; 1343 } 1344 return true; 1345 } 1346 IsGroupBaseFromAny(XmlSchemaGroupBase derivedGroupBase, XmlSchemaAny baseAny)1347 private bool IsGroupBaseFromAny(XmlSchemaGroupBase derivedGroupBase, XmlSchemaAny baseAny) { 1348 decimal minOccurs, maxOccurs; 1349 CalculateEffectiveTotalRange(derivedGroupBase, out minOccurs, out maxOccurs); 1350 if (!IsValidOccurrenceRangeRestriction(minOccurs, maxOccurs, baseAny.MinOccurs, baseAny.MaxOccurs)) { 1351 restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseFromAny2, derivedGroupBase.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedGroupBase.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseAny.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseAny.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 1352 return false; 1353 } 1354 // eliminate occurrance range check 1355 string minOccursAny = baseAny.MinOccursString; 1356 baseAny.MinOccurs = decimal.Zero; 1357 for (int i = 0; i < derivedGroupBase.Items.Count; ++i) { 1358 if (!IsValidRestriction((XmlSchemaParticle)derivedGroupBase.Items[i], baseAny)) { 1359 restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseFromAny1); 1360 baseAny.MinOccursString = minOccursAny; 1361 return false; 1362 } 1363 } 1364 baseAny.MinOccursString = minOccursAny; 1365 return true; 1366 } 1367 1368 #if Microsoft IsElementFromGroupBase(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase, bool skipEmptableOnly)1369 private bool IsElementFromGroupBase(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase, bool skipEmptableOnly) { 1370 if (!IsRangeSimple(baseGroupBase.MinOccurs, baseGroupBase.MaxOccurs) || !IsRangeSimple(derivedElement.MinOccurs, derivedElement.MaxOccurs)) { 1371 return IsElementFromGroupBase(derivedElement, baseGroupBase); //SPEC COMPLIANT 1372 } 1373 else { 1374 //Base partilce's and Derived Element's range is simple 1375 //If all particles in baseParticle also have simple ranges, then can use our algorithm 1376 //So that we dont break common cases that we used to accept earlier 1377 //Example Choice -> Element 1378 if (IsElementFromGroupBaseHack(derivedElement, baseGroupBase, skipEmptableOnly)) { 1379 return true; 1380 } 1381 else { //Fall back to regular checking 1382 return IsElementFromGroupBase(derivedElement, baseGroupBase); 1383 } 1384 } 1385 } 1386 IsElementFromGroupBaseHack(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase, bool skipEmptableOnly)1387 private bool IsElementFromGroupBaseHack(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase, bool skipEmptableOnly) { 1388 bool isMatched = false; 1389 1390 foreach(XmlSchemaParticle baseParticle in baseGroupBase.Items) { 1391 if (!isMatched && IsRangeSimple(baseParticle.MinOccurs, baseParticle.MaxOccurs)) { 1392 string minOccursElement = baseParticle.MinOccursString; 1393 string maxOccursElement = baseParticle.MaxOccursString; 1394 baseParticle.MinOccurs *= baseGroupBase.MinOccurs; 1395 if ( baseParticle.MaxOccurs != decimal.MaxValue) { 1396 if (baseGroupBase.MaxOccurs == decimal.MaxValue) 1397 baseParticle.MaxOccurs = decimal.MaxValue; 1398 else 1399 baseParticle.MaxOccurs *= baseGroupBase.MaxOccurs; 1400 } 1401 isMatched = IsValidRestriction(derivedElement, baseParticle); 1402 baseParticle.MinOccursString = minOccursElement; 1403 baseParticle.MaxOccursString = maxOccursElement; 1404 } 1405 if (!isMatched && skipEmptableOnly && !IsParticleEmptiable(baseParticle)) { 1406 return false; 1407 } 1408 } 1409 return isMatched; 1410 } 1411 #endif IsElementFromGroupBase(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase)1412 private bool IsElementFromGroupBase(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase) { 1413 if (baseGroupBase is XmlSchemaSequence) { 1414 XmlSchemaSequence virtualSeq = new XmlSchemaSequence(); 1415 virtualSeq.MinOccurs = 1; 1416 virtualSeq.MaxOccurs = 1; 1417 virtualSeq.Items.Add(derivedElement); 1418 if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)virtualSeq, baseGroupBase, true)) { 1419 return true; 1420 } 1421 restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromGroupBase1, derivedElement.QualifiedName.ToString(), derivedElement.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedElement.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 1422 } 1423 else if (baseGroupBase is XmlSchemaChoice) { 1424 XmlSchemaChoice virtualChoice = new XmlSchemaChoice(); 1425 virtualChoice.MinOccurs = 1; 1426 virtualChoice.MaxOccurs = 1; 1427 virtualChoice.Items.Add(derivedElement); 1428 if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)virtualChoice, baseGroupBase, false)) { 1429 return true; 1430 } 1431 restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromGroupBase2, derivedElement.QualifiedName.ToString(), derivedElement.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedElement.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 1432 } 1433 else if (baseGroupBase is XmlSchemaAll) { 1434 XmlSchemaAll virtualAll = new XmlSchemaAll(); 1435 virtualAll.MinOccurs = 1; 1436 virtualAll.MaxOccurs = 1; 1437 virtualAll.Items.Add(derivedElement); 1438 if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)virtualAll, baseGroupBase, true)) { 1439 return true; 1440 } 1441 restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromGroupBase3, derivedElement.QualifiedName.ToString(), derivedElement.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedElement.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 1442 } 1443 return false; 1444 } 1445 IsChoiceFromChoiceSubstGroup(XmlSchemaChoice derivedChoice, XmlSchemaChoice baseChoice)1446 private bool IsChoiceFromChoiceSubstGroup(XmlSchemaChoice derivedChoice, XmlSchemaChoice baseChoice) { 1447 if (!IsValidOccurrenceRangeRestriction(derivedChoice, baseChoice)) { 1448 restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestRangeInvalid); 1449 return false; 1450 } 1451 for (int i = 0; i < derivedChoice.Items.Count; ++i) { 1452 if (GetMappingParticle((XmlSchemaParticle)derivedChoice.Items[i], baseChoice.Items) < 0) { 1453 return false; 1454 } 1455 } 1456 return true; 1457 } 1458 IsGroupBaseFromGroupBase(XmlSchemaGroupBase derivedGroupBase, XmlSchemaGroupBase baseGroupBase, bool skipEmptableOnly)1459 private bool IsGroupBaseFromGroupBase(XmlSchemaGroupBase derivedGroupBase, XmlSchemaGroupBase baseGroupBase, bool skipEmptableOnly) { 1460 if (!IsValidOccurrenceRangeRestriction(derivedGroupBase, baseGroupBase)) { 1461 restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestRangeInvalid); 1462 return false; 1463 } 1464 if (derivedGroupBase.Items.Count > baseGroupBase.Items.Count) { 1465 restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestNoMap); 1466 return false; 1467 } 1468 int count = 0; 1469 for (int i = 0; i < baseGroupBase.Items.Count; ++i) { 1470 XmlSchemaParticle baseParticle = (XmlSchemaParticle)baseGroupBase.Items[i]; 1471 if ((count < derivedGroupBase.Items.Count) 1472 && IsValidRestriction((XmlSchemaParticle)derivedGroupBase.Items[count], baseParticle)) { 1473 count ++; 1474 } 1475 else if (skipEmptableOnly && !IsParticleEmptiable(baseParticle)) { 1476 if (restrictionErrorMsg == null) { //If restriction failed on previous check, do not overwrite error 1477 restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestNotEmptiable); 1478 } 1479 return false; 1480 } 1481 } 1482 if (count < derivedGroupBase.Items.Count) { 1483 return false; 1484 } 1485 return true; 1486 } 1487 IsSequenceFromAll(XmlSchemaSequence derivedSequence, XmlSchemaAll baseAll)1488 private bool IsSequenceFromAll(XmlSchemaSequence derivedSequence, XmlSchemaAll baseAll) { 1489 if (!IsValidOccurrenceRangeRestriction(derivedSequence, baseAll) || derivedSequence.Items.Count > baseAll.Items.Count) { 1490 return false; 1491 } 1492 BitSet map = new BitSet(baseAll.Items.Count); 1493 for (int j = 0; j < derivedSequence.Items.Count; ++j) { 1494 int i = GetMappingParticle((XmlSchemaParticle)derivedSequence.Items[j], baseAll.Items); 1495 if (i >= 0) { 1496 if (map[i]) { 1497 return false; 1498 } 1499 else { 1500 map.Set(i); 1501 } 1502 } 1503 else { 1504 return false; 1505 } 1506 } 1507 for (int i = 0; i < baseAll.Items.Count; i++) { 1508 if (!map[i] && !IsParticleEmptiable((XmlSchemaParticle)baseAll.Items[i])) { 1509 return false; 1510 } 1511 } 1512 return true; 1513 } 1514 IsSequenceFromChoice(XmlSchemaSequence derivedSequence, XmlSchemaChoice baseChoice)1515 private bool IsSequenceFromChoice(XmlSchemaSequence derivedSequence, XmlSchemaChoice baseChoice) { 1516 decimal minOccurs, maxOccurs; 1517 minOccurs = derivedSequence.MinOccurs * derivedSequence.Items.Count; 1518 if (derivedSequence.MaxOccurs == decimal.MaxValue) { 1519 maxOccurs = decimal.MaxValue; 1520 } 1521 else { 1522 maxOccurs = derivedSequence.MaxOccurs * derivedSequence.Items.Count; 1523 } 1524 if (!IsValidOccurrenceRangeRestriction(minOccurs, maxOccurs, baseChoice.MinOccurs, baseChoice.MaxOccurs) || derivedSequence.Items.Count > baseChoice.Items.Count) { 1525 return false; 1526 } 1527 for (int i = 0; i < derivedSequence.Items.Count; ++i) { 1528 if (GetMappingParticle((XmlSchemaParticle)derivedSequence.Items[i], baseChoice.Items) < 0) 1529 return false; 1530 } 1531 return true; 1532 } 1533 IsValidOccurrenceRangeRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle)1534 private bool IsValidOccurrenceRangeRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) { 1535 return IsValidOccurrenceRangeRestriction(derivedParticle.MinOccurs, derivedParticle.MaxOccurs, baseParticle.MinOccurs, baseParticle.MaxOccurs); 1536 } 1537 IsValidOccurrenceRangeRestriction(decimal minOccurs, decimal maxOccurs, decimal baseMinOccurs, decimal baseMaxOccurs)1538 private bool IsValidOccurrenceRangeRestriction(decimal minOccurs, decimal maxOccurs, decimal baseMinOccurs, decimal baseMaxOccurs) { 1539 return (baseMinOccurs <= minOccurs) && (maxOccurs <= baseMaxOccurs); 1540 } 1541 GetMappingParticle(XmlSchemaParticle particle, XmlSchemaObjectCollection collection)1542 private int GetMappingParticle(XmlSchemaParticle particle, XmlSchemaObjectCollection collection) { 1543 for (int i = 0; i < collection.Count; i++) { 1544 if (IsValidRestriction(particle, (XmlSchemaParticle)collection[i])) 1545 return i; 1546 } 1547 return -1; 1548 } 1549 IsParticleEmptiable(XmlSchemaParticle particle)1550 private bool IsParticleEmptiable(XmlSchemaParticle particle) { 1551 decimal minOccurs, maxOccurs; 1552 CalculateEffectiveTotalRange(particle, out minOccurs, out maxOccurs); 1553 return minOccurs == decimal.Zero; 1554 } 1555 CalculateEffectiveTotalRange(XmlSchemaParticle particle, out decimal minOccurs, out decimal maxOccurs)1556 private void CalculateEffectiveTotalRange(XmlSchemaParticle particle, out decimal minOccurs, out decimal maxOccurs) { 1557 XmlSchemaChoice choice = particle as XmlSchemaChoice; 1558 1559 if (particle is XmlSchemaElement || particle is XmlSchemaAny) { 1560 minOccurs = particle.MinOccurs; 1561 maxOccurs = particle.MaxOccurs; 1562 } 1563 else if (choice != null) { 1564 if (choice.Items.Count == 0) { 1565 minOccurs = maxOccurs = decimal.Zero; 1566 } 1567 else { 1568 minOccurs = decimal.MaxValue; 1569 maxOccurs = decimal.Zero; 1570 for (int i = 0; i < choice.Items.Count; ++i) { 1571 decimal min, max; 1572 CalculateEffectiveTotalRange((XmlSchemaParticle)choice.Items[i], out min, out max); 1573 if (min < minOccurs) { 1574 minOccurs = min; 1575 } 1576 if (max > maxOccurs) { 1577 maxOccurs = max; 1578 } 1579 } 1580 minOccurs *= particle.MinOccurs; 1581 if (maxOccurs != decimal.MaxValue) { 1582 if (particle.MaxOccurs == decimal.MaxValue) 1583 maxOccurs = decimal.MaxValue; 1584 else 1585 maxOccurs *= particle.MaxOccurs; 1586 } 1587 } 1588 } 1589 else { 1590 XmlSchemaObjectCollection collection = ((XmlSchemaGroupBase)particle).Items; 1591 if (collection.Count == 0) { 1592 minOccurs = maxOccurs = decimal.Zero; 1593 } 1594 else { 1595 minOccurs = 0; 1596 maxOccurs = 0; 1597 for (int i = 0; i < collection.Count; ++i) { 1598 decimal min, max; 1599 CalculateEffectiveTotalRange((XmlSchemaParticle)collection[i], out min, out max); 1600 minOccurs += min; 1601 if (maxOccurs != decimal.MaxValue) { 1602 if (max == decimal.MaxValue) 1603 maxOccurs = decimal.MaxValue; 1604 else 1605 maxOccurs += max; 1606 } 1607 } 1608 minOccurs *= particle.MinOccurs; 1609 if (maxOccurs != decimal.MaxValue) { 1610 if (particle.MaxOccurs == decimal.MaxValue) 1611 maxOccurs = decimal.MaxValue; 1612 else 1613 maxOccurs *= particle.MaxOccurs; 1614 } 1615 } 1616 } 1617 } 1618 PushComplexType(XmlSchemaComplexType complexType)1619 private void PushComplexType(XmlSchemaComplexType complexType) { 1620 this.complexTypeStack.Push(complexType); 1621 } 1622 GetSchemaContentType(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaParticle particle)1623 private XmlSchemaContentType GetSchemaContentType(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaParticle particle) { 1624 if ((complexContent != null && complexContent.IsMixed) || 1625 (complexContent == null && complexType.IsMixed)) { 1626 return XmlSchemaContentType.Mixed; 1627 } 1628 else if (particle != null && !particle.IsEmpty) { 1629 return XmlSchemaContentType.ElementOnly; 1630 } 1631 else { 1632 return XmlSchemaContentType.Empty; 1633 } 1634 } 1635 CompileAttributeGroup(XmlSchemaAttributeGroup attributeGroup)1636 private void CompileAttributeGroup(XmlSchemaAttributeGroup attributeGroup) { 1637 if (attributeGroup.IsProcessing) { 1638 SendValidationEvent(Res.Sch_AttributeGroupCircularRef, attributeGroup); 1639 return; 1640 } 1641 if (attributeGroup.AttributeUses.Count > 0) {// already checked 1642 return; 1643 } 1644 attributeGroup.IsProcessing = true; 1645 XmlSchemaAnyAttribute anyAttribute = attributeGroup.AnyAttribute; 1646 1647 try { 1648 for (int i = 0; i < attributeGroup.Attributes.Count; ++i) { 1649 XmlSchemaAttribute attr = attributeGroup.Attributes[i] as XmlSchemaAttribute; 1650 if (attr != null) { 1651 if (attr.Use == XmlSchemaUse.Prohibited) { 1652 continue; 1653 } 1654 CompileAttribute(attr); 1655 if (attributeGroup.AttributeUses[attr.QualifiedName] == null) { 1656 attributeGroup.AttributeUses.Add(attr.QualifiedName, attr); 1657 } 1658 else { 1659 SendValidationEvent(Res.Sch_DupAttributeUse, attr.QualifiedName.ToString(), attr); 1660 } 1661 } 1662 else { // XmlSchemaAttributeGroupRef 1663 XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef)attributeGroup.Attributes[i]; 1664 XmlSchemaAttributeGroup attributeGroupResolved; 1665 if (attributeGroup.Redefined != null && attributeGroupRef.RefName == attributeGroup.Redefined.QualifiedName) { 1666 attributeGroupResolved = (XmlSchemaAttributeGroup)attributeGroup.Redefined; 1667 } 1668 else { 1669 attributeGroupResolved = (XmlSchemaAttributeGroup)attributeGroups[attributeGroupRef.RefName]; 1670 } 1671 if (attributeGroupResolved != null) { 1672 CompileAttributeGroup(attributeGroupResolved); 1673 foreach (XmlSchemaAttribute attribute in attributeGroupResolved.AttributeUses.Values) { 1674 if (attributeGroup.AttributeUses[attribute.QualifiedName] == null) { 1675 attributeGroup.AttributeUses.Add(attribute.QualifiedName, attribute); 1676 } 1677 else { 1678 SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attribute); 1679 } 1680 } 1681 anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroupResolved.AttributeWildcard); 1682 } 1683 else { 1684 SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef); 1685 } 1686 } 1687 } 1688 attributeGroup.AttributeWildcard = anyAttribute; 1689 } 1690 finally { 1691 attributeGroup.IsProcessing = false; 1692 } 1693 } 1694 CompileLocalAttributes(XmlSchemaComplexType baseType, XmlSchemaComplexType derivedType, XmlSchemaObjectCollection attributes, XmlSchemaAnyAttribute anyAttribute, XmlSchemaDerivationMethod derivedBy)1695 private void CompileLocalAttributes(XmlSchemaComplexType baseType, XmlSchemaComplexType derivedType, XmlSchemaObjectCollection attributes, XmlSchemaAnyAttribute anyAttribute, XmlSchemaDerivationMethod derivedBy) { 1696 XmlSchemaAnyAttribute baseAttributeWildcard = baseType != null ? baseType.AttributeWildcard : null; 1697 for (int i = 0; i < attributes.Count; ++i) { 1698 XmlSchemaAttribute attr = attributes[i] as XmlSchemaAttribute; 1699 if (attr != null) { 1700 if (attr.Use != XmlSchemaUse.Prohibited) { 1701 CompileAttribute(attr); 1702 } 1703 if (attr.Use != XmlSchemaUse.Prohibited || 1704 (attr.Use == XmlSchemaUse.Prohibited && derivedBy == XmlSchemaDerivationMethod.Restriction && baseType != XmlSchemaComplexType.AnyType)) { 1705 1706 if (derivedType.AttributeUses[attr.QualifiedName] == null) { 1707 derivedType.AttributeUses.Add(attr.QualifiedName, attr); 1708 } 1709 else { 1710 SendValidationEvent(Res.Sch_DupAttributeUse, attr.QualifiedName.ToString(), attr); 1711 } 1712 } 1713 else { 1714 SendValidationEvent(Res.Sch_AttributeIgnored, attr.QualifiedName.ToString(), attr, XmlSeverityType.Warning); 1715 } 1716 1717 } 1718 else { // is XmlSchemaAttributeGroupRef 1719 XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef) attributes[i]; 1720 XmlSchemaAttributeGroup attributeGroup = (XmlSchemaAttributeGroup)attributeGroups[attributeGroupRef.RefName]; 1721 if (attributeGroup != null) { 1722 CompileAttributeGroup(attributeGroup); 1723 foreach (XmlSchemaAttribute attribute in attributeGroup.AttributeUses.Values) { 1724 if (attribute.Use != XmlSchemaUse.Prohibited || 1725 (attribute.Use == XmlSchemaUse.Prohibited && derivedBy == XmlSchemaDerivationMethod.Restriction && baseType != XmlSchemaComplexType.AnyType)) { 1726 if (derivedType.AttributeUses[attribute.QualifiedName] == null) { 1727 derivedType.AttributeUses.Add(attribute.QualifiedName, attribute); 1728 } 1729 else { 1730 SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attributeGroupRef); 1731 } 1732 } 1733 else { 1734 SendValidationEvent(Res.Sch_AttributeIgnored, attribute.QualifiedName.ToString(), attribute, XmlSeverityType.Warning); 1735 } 1736 1737 } 1738 anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroup.AttributeWildcard); 1739 } 1740 else { 1741 SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef); 1742 } 1743 } 1744 } 1745 1746 // check derivation rules 1747 if (baseType != null) { 1748 if (derivedBy == XmlSchemaDerivationMethod.Extension) { 1749 derivedType.SetAttributeWildcard(CompileAnyAttributeUnion(anyAttribute, baseAttributeWildcard)); 1750 foreach(XmlSchemaAttribute attributeBase in baseType.AttributeUses.Values) { 1751 XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedType.AttributeUses[attributeBase.QualifiedName]; 1752 if (attribute == null) { 1753 derivedType.AttributeUses.Add(attributeBase.QualifiedName, attributeBase); 1754 } 1755 else { 1756 Debug.Assert(attribute.Use != XmlSchemaUse.Prohibited); 1757 if (attributeBase.Use != XmlSchemaUse.Prohibited && attribute.AttributeSchemaType != attributeBase.AttributeSchemaType) { //Extension allows previously prohibited attributes to be re-added, 1758 SendValidationEvent(Res.Sch_InvalidAttributeExtension, attribute); 1759 } 1760 } 1761 } 1762 } 1763 else { // derivedBy == XmlSchemaDerivationMethod.Restriction 1764 // Schema Component Constraint: Derivation Valid (Restriction, Complex) 1765 if ((anyAttribute != null) && (baseAttributeWildcard == null || !XmlSchemaAnyAttribute.IsSubset(anyAttribute, baseAttributeWildcard) || !IsProcessContentsRestricted(baseType, anyAttribute, baseAttributeWildcard)) ) { 1766 SendValidationEvent(Res.Sch_InvalidAnyAttributeRestriction, derivedType); 1767 } 1768 else { 1769 derivedType.SetAttributeWildcard(anyAttribute); //complete wildcard 1770 } 1771 1772 // Add form the base 1773 foreach(XmlSchemaAttribute attributeBase in baseType.AttributeUses.Values) { 1774 XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedType.AttributeUses[attributeBase.QualifiedName]; 1775 if (attribute == null) { 1776 derivedType.AttributeUses.Add(attributeBase.QualifiedName, attributeBase); 1777 } 1778 else { 1779 if (attributeBase.Use == XmlSchemaUse.Prohibited && attribute.Use != XmlSchemaUse.Prohibited) { 1780 #if DEBUG 1781 string position = string.Empty; 1782 if (derivedType.SourceUri != null) { 1783 position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")"; 1784 } 1785 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType attributes restriction" + position); 1786 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, " Base " + DumpAttributes(baseType.AttributeUses, baseType.AttributeWildcard)); 1787 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, " Derived " + DumpAttributes(derivedType.AttributeUses, derivedType.AttributeWildcard)); 1788 #endif 1789 SendValidationEvent(Res.Sch_AttributeRestrictionProhibited, attribute); 1790 } 1791 else if (attributeBase.Use == XmlSchemaUse.Required && (attribute.Use != XmlSchemaUse.Required)) { //If base is required, derived should also be required 1792 SendValidationEvent(Res.Sch_AttributeUseInvalid, attribute); 1793 } 1794 else if (attribute.Use == XmlSchemaUse.Prohibited) { 1795 continue; 1796 } 1797 else if (attributeBase.AttributeSchemaType == null || attribute.AttributeSchemaType == null || !XmlSchemaType.IsDerivedFrom(attribute.AttributeSchemaType, attributeBase.AttributeSchemaType, XmlSchemaDerivationMethod.Empty)) { 1798 SendValidationEvent(Res.Sch_AttributeRestrictionInvalid, attribute); 1799 } 1800 else if (!IsFixedEqual(attributeBase.AttDef, attribute.AttDef)) { 1801 SendValidationEvent(Res.Sch_AttributeFixedInvalid, attribute); 1802 } 1803 } 1804 } 1805 1806 // Check additional ones are valid restriction of base's wildcard 1807 foreach(XmlSchemaAttribute attribute in derivedType.AttributeUses.Values) { 1808 XmlSchemaAttribute attributeBase = (XmlSchemaAttribute)baseType.AttributeUses[attribute.QualifiedName]; 1809 if (attributeBase != null) { 1810 continue; 1811 } 1812 if (baseAttributeWildcard == null || !baseAttributeWildcard.Allows(attribute.QualifiedName)) { 1813 #if DEBUG 1814 string position = string.Empty; 1815 if (derivedType.SourceUri != null) { 1816 position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")"; 1817 } 1818 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType attributes restriction" + position); 1819 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, " Base " + DumpAttributes(baseType.AttributeUses, baseType.AttributeWildcard)); 1820 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, " Derived " + DumpAttributes(derivedType.AttributeUses, derivedType.AttributeWildcard)); 1821 #endif 1822 SendValidationEvent(Res.Sch_AttributeRestrictionInvalidFromWildcard, attribute); 1823 } 1824 } 1825 } 1826 } 1827 else { 1828 derivedType.SetAttributeWildcard(anyAttribute); 1829 } 1830 } 1831 CheckAtrributeGroupRestriction(XmlSchemaAttributeGroup baseAttributeGroup, XmlSchemaAttributeGroup derivedAttributeGroup)1832 private void CheckAtrributeGroupRestriction(XmlSchemaAttributeGroup baseAttributeGroup, XmlSchemaAttributeGroup derivedAttributeGroup) { 1833 XmlSchemaAnyAttribute baseAnyAtt = baseAttributeGroup.AttributeWildcard; 1834 XmlSchemaAnyAttribute derivedAnyAtt = derivedAttributeGroup.AttributeWildcard; 1835 1836 if ((derivedAnyAtt != null) && (baseAnyAtt == null || !XmlSchemaAnyAttribute.IsSubset(derivedAnyAtt, baseAnyAtt) || !IsProcessContentsRestricted(null, derivedAnyAtt, baseAnyAtt))) { 1837 SendValidationEvent(Res.Sch_InvalidAnyAttributeRestriction, derivedAttributeGroup); 1838 } 1839 foreach(XmlSchemaAttribute attributeBase in baseAttributeGroup.AttributeUses.Values) { 1840 XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedAttributeGroup.AttributeUses[attributeBase.QualifiedName]; 1841 if (attribute != null) { 1842 if (attributeBase.Use == XmlSchemaUse.Prohibited && attribute.Use != XmlSchemaUse.Prohibited) { 1843 SendValidationEvent(Res.Sch_AttributeRestrictionProhibited, attribute); 1844 } 1845 else if (attributeBase.Use == XmlSchemaUse.Required && attribute.Use != XmlSchemaUse.Required) { 1846 SendValidationEvent(Res.Sch_AttributeUseInvalid, attribute); 1847 } 1848 else if (attribute.Use == XmlSchemaUse.Prohibited) { //If derived att is prohibited, continue 1849 continue; 1850 } 1851 else if (attributeBase.AttributeSchemaType == null || attribute.AttributeSchemaType == null || !XmlSchemaType.IsDerivedFrom(attribute.AttributeSchemaType, attributeBase.AttributeSchemaType, XmlSchemaDerivationMethod.Empty)) { 1852 SendValidationEvent(Res.Sch_AttributeRestrictionInvalid, attribute); 1853 } 1854 else if (!IsFixedEqual(attributeBase.AttDef, attribute.AttDef)) { 1855 SendValidationEvent(Res.Sch_AttributeFixedInvalid, attribute); 1856 } 1857 } 1858 else if (attributeBase.Use == XmlSchemaUse.Required) { 1859 SendValidationEvent(Res.Sch_NoDerivedAttribute, attributeBase.QualifiedName.ToString(), baseAttributeGroup.QualifiedName.ToString(), derivedAttributeGroup); 1860 } 1861 } 1862 // Check additional ones are valid restriction of base's wildcard 1863 foreach(XmlSchemaAttribute attribute in derivedAttributeGroup.AttributeUses.Values) { 1864 XmlSchemaAttribute attributeBase = (XmlSchemaAttribute)baseAttributeGroup.AttributeUses[attribute.QualifiedName]; 1865 if (attributeBase != null) { 1866 continue; 1867 } 1868 if (baseAnyAtt == null || !baseAnyAtt.Allows(attribute.QualifiedName)) { 1869 SendValidationEvent(Res.Sch_AttributeRestrictionInvalidFromWildcard, attribute); 1870 } 1871 } 1872 } 1873 1874 #if DEBUG DumpAttributes(XmlSchemaObjectTable attributeUses, XmlSchemaAnyAttribute attributeWildcard)1875 private string DumpAttributes(XmlSchemaObjectTable attributeUses, XmlSchemaAnyAttribute attributeWildcard) { 1876 StringBuilder sb = new StringBuilder(); 1877 sb.Append("["); 1878 bool first = true; 1879 foreach (XmlSchemaAttribute attribute in attributeUses.Values) { 1880 if (attribute.Use != XmlSchemaUse.Prohibited) { 1881 if (first) { 1882 first = false; 1883 } 1884 else { 1885 sb.Append(" "); 1886 } 1887 sb.Append(attribute.QualifiedName.Name); 1888 if (attribute.Use == XmlSchemaUse.Optional || attribute.Use == XmlSchemaUse.None) { 1889 sb.Append("?"); 1890 } 1891 } 1892 } 1893 if (attributeWildcard != null) { 1894 if (attributeUses.Count != 0) { 1895 sb.Append(" "); 1896 } 1897 sb.Append("<"); 1898 sb.Append(attributeWildcard.NamespaceList.ToString()); 1899 sb.Append(">"); 1900 } 1901 sb.Append("] - ["); 1902 first = true; 1903 foreach (XmlSchemaAttribute attribute in attributeUses.Values) { 1904 if (attribute.Use == XmlSchemaUse.Prohibited) { 1905 if (first) { 1906 first = false; 1907 } 1908 else { 1909 sb.Append(" "); 1910 } 1911 sb.Append(attribute.QualifiedName.Name); 1912 } 1913 } 1914 sb.Append("]"); 1915 return sb.ToString(); 1916 } 1917 #endif 1918 IsProcessContentsRestricted(XmlSchemaComplexType baseType, XmlSchemaAnyAttribute derivedAttributeWildcard, XmlSchemaAnyAttribute baseAttributeWildcard)1919 private bool IsProcessContentsRestricted(XmlSchemaComplexType baseType, XmlSchemaAnyAttribute derivedAttributeWildcard, XmlSchemaAnyAttribute baseAttributeWildcard) { 1920 if (baseType == XmlSchemaComplexType.AnyType) { 1921 return true; 1922 } 1923 if ((int)derivedAttributeWildcard.ProcessContentsCorrect >= (int)baseAttributeWildcard.ProcessContentsCorrect) { 1924 return true; 1925 } 1926 return false; 1927 } 1928 CompileAnyAttributeUnion(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b)1929 private XmlSchemaAnyAttribute CompileAnyAttributeUnion(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) { 1930 if (a == null) { 1931 return b; 1932 } 1933 else if (b == null) { 1934 return a; 1935 } 1936 else { 1937 XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Union(a, b, false); //false is for v1Compatd 1938 if (attribute == null) { 1939 SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a); 1940 } 1941 return attribute; 1942 } 1943 1944 } 1945 CompileAnyAttributeIntersection(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b)1946 private XmlSchemaAnyAttribute CompileAnyAttributeIntersection(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) { 1947 if (a == null) { 1948 return b; 1949 } 1950 else if (b == null) { 1951 return a; 1952 } 1953 else { 1954 XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Intersection(a, b, false); //false is for v1Compat 1955 if (attribute == null) { 1956 SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a); 1957 } 1958 return attribute; 1959 } 1960 } 1961 CompileAttribute(XmlSchemaAttribute xa)1962 private void CompileAttribute(XmlSchemaAttribute xa) { 1963 if (xa.IsProcessing) { 1964 SendValidationEvent(Res.Sch_AttributeCircularRef, xa); 1965 return; 1966 } 1967 if (xa.AttDef != null) { //already compiled? 1968 return; 1969 } 1970 xa.IsProcessing = true; 1971 SchemaAttDef decl = null; 1972 try { 1973 if (!xa.RefName.IsEmpty) { 1974 XmlSchemaAttribute a = (XmlSchemaAttribute)attributes[xa.RefName]; 1975 if (a == null) { 1976 throw new XmlSchemaException(Res.Sch_UndeclaredAttribute, xa.RefName.ToString(), xa); 1977 } 1978 CompileAttribute(a); 1979 if (a.AttDef == null) { 1980 throw new XmlSchemaException(Res.Sch_RefInvalidAttribute, xa.RefName.ToString(), xa); 1981 } 1982 decl = a.AttDef.Clone(); 1983 XmlSchemaDatatype datatype = decl.Datatype; 1984 1985 if (datatype != null) { 1986 if (a.FixedValue == null && a.DefaultValue == null) { 1987 SetDefaultFixed(xa, decl); 1988 } 1989 else if (a.FixedValue != null) { 1990 if (xa.DefaultValue != null) { 1991 throw new XmlSchemaException(Res.Sch_FixedDefaultInRef, xa.RefName.ToString(), xa); 1992 } 1993 else if (xa.FixedValue != null ) { 1994 object refFixedValue = datatype.ParseValue(xa.FixedValue, NameTable, new SchemaNamespaceManager(xa), true); 1995 if ( !datatype.IsEqual(decl.DefaultValueTyped, refFixedValue)) { 1996 throw new XmlSchemaException(Res.Sch_FixedInRef, xa.RefName.ToString(), xa); 1997 } 1998 } 1999 } 2000 } 2001 xa.SetAttributeType(a.AttributeSchemaType); 2002 } 2003 else { 2004 decl = new SchemaAttDef(xa.QualifiedName); 2005 if (xa.SchemaType != null) { 2006 CompileSimpleType(xa.SchemaType); 2007 xa.SetAttributeType(xa.SchemaType); 2008 decl.SchemaType = xa.SchemaType; 2009 decl.Datatype = xa.SchemaType.Datatype; 2010 } 2011 else if (!xa.SchemaTypeName.IsEmpty) { 2012 XmlSchemaSimpleType simpleType = GetSimpleType(xa.SchemaTypeName); 2013 if (simpleType != null) { 2014 xa.SetAttributeType(simpleType); 2015 decl.Datatype = simpleType.Datatype; 2016 decl.SchemaType = simpleType; 2017 } 2018 else { 2019 throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, xa.SchemaTypeName.ToString(), xa); 2020 } 2021 } 2022 else { 2023 decl.SchemaType = DatatypeImplementation.AnySimpleType; 2024 decl.Datatype = DatatypeImplementation.AnySimpleType.Datatype; 2025 xa.SetAttributeType(DatatypeImplementation.AnySimpleType); 2026 } 2027 //} //Removed this here since the following should be done only if RefName is Empty 2028 if (decl.Datatype != null) { 2029 decl.Datatype.VerifySchemaValid(notations, xa); 2030 } 2031 SetDefaultFixed(xa, decl); 2032 } //End of Else for !RefName.IsEmpty 2033 2034 decl.SchemaAttribute = xa; //So this is available for PSVI 2035 xa.AttDef = decl; 2036 } 2037 catch (XmlSchemaException e) { 2038 if (e.SourceSchemaObject == null) { 2039 e.SetSource(xa); 2040 } 2041 SendValidationEvent(e); 2042 xa.AttDef = SchemaAttDef.Empty; 2043 } 2044 finally { 2045 xa.IsProcessing = false; 2046 } 2047 } 2048 SetDefaultFixed(XmlSchemaAttribute xa, SchemaAttDef decl)2049 private void SetDefaultFixed(XmlSchemaAttribute xa, SchemaAttDef decl) { 2050 if (xa.DefaultValue != null || xa.FixedValue != null) { 2051 if (xa.DefaultValue != null) { 2052 decl.Presence = SchemaDeclBase.Use.Default; 2053 decl.DefaultValueRaw = decl.DefaultValueExpanded = xa.DefaultValue; 2054 } 2055 else { 2056 if (xa.Use == XmlSchemaUse.Required) { 2057 decl.Presence = SchemaDeclBase.Use.RequiredFixed; 2058 } 2059 else { 2060 decl.Presence = SchemaDeclBase.Use.Fixed; 2061 } 2062 decl.DefaultValueRaw = decl.DefaultValueExpanded = xa.FixedValue; 2063 } 2064 if(decl.Datatype != null) { 2065 if (decl.Datatype.TypeCode == XmlTypeCode.Id) { 2066 SendValidationEvent(Res.Sch_DefaultIdValue, xa); 2067 } 2068 else { 2069 decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xa), true); 2070 } 2071 } 2072 } 2073 else { 2074 switch (xa.Use) { 2075 case XmlSchemaUse.None: 2076 case XmlSchemaUse.Optional: 2077 decl.Presence = SchemaDeclBase.Use.Implied; 2078 break; 2079 case XmlSchemaUse.Required: 2080 decl.Presence = SchemaDeclBase.Use.Required; 2081 break; 2082 case XmlSchemaUse.Prohibited: 2083 break; 2084 } 2085 } 2086 } 2087 CompileIdentityConstraint(XmlSchemaIdentityConstraint xi)2088 private void CompileIdentityConstraint (XmlSchemaIdentityConstraint xi) { 2089 if (xi.IsProcessing) { 2090 xi.CompiledConstraint = CompiledIdentityConstraint.Empty; 2091 SendValidationEvent(Res.Sch_IdentityConstraintCircularRef, xi); 2092 return; 2093 } 2094 2095 if (xi.CompiledConstraint != null) { 2096 return; 2097 } 2098 2099 xi.IsProcessing = true; 2100 CompiledIdentityConstraint compic = null; 2101 try { 2102 SchemaNamespaceManager xnmgr = new SchemaNamespaceManager(xi); 2103 compic = new CompiledIdentityConstraint(xi, xnmgr); 2104 if (xi is XmlSchemaKeyref) { 2105 XmlSchemaIdentityConstraint ic = (XmlSchemaIdentityConstraint)this.identityConstraints[((XmlSchemaKeyref)xi).Refer]; 2106 if (ic == null) { 2107 throw new XmlSchemaException(Res.Sch_UndeclaredIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi); 2108 } 2109 CompileIdentityConstraint(ic); 2110 if (ic.CompiledConstraint == null) { 2111 throw new XmlSchemaException(Res.Sch_RefInvalidIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi); 2112 } 2113 // keyref has the different cardinality with the key it referred 2114 if (ic.Fields.Count != xi.Fields.Count) { 2115 throw new XmlSchemaException(Res.Sch_RefInvalidCardin, xi.QualifiedName.ToString(), xi); 2116 } 2117 // keyref can only refer to key/unique 2118 if (ic.CompiledConstraint.Role == CompiledIdentityConstraint.ConstraintRole.Keyref) { 2119 throw new XmlSchemaException(Res.Sch_ReftoKeyref, xi.QualifiedName.ToString(), xi); 2120 } 2121 } 2122 xi.CompiledConstraint = compic; 2123 } 2124 catch (XmlSchemaException e) { 2125 if (e.SourceSchemaObject == null) { 2126 e.SetSource(xi); 2127 } 2128 SendValidationEvent(e); 2129 xi.CompiledConstraint = CompiledIdentityConstraint.Empty; 2130 // empty is better than null here, stop quickly when circle referencing 2131 } 2132 finally { 2133 xi.IsProcessing = false; 2134 } 2135 2136 } 2137 CompileElement(XmlSchemaElement xe)2138 private void CompileElement(XmlSchemaElement xe) { 2139 if (xe.IsProcessing) { 2140 SendValidationEvent(Res.Sch_ElementCircularRef, xe); 2141 return; 2142 } 2143 if (xe.ElementDecl != null) { 2144 return; 2145 } 2146 xe.IsProcessing = true; 2147 SchemaElementDecl decl = null; 2148 try { 2149 if (!xe.RefName.IsEmpty) { 2150 XmlSchemaElement e = (XmlSchemaElement)elements[xe.RefName]; 2151 if (e == null) { 2152 throw new XmlSchemaException(Res.Sch_UndeclaredElement, xe.RefName.ToString(), xe); 2153 } 2154 CompileElement(e); 2155 if (e.ElementDecl == null) { 2156 throw new XmlSchemaException(Res.Sch_RefInvalidElement, xe.RefName.ToString(), xe); 2157 } 2158 xe.SetElementType(e.ElementSchemaType); 2159 decl = e.ElementDecl.Clone(); 2160 } 2161 else { 2162 if (xe.SchemaType != null) { 2163 xe.SetElementType(xe.SchemaType); 2164 } 2165 else if (!xe.SchemaTypeName.IsEmpty) { 2166 xe.SetElementType(GetAnySchemaType(xe.SchemaTypeName)); 2167 if (xe.ElementSchemaType == null) { 2168 throw new XmlSchemaException(Res.Sch_UndeclaredType, xe.SchemaTypeName.ToString(), xe); 2169 } 2170 } 2171 else if (!xe.SubstitutionGroup.IsEmpty) { 2172 XmlSchemaElement examplar = (XmlSchemaElement)elements[xe.SubstitutionGroup]; 2173 if (examplar == null) { 2174 throw new XmlSchemaException(Res.Sch_UndeclaredEquivClass, xe.SubstitutionGroup.Name.ToString(CultureInfo.InvariantCulture), xe); 2175 } 2176 if (examplar.IsProcessing) { //Circular subst group; already detected by now 2177 return; 2178 } 2179 CompileElement(examplar); 2180 if (examplar.ElementDecl == null) { //If head is invalid, fall back to AnyType 2181 xe.SetElementType(XmlSchemaComplexType.AnyType); 2182 decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone(); 2183 } 2184 else { 2185 xe.SetElementType(examplar.ElementSchemaType); 2186 decl = examplar.ElementDecl.Clone(); 2187 } 2188 } 2189 else { 2190 xe.SetElementType(XmlSchemaComplexType.AnyType); 2191 decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone(); 2192 } 2193 2194 if (decl == null) { 2195 Debug.Assert(xe.ElementSchemaType != null); 2196 if (xe.ElementSchemaType is XmlSchemaComplexType) { 2197 XmlSchemaComplexType complexType = (XmlSchemaComplexType)xe.ElementSchemaType; 2198 CompileComplexType(complexType); 2199 if (complexType.ElementDecl != null) { 2200 decl = complexType.ElementDecl.Clone(); 2201 // decl.LocalElements = complexType.LocalElementDecls; 2202 } 2203 } 2204 else if (xe.ElementSchemaType is XmlSchemaSimpleType) { 2205 XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)xe.ElementSchemaType; 2206 CompileSimpleType(simpleType); 2207 if (simpleType.ElementDecl != null) { 2208 decl = simpleType.ElementDecl.Clone(); 2209 } 2210 } 2211 } 2212 Debug.Assert(decl != null); 2213 decl.Name = xe.QualifiedName; 2214 decl.IsAbstract = xe.IsAbstract; 2215 XmlSchemaComplexType ct = xe.ElementSchemaType as XmlSchemaComplexType; 2216 if (ct != null) { 2217 decl.IsAbstract |= ct.IsAbstract; 2218 } 2219 decl.IsNillable = xe.IsNillable; 2220 decl.Block |= xe.BlockResolved; 2221 } 2222 if (decl.Datatype != null) { 2223 decl.Datatype.VerifySchemaValid(notations, xe); 2224 } 2225 2226 if (xe.DefaultValue != null || xe.FixedValue != null) { 2227 if (decl.ContentValidator != null) { 2228 if (decl.ContentValidator.ContentType == XmlSchemaContentType.TextOnly || (decl.ContentValidator.ContentType == XmlSchemaContentType.Mixed && decl.ContentValidator.IsEmptiable)) { 2229 if (xe.DefaultValue != null) { 2230 decl.Presence = SchemaDeclBase.Use.Default; 2231 decl.DefaultValueRaw = xe.DefaultValue; 2232 } 2233 else { 2234 decl.Presence = SchemaDeclBase.Use.Fixed; 2235 decl.DefaultValueRaw = xe.FixedValue; 2236 } 2237 if (decl.Datatype != null) { 2238 if (decl.Datatype.TypeCode == XmlTypeCode.Id) { 2239 SendValidationEvent(Res.Sch_DefaultIdValue, xe); 2240 } 2241 else { 2242 decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe), true); 2243 } 2244 } 2245 else { //Mixed with emptiable particle 2246 decl.DefaultValueTyped = DatatypeImplementation.AnySimpleType.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe)); 2247 } 2248 } 2249 else { 2250 throw new XmlSchemaException(Res.Sch_ElementCannotHaveValue, xe); 2251 } 2252 } 2253 } 2254 if (xe.HasConstraints) { 2255 XmlSchemaObjectCollection constraints = xe.Constraints; 2256 CompiledIdentityConstraint[] compiledConstraints = new CompiledIdentityConstraint[constraints.Count]; 2257 int idx = 0; 2258 for (int i = 0; i < constraints.Count; ++i) { 2259 XmlSchemaIdentityConstraint constraint = (XmlSchemaIdentityConstraint)constraints[i]; 2260 CompileIdentityConstraint(constraint); 2261 compiledConstraints[idx ++] = constraint.CompiledConstraint; 2262 } 2263 decl.Constraints = compiledConstraints; 2264 } 2265 decl.SchemaElement = xe; //So this is available for PSVI 2266 xe.ElementDecl = decl; 2267 } 2268 catch (XmlSchemaException e) { 2269 if (e.SourceSchemaObject == null) { 2270 e.SetSource(xe); 2271 } 2272 SendValidationEvent(e); 2273 xe.ElementDecl = SchemaElementDecl.Empty; 2274 } 2275 finally { 2276 xe.IsProcessing = false; 2277 } 2278 } 2279 CompileComplexContent(XmlSchemaComplexType complexType)2280 private ContentValidator CompileComplexContent(XmlSchemaComplexType complexType) { 2281 if (complexType.ContentType == XmlSchemaContentType.Empty) { 2282 return ContentValidator.Empty; 2283 } 2284 else if (complexType.ContentType == XmlSchemaContentType.TextOnly) { 2285 return ContentValidator.TextOnly; 2286 } 2287 XmlSchemaParticle particle = complexType.ContentTypeParticle; 2288 if (particle == null || particle == XmlSchemaParticle.Empty) { 2289 if (complexType.ContentType == XmlSchemaContentType.ElementOnly) { 2290 return ContentValidator.Empty; 2291 } 2292 else { 2293 return ContentValidator.Mixed; 2294 } 2295 } 2296 PushComplexType(complexType); 2297 if (particle is XmlSchemaAll) { 2298 XmlSchemaAll all = (XmlSchemaAll)particle; 2299 AllElementsContentValidator contentValidator = new AllElementsContentValidator(complexType.ContentType, all.Items.Count, all.MinOccurs == decimal.Zero); 2300 for (int i = 0; i < all.Items.Count; ++i) { 2301 XmlSchemaElement localElement = (XmlSchemaElement)all.Items[i]; 2302 if (!contentValidator.AddElement(localElement.QualifiedName, localElement, localElement.MinOccurs == decimal.Zero)) { 2303 SendValidationEvent(Res.Sch_DupElement, localElement.QualifiedName.ToString(), localElement); 2304 } 2305 } 2306 return contentValidator; 2307 } 2308 else { 2309 ParticleContentValidator contentValidator = new ParticleContentValidator(complexType.ContentType, CompilationSettings.EnableUpaCheck); 2310 #if DEBUG 2311 string name = complexType.Name != null ? complexType.Name : string.Empty; 2312 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceVerbose, "CompileComplexContent: "+ name + DumpContentModel(particle)); 2313 #endif 2314 try { 2315 contentValidator.Start(); 2316 complexType.HasWildCard = BuildParticleContentModel(contentValidator, particle); 2317 return contentValidator.Finish(true); 2318 } 2319 catch(UpaException e) { 2320 if (e.Particle1 is XmlSchemaElement) { 2321 if (e.Particle2 is XmlSchemaElement) { 2322 SendValidationEvent(Res.Sch_NonDeterministic, ((XmlSchemaElement)e.Particle1).QualifiedName.ToString(), (XmlSchemaElement)e.Particle2); 2323 } 2324 else { 2325 SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle2).ResolvedNamespace, ((XmlSchemaElement)e.Particle1).QualifiedName.ToString(), (XmlSchemaAny)e.Particle2); 2326 } 2327 } 2328 else { 2329 if (e.Particle2 is XmlSchemaElement) { 2330 SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle1).ResolvedNamespace, ((XmlSchemaElement)e.Particle2).QualifiedName.ToString(), (XmlSchemaElement)e.Particle2); 2331 } 2332 else { 2333 SendValidationEvent(Res.Sch_NonDeterministicAnyAny, ((XmlSchemaAny)e.Particle1).ResolvedNamespace, ((XmlSchemaAny)e.Particle2).ResolvedNamespace, (XmlSchemaAny)e.Particle2); 2334 } 2335 } 2336 return XmlSchemaComplexType.AnyTypeContentValidator; 2337 } 2338 catch(NotSupportedException) { 2339 SendValidationEvent(Res.Sch_ComplexContentModel, complexType, XmlSeverityType.Warning); 2340 return XmlSchemaComplexType.AnyTypeContentValidator; 2341 } 2342 } 2343 } 2344 2345 #if DEBUG DumpContentModel(XmlSchemaParticle particle)2346 private string DumpContentModel(XmlSchemaParticle particle) { 2347 StringBuilder sb = new StringBuilder(); 2348 DumpContentModelTo(sb, particle); 2349 return sb.ToString(); 2350 } 2351 DumpContentModelTo(StringBuilder sb, XmlSchemaParticle particle)2352 private void DumpContentModelTo(StringBuilder sb, XmlSchemaParticle particle) { 2353 if (particle is XmlSchemaElement) { 2354 sb.Append(((XmlSchemaElement)particle).QualifiedName); 2355 } 2356 else if (particle is XmlSchemaAny) { 2357 sb.Append("<"); 2358 sb.Append(((XmlSchemaAny)particle).NamespaceList.ToString()); 2359 sb.Append(">"); 2360 } 2361 else if (particle is XmlSchemaAll) { 2362 XmlSchemaAll all = (XmlSchemaAll)particle; 2363 sb.Append("["); 2364 bool first = true; 2365 for (int i = 0; i < all.Items.Count; ++i) { 2366 XmlSchemaElement localElement = (XmlSchemaElement)all.Items[i]; 2367 if (first) { 2368 first = false; 2369 } 2370 else { 2371 sb.Append(", "); 2372 } 2373 sb.Append(localElement.QualifiedName.Name); 2374 if (localElement.MinOccurs == decimal.Zero) { 2375 sb.Append("?"); 2376 } 2377 } 2378 sb.Append("]"); 2379 } 2380 else if (particle is XmlSchemaGroupBase) { 2381 XmlSchemaGroupBase gb = (XmlSchemaGroupBase)particle; 2382 sb.Append("("); 2383 string delimeter = (particle is XmlSchemaChoice) ? " | " : ", "; 2384 bool first = true; 2385 for (int i = 0; i < gb.Items.Count; ++i) { 2386 if (first) { 2387 first = false; 2388 } 2389 else { 2390 sb.Append(delimeter); 2391 } 2392 DumpContentModelTo(sb, (XmlSchemaParticle)gb.Items[i]); 2393 } 2394 sb.Append(")"); 2395 } else { 2396 Debug.Assert(particle == XmlSchemaParticle.Empty); 2397 sb.Append("<>"); 2398 } 2399 if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) { 2400 // nothing 2401 } 2402 else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) { 2403 sb.Append("?"); 2404 } 2405 else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) { 2406 sb.Append("*"); 2407 } 2408 else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) { 2409 sb.Append("+"); 2410 } 2411 else { 2412 sb.Append("{" + particle.MinOccurs.ToString(NumberFormatInfo.InvariantInfo) +", " + particle.MaxOccurs.ToString(NumberFormatInfo.InvariantInfo) + "}"); 2413 } 2414 } 2415 #endif 2416 BuildParticleContentModel(ParticleContentValidator contentValidator, XmlSchemaParticle particle)2417 private bool BuildParticleContentModel(ParticleContentValidator contentValidator, XmlSchemaParticle particle) { 2418 bool hasWildCard = false; 2419 if (particle is XmlSchemaElement) { 2420 XmlSchemaElement element = (XmlSchemaElement)particle; 2421 contentValidator.AddName(element.QualifiedName, element); 2422 } 2423 else if (particle is XmlSchemaAny) { 2424 hasWildCard = true; 2425 XmlSchemaAny any = (XmlSchemaAny)particle; 2426 contentValidator.AddNamespaceList(any.NamespaceList, any); 2427 } 2428 else if (particle is XmlSchemaGroupBase) { 2429 XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items; 2430 bool isChoice = particle is XmlSchemaChoice; 2431 contentValidator.OpenGroup(); 2432 bool first = true; 2433 for (int i = 0; i < particles.Count; ++i) { 2434 Debug.Assert(!((XmlSchemaParticle)particles[i]).IsEmpty); 2435 if (first) { 2436 first = false; 2437 } 2438 else if (isChoice) { 2439 contentValidator.AddChoice(); 2440 } 2441 else { 2442 contentValidator.AddSequence(); 2443 } 2444 hasWildCard = BuildParticleContentModel(contentValidator, (XmlSchemaParticle)particles[i]); 2445 } 2446 contentValidator.CloseGroup(); 2447 } 2448 else { 2449 Debug.Assert(false); 2450 } 2451 if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) { 2452 // nothing 2453 } 2454 else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) { 2455 contentValidator.AddQMark(); 2456 } 2457 else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) { 2458 contentValidator.AddStar(); 2459 } 2460 else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) { 2461 contentValidator.AddPlus(); 2462 } 2463 else { 2464 contentValidator.AddLeafRange(particle.MinOccurs, particle.MaxOccurs); 2465 } 2466 return hasWildCard; 2467 } 2468 CompileParticleElements(XmlSchemaComplexType complexType, XmlSchemaParticle particle)2469 private void CompileParticleElements(XmlSchemaComplexType complexType, XmlSchemaParticle particle) { 2470 if (particle is XmlSchemaElement) { 2471 XmlSchemaElement localElement = (XmlSchemaElement)particle; 2472 CompileElement(localElement); 2473 if (complexType.LocalElements[localElement.QualifiedName] == null) { 2474 complexType.LocalElements.Add(localElement.QualifiedName, localElement); 2475 } 2476 else { 2477 XmlSchemaElement element = (XmlSchemaElement)complexType.LocalElements[localElement.QualifiedName]; 2478 if (element.ElementSchemaType != localElement.ElementSchemaType) { 2479 SendValidationEvent(Res.Sch_ElementTypeCollision, particle); 2480 } 2481 } 2482 } 2483 else if (particle is XmlSchemaGroupBase) { 2484 XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items; 2485 for (int i = 0; i < particles.Count; ++i) { 2486 CompileParticleElements(complexType, (XmlSchemaParticle)particles[i]); 2487 } 2488 } 2489 } 2490 CompileParticleElements(XmlSchemaParticle particle)2491 private void CompileParticleElements(XmlSchemaParticle particle) { //For checking redefined group particle derivation 2492 if (particle is XmlSchemaElement) { 2493 XmlSchemaElement localElement = (XmlSchemaElement)particle; 2494 CompileElement(localElement); 2495 } 2496 else if (particle is XmlSchemaGroupBase) { 2497 XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items; 2498 for (int i = 0; i < particles.Count; ++i) { 2499 CompileParticleElements((XmlSchemaParticle)particles[i]); 2500 } 2501 } 2502 } 2503 CompileComplexTypeElements(XmlSchemaComplexType complexType)2504 private void CompileComplexTypeElements(XmlSchemaComplexType complexType) { 2505 if (complexType.IsProcessing) { 2506 SendValidationEvent(Res.Sch_TypeCircularRef, complexType); 2507 return; 2508 } 2509 complexType.IsProcessing = true; 2510 try { 2511 if (complexType.ContentTypeParticle != XmlSchemaParticle.Empty) { 2512 CompileParticleElements(complexType, complexType.ContentTypeParticle); 2513 } 2514 } 2515 finally { 2516 complexType.IsProcessing = false; 2517 } 2518 } 2519 GetSimpleType(XmlQualifiedName name)2520 private XmlSchemaSimpleType GetSimpleType(XmlQualifiedName name) { 2521 XmlSchemaSimpleType type = schemaTypes[name] as XmlSchemaSimpleType; 2522 if (type != null) { 2523 CompileSimpleType(type); 2524 } 2525 else { 2526 type = DatatypeImplementation.GetSimpleTypeFromXsdType(name); 2527 } 2528 return type; 2529 } 2530 GetComplexType(XmlQualifiedName name)2531 private XmlSchemaComplexType GetComplexType(XmlQualifiedName name) { 2532 XmlSchemaComplexType type = schemaTypes[name] as XmlSchemaComplexType; 2533 if (type != null) { 2534 CompileComplexType(type); 2535 } 2536 return type; 2537 } 2538 GetAnySchemaType(XmlQualifiedName name)2539 private XmlSchemaType GetAnySchemaType(XmlQualifiedName name) { 2540 XmlSchemaType type = (XmlSchemaType)schemaTypes[name]; 2541 if (type != null) { 2542 if (type is XmlSchemaComplexType) { 2543 CompileComplexType((XmlSchemaComplexType)type); 2544 } 2545 else { 2546 CompileSimpleType((XmlSchemaSimpleType)type); 2547 } 2548 return type; 2549 } 2550 else { //Its is a built-in simpleType 2551 XmlSchemaSimpleType simpleType = DatatypeImplementation.GetSimpleTypeFromXsdType(name); 2552 return simpleType; 2553 } 2554 } 2555 CopyPosition(XmlSchemaAnnotated to, XmlSchemaAnnotated from, bool copyParent)2556 private void CopyPosition(XmlSchemaAnnotated to, XmlSchemaAnnotated from, bool copyParent) { 2557 to.SourceUri = from.SourceUri; 2558 to.LinePosition = from.LinePosition; 2559 to.LineNumber = from.LineNumber; 2560 to.SetUnhandledAttributes(from.UnhandledAttributes); 2561 if (copyParent) { 2562 to.Parent = from.Parent; 2563 } 2564 } 2565 IsFixedEqual(SchemaDeclBase baseDecl, SchemaDeclBase derivedDecl)2566 private bool IsFixedEqual(SchemaDeclBase baseDecl, SchemaDeclBase derivedDecl) { 2567 2568 if (baseDecl.Presence == SchemaDeclBase.Use.Fixed || baseDecl.Presence == SchemaDeclBase.Use.RequiredFixed) { 2569 object baseFixedValue = baseDecl.DefaultValueTyped; 2570 object derivedFixedValue = derivedDecl.DefaultValueTyped; 2571 2572 Debug.Assert(baseFixedValue != null); 2573 if (derivedDecl.Presence != SchemaDeclBase.Use.Fixed && derivedDecl.Presence != SchemaDeclBase.Use.RequiredFixed) { 2574 return false; 2575 } 2576 Debug.Assert(derivedFixedValue != null); 2577 XmlSchemaDatatype baseDatatype = baseDecl.Datatype; 2578 XmlSchemaDatatype derivedDatatype = derivedDecl.Datatype; 2579 2580 if (baseDatatype.Variety == XmlSchemaDatatypeVariety.Union) { 2581 if (derivedDatatype.Variety == XmlSchemaDatatypeVariety.Union) { 2582 if ( !derivedDatatype.IsEqual(baseFixedValue, derivedFixedValue) ) { 2583 return false; 2584 } 2585 } 2586 else { //Base is union and derived is member of union 2587 XsdSimpleValue simpleFixedValue = baseDecl.DefaultValueTyped as XsdSimpleValue; 2588 Debug.Assert(simpleFixedValue != null); 2589 XmlSchemaDatatype memberType = simpleFixedValue.XmlType.Datatype; 2590 if (!memberType.IsComparable(derivedDatatype) || !derivedDatatype.IsEqual(simpleFixedValue.TypedValue, derivedFixedValue)) { //base type {Union of long & string}, derived type {int} 2591 return false; 2592 } 2593 } 2594 } 2595 else if (!derivedDatatype.IsEqual(baseFixedValue, derivedFixedValue)) { 2596 return false; 2597 } 2598 } 2599 return true; 2600 } 2601 }; 2602 2603 } // namespace System.Xml 2604