1 //------------------------------------------------------------------------------
2 // <copyright file="Compiler.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
8 namespace System.Xml.Schema {
11 using System.Collections;
12 using System.Globalization;
14 using System.Diagnostics;
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();
30 XmlSchema schemaForSchema;
32 public Compiler(XmlNameTable nameTable, ValidationEventHandler eventHandler, XmlSchema schemaForSchema, XmlSchemaCompilationSettings compilationSettings) : base(nameTable, null, eventHandler, compilationSettings) {
33 this.schemaForSchema = schemaForSchema;
36 public bool Execute(XmlSchemaSet schemaSet, SchemaInfo schemaCompiledInfo) {
39 Output(schemaCompiledInfo);
40 schemaSet.elements = elements;
41 schemaSet.attributes = attributes;
42 schemaSet.schemaTypes = schemaTypes;
43 schemaSet.substitutionGroups = examplars;
48 internal void Prepare(XmlSchema schema, bool cleanup) {
49 if (schemasToCompile[schema] != null) {
52 schemasToCompile.Add(schema, schema);
53 foreach (XmlSchemaElement element in schema.Elements.Values) {
55 CleanupElement(element);
57 AddToTable(elements, element.QualifiedName, element);
59 foreach (XmlSchemaAttribute attribute in schema.Attributes.Values) {
61 CleanupAttribute(attribute);
63 AddToTable(attributes, attribute.QualifiedName, attribute);
65 foreach (XmlSchemaGroup group in schema.Groups.Values) {
69 AddToTable(groups, group.QualifiedName, group);
71 foreach (XmlSchemaAttributeGroup attributeGroup in schema.AttributeGroups.Values) {
73 CleanupAttributeGroup(attributeGroup);
75 AddToTable(attributeGroups, attributeGroup.QualifiedName, attributeGroup);
77 foreach (XmlSchemaType type in schema.SchemaTypes.Values) {
79 XmlSchemaComplexType ct = type as XmlSchemaComplexType;
81 CleanupComplexType(ct);
84 CleanupSimpleType(type as XmlSchemaSimpleType);
87 AddToTable(schemaTypes, type.QualifiedName, type);
89 foreach (XmlSchemaNotation notation in schema.Notations.Values) {
90 AddToTable(notations, notation.QualifiedName, notation);
92 foreach (XmlSchemaIdentityConstraint ic in schema.IdentityConstraints.Values) {
93 AddToTable(identityConstraints, ic.QualifiedName, ic);
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);
110 private void Output(SchemaInfo schemaInfo) {
112 foreach(XmlSchema schema in schemasToCompile.Values) {
113 tns = schema.TargetNamespace;
117 schemaInfo.TargetNamespaces[tns] = true;
119 foreach (XmlSchemaElement element in elements.Values) {
120 schemaInfo.ElementDecls.Add(element.QualifiedName, element.ElementDecl);
122 foreach (XmlSchemaAttribute attribute in attributes.Values) {
123 schemaInfo.AttributeDecls.Add(attribute.QualifiedName, attribute.AttDef);
125 foreach (XmlSchemaType type in schemaTypes.Values) {
126 schemaInfo.ElementDeclsByType.Add(type.QualifiedName, type.ElementDecl);
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);
139 internal void ImportAllCompiledSchemas(XmlSchemaSet schemaSet) {
140 XmlSchema currentSchema;
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);
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();
158 foreach(XmlSchemaGroup group in groups.Values) {
161 foreach(XmlSchemaAttributeGroup attributeGroup in attributeGroups.Values) {
162 CompileAttributeGroup(attributeGroup);
164 foreach (XmlSchemaType type in schemaTypes.Values) {
165 XmlSchemaComplexType ct = type as XmlSchemaComplexType;
167 CompileComplexType(ct);
170 CompileSimpleType((XmlSchemaSimpleType)type);
173 foreach (XmlSchemaElement element in elements.Values) {
174 if (element.ElementDecl == null) {
175 CompileElement(element);
178 foreach (XmlSchemaAttribute attribute in attributes.Values) {
179 if (attribute.AttDef == null) {
180 CompileAttribute(attribute);
183 foreach (XmlSchemaIdentityConstraint identityConstraint in identityConstraints.Values) {
184 if (identityConstraint.CompiledConstraint == null) {
185 CompileIdentityConstraint(identityConstraint);
188 while (this.complexTypeStack.Count > 0) {
189 XmlSchemaComplexType type = (XmlSchemaComplexType)complexTypeStack.Pop();
190 CompileComplexTypeElements(type);
193 ProcessSubstitutionGroups();
195 foreach (XmlSchemaType type in schemaTypes.Values) {
196 XmlSchemaComplexType localType = type as XmlSchemaComplexType;
197 if (localType != null) {
198 CheckParticleDerivation(localType);
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);
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);
215 foreach (XmlSchemaAttributeGroup attributeGroup in attributeGroups.Values) {
216 XmlSchemaAttributeGroup baseAttributeGroup = attributeGroup.Redefined;
217 if (baseAttributeGroup != null) {
218 RecursivelyCheckRedefinedAttributeGroups(attributeGroup, baseAttributeGroup);
224 private void CleanupAttribute(XmlSchemaAttribute attribute) {
225 if (attribute.SchemaType != null) {
226 CleanupSimpleType((XmlSchemaSimpleType)attribute.SchemaType);
228 attribute.AttDef = null;
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);
240 private void CleanupComplexType(XmlSchemaComplexType complexType) {
241 if (complexType.QualifiedName == DatatypeImplementation.QnAnyType) { //if it is built-in anyType dont clean it.
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);
251 else { //simpleContent.Content is XmlSchemaSimpleContentRestriction
252 XmlSchemaSimpleContentRestriction simpleRestriction = (XmlSchemaSimpleContentRestriction)simpleContent.Content;
253 CleanupAttributes(simpleRestriction.Attributes);
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);
264 else { //XmlSchemaComplexContentRestriction
265 XmlSchemaComplexContentRestriction complexRestriction = (XmlSchemaComplexContentRestriction)complexContent.Content;
266 CleanupParticle(complexRestriction.Particle);
267 CleanupAttributes(complexRestriction.Attributes);
271 else { //equals XmlSchemaComplexContent with baseType is anyType
272 CleanupParticle(complexType.Particle);
273 CleanupAttributes(complexType.Attributes);
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;
282 //Clean up the original type if this is a redefined type
283 if (complexType.Redefined != null) {
284 CleanupComplexType(complexType.Redefined as XmlSchemaComplexType);
288 private void CleanupSimpleType(XmlSchemaSimpleType simpleType) {
289 if (simpleType == XmlSchemaType.GetBuiltInSimpleType(simpleType.TypeCode)) { //If it is a built-in simple type dont clean up
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);
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);
306 CleanupSimpleType((XmlSchemaSimpleType)element.SchemaType);
309 for (int i = 0; i < element.Constraints.Count; ++i) {
310 ((XmlSchemaIdentityConstraint)element.Constraints[i]).CompiledConstraint = null;
312 element.ElementDecl = null;
313 element.IsLocalTypeDerivationChecked = false; //clear Local element type derivation check
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);
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);
334 private void CleanupParticle(XmlSchemaParticle particle) {
335 XmlSchemaElement element = particle as XmlSchemaElement;
336 if (element != null) {
337 CleanupElement(element);
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]);
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);
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);
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);
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);
376 //Check the subst groups that we just built
377 foreach (XmlSchemaSubstitutionGroup substitutionGroup in examplars.Values) {
378 CompileSubstitutionGroup(substitutionGroup);
382 private void CompileSubstitutionGroup(XmlSchemaSubstitutionGroup substitutionGroup) {
383 if (substitutionGroup.IsProcessing && substitutionGroup.Members.Count > 0) {
384 SendValidationEvent(Res.Sch_SubstitutionCircularRef, (XmlSchemaElement)substitutionGroup.Members[0]);
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
392 substitutionGroup.IsProcessing = true;
394 if (examplar.FinalResolved == XmlSchemaDerivationMethod.All) {
395 SendValidationEvent(Res.Sch_InvalidExamplar, examplar);
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];
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();
411 newMembers.Add(g.Members[j]);
417 if (newMembers != null) {
418 for (int i = 0; i < newMembers.Count; ++i) {
419 substitutionGroup.Members.Add(newMembers[i]);
422 substitutionGroup.Members.Add(examplar); // Compiled mark
425 substitutionGroup.IsProcessing = false;
429 private void RecursivelyCheckRedefinedGroups(XmlSchemaGroup redefinedGroup, XmlSchemaGroup baseGroup) {
430 if (baseGroup.Redefined != null) {
431 RecursivelyCheckRedefinedGroups(baseGroup, baseGroup.Redefined);
433 if (redefinedGroup.SelfReferenceCount == 0) {
434 if (baseGroup.CanonicalParticle == null) {
435 baseGroup.CanonicalParticle = CannonicalizeParticle(baseGroup.Particle, true);
437 if (redefinedGroup.CanonicalParticle == null) {
438 redefinedGroup.CanonicalParticle = CannonicalizeParticle(redefinedGroup.Particle, true);
440 CompileParticleElements(redefinedGroup.CanonicalParticle);
441 CompileParticleElements(baseGroup.CanonicalParticle);
442 CheckParticleDerivation(redefinedGroup.CanonicalParticle, baseGroup.CanonicalParticle);
446 private void RecursivelyCheckRedefinedAttributeGroups(XmlSchemaAttributeGroup attributeGroup, XmlSchemaAttributeGroup baseAttributeGroup) {
447 if (baseAttributeGroup.Redefined != null) {
448 RecursivelyCheckRedefinedAttributeGroups(baseAttributeGroup, baseAttributeGroup.Redefined);
450 if (attributeGroup.SelfReferenceCount == 0) {
451 CompileAttributeGroup(baseAttributeGroup);
452 CompileAttributeGroup(attributeGroup);
453 CheckAtrributeGroupRestriction(baseAttributeGroup, attributeGroup);
457 private void CompileGroup(XmlSchemaGroup group) {
458 if (group.IsProcessing) {
459 SendValidationEvent(Res.Sch_GroupCircularRef, group);
460 group.CanonicalParticle = XmlSchemaParticle.Empty;
463 group.IsProcessing = true;
464 if (group.CanonicalParticle == null) {
465 group.CanonicalParticle = CannonicalizeParticle(group.Particle, true);
467 Debug.Assert(group.CanonicalParticle != null);
468 group.IsProcessing = false; //Not enclosung in try -finally as cannonicalizeParticle will not throw exception
472 private void CompileSimpleType(XmlSchemaSimpleType simpleType) {
473 if (simpleType.IsProcessing) {
474 throw new XmlSchemaException(Res.Sch_TypeCircularRef, simpleType);
476 if (simpleType.ElementDecl != null) { // already compiled
479 simpleType.IsProcessing = true;
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;
491 XmlSchemaSimpleType type = GetSimpleType(list.ItemTypeName);
493 if ((type.FinalResolved & XmlSchemaDerivationMethod.List) != 0) {
494 SendValidationEvent(Res.Sch_BaseFinalList, simpleType);
496 list.BaseItemType = type;
497 datatype = type.Datatype;
500 throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, list.ItemTypeName.ToString(), list);
503 simpleType.SetDatatype(datatype.DeriveByList(simpleType));
504 simpleType.SetDerivedBy(XmlSchemaDerivationMethod.List);
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;
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;
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);
526 XmlSchemaSimpleType type = GetSimpleType(restriction.BaseTypeName);
528 if ((type.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
529 SendValidationEvent(Res.Sch_BaseFinalRestriction, simpleType);
531 simpleType.SetBaseSchemaType(type);
532 datatype = type.Datatype;
535 throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, restriction.BaseTypeName.ToString(), restriction);
538 simpleType.SetDatatype(datatype.DeriveByRestriction(restriction.Facets, NameTable, simpleType));
539 simpleType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
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);
548 catch (XmlSchemaException e) {
549 if (e.SourceSchemaObject == null) {
550 e.SetSource(simpleType);
552 SendValidationEvent(e);
553 simpleType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype);
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;
565 private XmlSchemaSimpleType[] CompileBaseMemberTypes(XmlSchemaSimpleType simpleType) {
566 XmlSchemaSimpleType unionMember;
567 ArrayList memberTypeDefinitions = new ArrayList();
569 XmlSchemaSimpleTypeUnion mainUnion = (XmlSchemaSimpleTypeUnion)simpleType.Content;
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);
579 else { //its list or atomic
580 memberTypeDefinitions.Add(unionMember);
582 //Check derivation method of the member that is referenced
583 if ((unionMember.FinalResolved & XmlSchemaDerivationMethod.Union) != 0) {
584 SendValidationEvent(Res.Sch_BaseFinalUnion, simpleType);
588 throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, mainMemberTypes[i].ToString(), mainUnion);
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);
602 else { //its list or atomic
603 memberTypeDefinitions.Add(st);
608 mainUnion.SetBaseMemberTypes(memberTypeDefinitions.ToArray(typeof(XmlSchemaSimpleType)) as XmlSchemaSimpleType[]);
609 return mainUnion.BaseMemberTypes;
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);
618 Datatype_union uniondt = unionMember.Datatype as Datatype_union;
619 memberTypeDefinitions.AddRange(uniondt.BaseMemberTypes);
623 private void CompileComplexType(XmlSchemaComplexType complexType) {
624 if (complexType.ElementDecl != null) { //already compiled
627 if (complexType.IsProcessing) {
628 SendValidationEvent(Res.Sch_TypeCircularRef, complexType);
631 complexType.IsProcessing = true;
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);
640 else { //simpleContent.Content is XmlSchemaSimpleContentRestriction
641 CompileSimpleContentRestriction(complexType, (XmlSchemaSimpleContentRestriction)simpleContent.Content);
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);
649 else { // complexContent.Content is XmlSchemaComplexContentRestriction
650 CompileComplexContentRestriction(complexType, complexContent, (XmlSchemaComplexContentRestriction)complexContent.Content);
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));
661 if (complexType.ContainsIdAttribute(true)) {
662 SendValidationEvent(Res.Sch_TwoIdAttrUses, complexType);
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);
678 if (!decl.AttDefs.ContainsKey(attribute.QualifiedName) && attribute.AttDef != null && attribute.AttDef.Name != XmlQualifiedName.Empty && attribute.AttDef != SchemaAttDef.Empty) {
679 decl.AddAttDef(attribute.AttDef);
683 complexType.ElementDecl = decl;
686 complexType.IsProcessing = false;
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);
700 XmlSchemaType bto = GetAnySchemaType(simpleExtension.BaseTypeName);
702 SendValidationEvent(Res.Sch_UndeclaredType, simpleExtension.BaseTypeName.ToString(), simpleExtension);
705 complexType.SetBaseSchemaType(bto);
706 complexType.SetDatatype(bto.Datatype);
708 baseType = bto as XmlSchemaComplexType;
710 if (baseType != null) {
711 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) {
712 SendValidationEvent(Res.Sch_BaseFinalExtension, complexType);
714 if (baseType.ContentType != XmlSchemaContentType.TextOnly) {
715 SendValidationEvent(Res.Sch_NotSimpleContent, complexType);
718 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension);
719 CompileLocalAttributes(baseType, complexType, simpleExtension.Attributes, simpleExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension);
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;
731 baseType = GetComplexType(simpleRestriction.BaseTypeName);
732 if (baseType == null) {
733 SendValidationEvent(Res.Sch_UndefBaseRestriction, simpleRestriction.BaseTypeName.ToString(), simpleRestriction);
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.
743 CompileSimpleType(simpleRestriction.BaseType);
744 if(!XmlSchemaType.IsDerivedFromDatatype(simpleRestriction.BaseType.Datatype, baseType.Datatype, XmlSchemaDerivationMethod.None)) {
745 SendValidationEvent(Res.Sch_DerivedNotFromBase, simpleRestriction);
747 datatype = simpleRestriction.BaseType.Datatype;
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;
757 SendValidationEvent(Res.Sch_NeedSimpleTypeChild, simpleRestriction);
761 SendValidationEvent(Res.Sch_NotSimpleContent, complexType);
764 if (baseType != null && baseType.ElementDecl != null) {
765 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
766 SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType);
769 if (baseType != null) {
770 complexType.SetBaseSchemaType(baseType);
772 if (datatype != null) {
774 complexType.SetDatatype(datatype.DeriveByRestriction(simpleRestriction.Facets, NameTable, complexType));
776 catch (XmlSchemaException e) {
777 if (e.SourceSchemaObject == null) {
778 e.SetSource(complexType);
780 SendValidationEvent(e);
781 complexType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype);
784 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
785 CompileLocalAttributes(baseType, complexType, simpleRestriction.Attributes, simpleRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
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);
795 baseType = GetComplexType(complexExtension.BaseTypeName);
796 if (baseType == null) {
797 SendValidationEvent(Res.Sch_UndefBaseExtension, complexExtension.BaseTypeName.ToString(), complexExtension);
801 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) {
802 SendValidationEvent(Res.Sch_BaseFinalExtension, complexType);
804 CompileLocalAttributes(baseType, complexType, complexExtension.Attributes, complexExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension);
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));
816 complexType.SetContentTypeParticle(baseParticle);
820 complexType.SetContentTypeParticle(extendedParticle);
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);
832 complexType.SetContentType(contentType);
834 if (baseType.ContentType != XmlSchemaContentType.Empty && complexType.ContentType != baseType.ContentType) { //If base is empty, do not check
835 SendValidationEvent(Res.Sch_DifContentType, complexType);
838 complexType.SetBaseSchemaType(baseType);
839 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension);
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);
849 baseType = GetComplexType(complexRestriction.BaseTypeName);
850 if (baseType == null) {
851 SendValidationEvent(Res.Sch_UndefBaseRestriction, complexRestriction.BaseTypeName.ToString(), complexRestriction);
855 complexType.SetBaseSchemaType(baseType);
856 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
857 SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType);
859 CompileLocalAttributes(baseType, complexType, complexRestriction.Attributes, complexRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
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);
871 case XmlSchemaContentType.Mixed:
872 if (baseType.ContentType != XmlSchemaContentType.Mixed) {
873 SendValidationEvent(Res.Sch_InvalidContentRestrictionDetailed, Res.GetString(Res.Sch_InvalidBaseToMixed), complexType);
877 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
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)) {
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 + ")";
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));
898 if (restrictionErrorMsg != null) {
899 SendValidationEvent(Res.Sch_InvalidParticleRestrictionDetailed, restrictionErrorMsg, complexType);
902 SendValidationEvent(Res.Sch_InvalidParticleRestriction, complexType);
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
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);
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);
929 SendValidationEvent(Res.Sch_InvalidParticleRestriction, derivedParticle);
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);
941 return XmlSchemaParticle.Empty;
946 private XmlSchemaParticle CannonicalizeParticle(XmlSchemaParticle particle, bool root) {
947 if (particle == null || particle.IsEmpty) {
948 return XmlSchemaParticle.Empty;
950 else if (particle is XmlSchemaElement) {
951 //return CannonicalizeElement((XmlSchemaElement)particle, substitution);
954 else if (particle is XmlSchemaGroupRef) {
955 return CannonicalizeGroupRef((XmlSchemaGroupRef)particle, root);
957 else if (particle is XmlSchemaAll) {
958 return CannonicalizeAll((XmlSchemaAll)particle, root);
960 else if (particle is XmlSchemaChoice) {
961 return CannonicalizeChoice((XmlSchemaChoice)particle, root);
963 else if (particle is XmlSchemaSequence) {
964 return CannonicalizeSequence((XmlSchemaSequence)particle, root);
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) {
978 XmlSchemaChoice choice = new XmlSchemaChoice();
979 for (int i = 0; i < substitutionGroup.Members.Count; ++i) {
980 choice.Items.Add((XmlSchemaElement)substitutionGroup.Members[i]);
982 choice.MinOccurs = element.MinOccurs;
983 choice.MaxOccurs = element.MaxOccurs;
984 CopyPosition(choice, element, false);
993 private XmlSchemaParticle CannonicalizeGroupRef(XmlSchemaGroupRef groupRef, bool root) {
994 XmlSchemaGroup group;
995 if (groupRef.Redefined != null) {
996 group = groupRef.Redefined;
999 group = (XmlSchemaGroup)groups[groupRef.RefName];
1001 if (group == null) {
1002 SendValidationEvent(Res.Sch_UndefGroupRef, groupRef.RefName.ToString(), groupRef);
1003 return XmlSchemaParticle.Empty;
1005 if (group.CanonicalParticle == null) {
1006 CompileGroup(group);
1008 if (group.CanonicalParticle == XmlSchemaParticle.Empty) {
1009 return XmlSchemaParticle.Empty;
1011 XmlSchemaGroupBase groupBase = (XmlSchemaGroupBase)group.CanonicalParticle;
1012 if (groupBase is XmlSchemaAll) {
1014 SendValidationEvent(Res.Sch_AllRefNotRoot, "", groupRef);
1015 return XmlSchemaParticle.Empty;
1017 if (groupRef.MinOccurs > decimal.One || groupRef.MaxOccurs != decimal.One) {
1018 SendValidationEvent(Res.Sch_AllRefMinMax, groupRef);
1019 return XmlSchemaParticle.Empty;
1022 else if (groupBase is XmlSchemaChoice && groupBase.Items.Count == 0) {
1023 if (groupRef.MinOccurs != decimal.Zero) {
1024 SendValidationEvent(Res.Sch_EmptyChoice, groupRef, XmlSeverityType.Warning);
1026 return XmlSchemaParticle.Empty;
1028 XmlSchemaGroupBase groupRefBase = (
1029 (groupBase is XmlSchemaSequence) ? (XmlSchemaGroupBase)new XmlSchemaSequence() :
1030 (groupBase is XmlSchemaChoice) ? (XmlSchemaGroupBase)new XmlSchemaChoice() :
1031 (XmlSchemaGroupBase)new XmlSchemaAll()
1033 groupRefBase.MinOccurs = groupRef.MinOccurs;
1034 groupRefBase.MaxOccurs = groupRef.MaxOccurs;
1035 CopyPosition(groupRefBase, groupRef, true);
1037 for (int i = 0; i < groupBase.Items.Count; ++i) {
1038 groupRefBase.Items.Add(groupBase.Items[i]);
1040 groupRef.SetParticle(groupRefBase);
1041 return groupRefBase;
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);
1058 if (all.Items.Count == 0) {
1059 return XmlSchemaParticle.Empty;
1062 SendValidationEvent(Res.Sch_NotAllAlone, all);
1063 return XmlSchemaParticle.Empty;
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]);
1087 newChoice.Items.Add(p1);
1093 if (!root && choice.Items.Count == 0) {
1094 if (choice.MinOccurs != decimal.Zero) {
1095 SendValidationEvent(Res.Sch_EmptyChoice, oldChoice, XmlSeverityType.Warning);
1097 return XmlSchemaParticle.Empty;
1099 else if (!root && choice.Items.Count == 1 && choice.MinOccurs == decimal.One && choice.MaxOccurs == decimal.One) {
1100 return (XmlSchemaParticle)choice.Items[0];
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]);
1123 newSequence.Items.Add(p1);
1127 sequence = newSequence;
1129 if (sequence.Items.Count == 0) {
1130 return XmlSchemaParticle.Empty;
1132 else if (!root && sequence.Items.Count == 1 && sequence.MinOccurs == decimal.One && sequence.MaxOccurs == decimal.One) {
1133 return (XmlSchemaParticle)sequence.Items[0];
1140 private XmlSchemaParticle CannonicalizePointlessRoot(XmlSchemaParticle particle) {
1141 if (particle == null) {
1144 XmlSchemaSequence xss;
1145 XmlSchemaChoice xsc;
1147 decimal one = decimal.One;
1149 if ( (xss = (particle as XmlSchemaSequence)) != null ) {
1150 XmlSchemaObjectCollection items = xss.Items;
1151 int count = items.Count;
1153 if (xss.MinOccurs == one && xss.MaxOccurs == one) {
1154 return (XmlSchemaParticle)items[0];
1158 else if ( (xsc = (particle as XmlSchemaChoice)) != null ) {
1159 XmlSchemaObjectCollection items = xsc.Items;
1160 int count = items.Count;
1163 if (xsc.MinOccurs == one && xsc.MaxOccurs == one) {
1164 return (XmlSchemaParticle)items[0];
1167 else if (count == 0) {
1168 return XmlSchemaParticle.Empty;
1171 else if ( (xsa = (particle as XmlSchemaAll)) != null ) {
1172 XmlSchemaObjectCollection items = xsa.Items;
1173 int count = items.Count;
1176 if (xsa.MinOccurs == one && xsa.MaxOccurs == one) {
1177 return (XmlSchemaParticle)items[0];
1185 private bool IsValidRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) {
1186 if (derivedParticle == baseParticle) {
1189 else if (derivedParticle == null || derivedParticle == XmlSchemaParticle.Empty) {
1190 return IsParticleEmptiable(baseParticle);
1192 else if (baseParticle == null || baseParticle == XmlSchemaParticle.Empty) {
1195 if (derivedParticle is XmlSchemaElement) { //check for derived element being head of substitutionGroup
1196 XmlSchemaElement derivedElem = (XmlSchemaElement)derivedParticle;
1197 derivedParticle = CannonicalizeElement(derivedElem);
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);
1206 else if (derivedParticle is XmlSchemaElement) {
1207 return IsElementFromElement((XmlSchemaElement)derivedParticle, baseElem);
1210 restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForElem);
1214 else if (baseParticle is XmlSchemaAny) {
1215 if (derivedParticle is XmlSchemaElement) {
1216 return IsElementFromAny((XmlSchemaElement)derivedParticle, (XmlSchemaAny)baseParticle);
1218 else if (derivedParticle is XmlSchemaAny) {
1219 return IsAnyFromAny((XmlSchemaAny)derivedParticle, (XmlSchemaAny)baseParticle);
1222 return IsGroupBaseFromAny((XmlSchemaGroupBase)derivedParticle, (XmlSchemaAny)baseParticle);
1225 else if (baseParticle is XmlSchemaAll) {
1226 if (derivedParticle is XmlSchemaElement) {
1227 return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle);
1229 else if (derivedParticle is XmlSchemaAll) {
1230 if(IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true)) {
1234 else if (derivedParticle is XmlSchemaSequence) {
1235 if(IsSequenceFromAll((XmlSchemaSequence)derivedParticle, (XmlSchemaAll)baseParticle)) {
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));
1240 else if (derivedParticle is XmlSchemaChoice || derivedParticle is XmlSchemaAny) {
1241 restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForAll);
1245 else if (baseParticle is XmlSchemaChoice ) {
1246 if (derivedParticle is XmlSchemaElement) {
1247 return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase) baseParticle);
1249 else if (derivedParticle is XmlSchemaChoice) {
1250 XmlSchemaChoice baseChoice = baseParticle as XmlSchemaChoice;
1251 XmlSchemaChoice derivedChoice = derivedParticle as XmlSchemaChoice;
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);
1256 if(IsGroupBaseFromGroupBase(derivedChoice, baseChoice, false)) {
1260 else if (derivedParticle is XmlSchemaSequence) {
1261 if(IsSequenceFromChoice((XmlSchemaSequence)derivedParticle, (XmlSchemaChoice) baseParticle)) {
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));
1267 restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForChoice);
1271 else if (baseParticle is XmlSchemaSequence) {
1272 if (derivedParticle is XmlSchemaElement) {
1273 return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle);
1275 else if (derivedParticle is XmlSchemaSequence || (derivedParticle is XmlSchemaAll && ((XmlSchemaGroupBase)derivedParticle).Items.Count ==1)) {
1276 if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true)) {
1281 restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForSeq);
1286 Debug.Assert(false);
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;
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);
1319 private bool IsElementFromAny(XmlSchemaElement derivedElement, XmlSchemaAny baseAny) {
1320 if (!baseAny.Allows(derivedElement.QualifiedName)) {
1321 restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromAnyRule1, derivedElement.QualifiedName.ToString());
1324 if (!IsValidOccurrenceRangeRestriction(derivedElement, baseAny)) {
1325 restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromAnyRule2, derivedElement.QualifiedName.ToString());
1331 private bool IsAnyFromAny(XmlSchemaAny derivedAny, XmlSchemaAny baseAny) {
1332 if (!IsValidOccurrenceRangeRestriction(derivedAny, baseAny)) {
1333 restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule1);
1336 if (!NamespaceList.IsSubset(derivedAny.NamespaceList, baseAny.NamespaceList)) {
1337 restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule2);
1340 if ((int)derivedAny.ProcessContentsCorrect < (int)baseAny.ProcessContentsCorrect) {
1341 restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule3);
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));
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;
1364 baseAny.MinOccursString = minOccursAny;
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
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)) {
1381 else { //Fall back to regular checking
1382 return IsElementFromGroupBase(derivedElement, baseGroupBase);
1387 private bool IsElementFromGroupBaseHack(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase, bool skipEmptableOnly) {
1388 bool isMatched = false;
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;
1399 baseParticle.MaxOccurs *= baseGroupBase.MaxOccurs;
1401 isMatched = IsValidRestriction(derivedElement, baseParticle);
1402 baseParticle.MinOccursString = minOccursElement;
1403 baseParticle.MaxOccursString = maxOccursElement;
1405 if (!isMatched && skipEmptableOnly && !IsParticleEmptiable(baseParticle)) {
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)) {
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));
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)) {
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));
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)) {
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));
1446 private bool IsChoiceFromChoiceSubstGroup(XmlSchemaChoice derivedChoice, XmlSchemaChoice baseChoice) {
1447 if (!IsValidOccurrenceRangeRestriction(derivedChoice, baseChoice)) {
1448 restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestRangeInvalid);
1451 for (int i = 0; i < derivedChoice.Items.Count; ++i) {
1452 if (GetMappingParticle((XmlSchemaParticle)derivedChoice.Items[i], baseChoice.Items) < 0) {
1459 private bool IsGroupBaseFromGroupBase(XmlSchemaGroupBase derivedGroupBase, XmlSchemaGroupBase baseGroupBase, bool skipEmptableOnly) {
1460 if (!IsValidOccurrenceRangeRestriction(derivedGroupBase, baseGroupBase)) {
1461 restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestRangeInvalid);
1464 if (derivedGroupBase.Items.Count > baseGroupBase.Items.Count) {
1465 restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestNoMap);
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)) {
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);
1482 if (count < derivedGroupBase.Items.Count) {
1488 private bool IsSequenceFromAll(XmlSchemaSequence derivedSequence, XmlSchemaAll baseAll) {
1489 if (!IsValidOccurrenceRangeRestriction(derivedSequence, baseAll) || derivedSequence.Items.Count > baseAll.Items.Count) {
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);
1507 for (int i = 0; i < baseAll.Items.Count; i++) {
1508 if (!map[i] && !IsParticleEmptiable((XmlSchemaParticle)baseAll.Items[i])) {
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;
1522 maxOccurs = derivedSequence.MaxOccurs * derivedSequence.Items.Count;
1524 if (!IsValidOccurrenceRangeRestriction(minOccurs, maxOccurs, baseChoice.MinOccurs, baseChoice.MaxOccurs) || derivedSequence.Items.Count > baseChoice.Items.Count) {
1527 for (int i = 0; i < derivedSequence.Items.Count; ++i) {
1528 if (GetMappingParticle((XmlSchemaParticle)derivedSequence.Items[i], baseChoice.Items) < 0)
1534 private bool IsValidOccurrenceRangeRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) {
1535 return IsValidOccurrenceRangeRestriction(derivedParticle.MinOccurs, derivedParticle.MaxOccurs, baseParticle.MinOccurs, baseParticle.MaxOccurs);
1538 private bool IsValidOccurrenceRangeRestriction(decimal minOccurs, decimal maxOccurs, decimal baseMinOccurs, decimal baseMaxOccurs) {
1539 return (baseMinOccurs <= minOccurs) && (maxOccurs <= baseMaxOccurs);
1542 private int GetMappingParticle(XmlSchemaParticle particle, XmlSchemaObjectCollection collection) {
1543 for (int i = 0; i < collection.Count; i++) {
1544 if (IsValidRestriction(particle, (XmlSchemaParticle)collection[i]))
1550 private bool IsParticleEmptiable(XmlSchemaParticle particle) {
1551 decimal minOccurs, maxOccurs;
1552 CalculateEffectiveTotalRange(particle, out minOccurs, out maxOccurs);
1553 return minOccurs == decimal.Zero;
1556 private void CalculateEffectiveTotalRange(XmlSchemaParticle particle, out decimal minOccurs, out decimal maxOccurs) {
1557 XmlSchemaChoice choice = particle as XmlSchemaChoice;
1559 if (particle is XmlSchemaElement || particle is XmlSchemaAny) {
1560 minOccurs = particle.MinOccurs;
1561 maxOccurs = particle.MaxOccurs;
1563 else if (choice != null) {
1564 if (choice.Items.Count == 0) {
1565 minOccurs = maxOccurs = decimal.Zero;
1568 minOccurs = decimal.MaxValue;
1569 maxOccurs = decimal.Zero;
1570 for (int i = 0; i < choice.Items.Count; ++i) {
1572 CalculateEffectiveTotalRange((XmlSchemaParticle)choice.Items[i], out min, out max);
1573 if (min < minOccurs) {
1576 if (max > maxOccurs) {
1580 minOccurs *= particle.MinOccurs;
1581 if (maxOccurs != decimal.MaxValue) {
1582 if (particle.MaxOccurs == decimal.MaxValue)
1583 maxOccurs = decimal.MaxValue;
1585 maxOccurs *= particle.MaxOccurs;
1590 XmlSchemaObjectCollection collection = ((XmlSchemaGroupBase)particle).Items;
1591 if (collection.Count == 0) {
1592 minOccurs = maxOccurs = decimal.Zero;
1597 for (int i = 0; i < collection.Count; ++i) {
1599 CalculateEffectiveTotalRange((XmlSchemaParticle)collection[i], out min, out max);
1601 if (maxOccurs != decimal.MaxValue) {
1602 if (max == decimal.MaxValue)
1603 maxOccurs = decimal.MaxValue;
1608 minOccurs *= particle.MinOccurs;
1609 if (maxOccurs != decimal.MaxValue) {
1610 if (particle.MaxOccurs == decimal.MaxValue)
1611 maxOccurs = decimal.MaxValue;
1613 maxOccurs *= particle.MaxOccurs;
1619 private void PushComplexType(XmlSchemaComplexType complexType) {
1620 this.complexTypeStack.Push(complexType);
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;
1628 else if (particle != null && !particle.IsEmpty) {
1629 return XmlSchemaContentType.ElementOnly;
1632 return XmlSchemaContentType.Empty;
1636 private void CompileAttributeGroup(XmlSchemaAttributeGroup attributeGroup) {
1637 if (attributeGroup.IsProcessing) {
1638 SendValidationEvent(Res.Sch_AttributeGroupCircularRef, attributeGroup);
1641 if (attributeGroup.AttributeUses.Count > 0) {// already checked
1644 attributeGroup.IsProcessing = true;
1645 XmlSchemaAnyAttribute anyAttribute = attributeGroup.AnyAttribute;
1648 for (int i = 0; i < attributeGroup.Attributes.Count; ++i) {
1649 XmlSchemaAttribute attr = attributeGroup.Attributes[i] as XmlSchemaAttribute;
1651 if (attr.Use == XmlSchemaUse.Prohibited) {
1654 CompileAttribute(attr);
1655 if (attributeGroup.AttributeUses[attr.QualifiedName] == null) {
1656 attributeGroup.AttributeUses.Add(attr.QualifiedName, attr);
1659 SendValidationEvent(Res.Sch_DupAttributeUse, attr.QualifiedName.ToString(), attr);
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;
1669 attributeGroupResolved = (XmlSchemaAttributeGroup)attributeGroups[attributeGroupRef.RefName];
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);
1678 SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attribute);
1681 anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroupResolved.AttributeWildcard);
1684 SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef);
1688 attributeGroup.AttributeWildcard = anyAttribute;
1691 attributeGroup.IsProcessing = false;
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;
1700 if (attr.Use != XmlSchemaUse.Prohibited) {
1701 CompileAttribute(attr);
1703 if (attr.Use != XmlSchemaUse.Prohibited ||
1704 (attr.Use == XmlSchemaUse.Prohibited && derivedBy == XmlSchemaDerivationMethod.Restriction && baseType != XmlSchemaComplexType.AnyType)) {
1706 if (derivedType.AttributeUses[attr.QualifiedName] == null) {
1707 derivedType.AttributeUses.Add(attr.QualifiedName, attr);
1710 SendValidationEvent(Res.Sch_DupAttributeUse, attr.QualifiedName.ToString(), attr);
1714 SendValidationEvent(Res.Sch_AttributeIgnored, attr.QualifiedName.ToString(), attr, XmlSeverityType.Warning);
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);
1730 SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attributeGroupRef);
1734 SendValidationEvent(Res.Sch_AttributeIgnored, attribute.QualifiedName.ToString(), attribute, XmlSeverityType.Warning);
1738 anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroup.AttributeWildcard);
1741 SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef);
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);
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);
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);
1769 derivedType.SetAttributeWildcard(anyAttribute); //complete wildcard
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);
1779 if (attributeBase.Use == XmlSchemaUse.Prohibited && attribute.Use != XmlSchemaUse.Prohibited) {
1781 string position = string.Empty;
1782 if (derivedType.SourceUri != null) {
1783 position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")";
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));
1789 SendValidationEvent(Res.Sch_AttributeRestrictionProhibited, attribute);
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);
1794 else if (attribute.Use == XmlSchemaUse.Prohibited) {
1797 else if (attributeBase.AttributeSchemaType == null || attribute.AttributeSchemaType == null || !XmlSchemaType.IsDerivedFrom(attribute.AttributeSchemaType, attributeBase.AttributeSchemaType, XmlSchemaDerivationMethod.Empty)) {
1798 SendValidationEvent(Res.Sch_AttributeRestrictionInvalid, attribute);
1800 else if (!IsFixedEqual(attributeBase.AttDef, attribute.AttDef)) {
1801 SendValidationEvent(Res.Sch_AttributeFixedInvalid, attribute);
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) {
1812 if (baseAttributeWildcard == null || !baseAttributeWildcard.Allows(attribute.QualifiedName)) {
1814 string position = string.Empty;
1815 if (derivedType.SourceUri != null) {
1816 position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")";
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));
1822 SendValidationEvent(Res.Sch_AttributeRestrictionInvalidFromWildcard, attribute);
1828 derivedType.SetAttributeWildcard(anyAttribute);
1832 private void CheckAtrributeGroupRestriction(XmlSchemaAttributeGroup baseAttributeGroup, XmlSchemaAttributeGroup derivedAttributeGroup) {
1833 XmlSchemaAnyAttribute baseAnyAtt = baseAttributeGroup.AttributeWildcard;
1834 XmlSchemaAnyAttribute derivedAnyAtt = derivedAttributeGroup.AttributeWildcard;
1836 if ((derivedAnyAtt != null) && (baseAnyAtt == null || !XmlSchemaAnyAttribute.IsSubset(derivedAnyAtt, baseAnyAtt) || !IsProcessContentsRestricted(null, derivedAnyAtt, baseAnyAtt))) {
1837 SendValidationEvent(Res.Sch_InvalidAnyAttributeRestriction, derivedAttributeGroup);
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);
1845 else if (attributeBase.Use == XmlSchemaUse.Required && attribute.Use != XmlSchemaUse.Required) {
1846 SendValidationEvent(Res.Sch_AttributeUseInvalid, attribute);
1848 else if (attribute.Use == XmlSchemaUse.Prohibited) { //If derived att is prohibited, continue
1851 else if (attributeBase.AttributeSchemaType == null || attribute.AttributeSchemaType == null || !XmlSchemaType.IsDerivedFrom(attribute.AttributeSchemaType, attributeBase.AttributeSchemaType, XmlSchemaDerivationMethod.Empty)) {
1852 SendValidationEvent(Res.Sch_AttributeRestrictionInvalid, attribute);
1854 else if (!IsFixedEqual(attributeBase.AttDef, attribute.AttDef)) {
1855 SendValidationEvent(Res.Sch_AttributeFixedInvalid, attribute);
1858 else if (attributeBase.Use == XmlSchemaUse.Required) {
1859 SendValidationEvent(Res.Sch_NoDerivedAttribute, attributeBase.QualifiedName.ToString(), baseAttributeGroup.QualifiedName.ToString(), derivedAttributeGroup);
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) {
1868 if (baseAnyAtt == null || !baseAnyAtt.Allows(attribute.QualifiedName)) {
1869 SendValidationEvent(Res.Sch_AttributeRestrictionInvalidFromWildcard, attribute);
1875 private string DumpAttributes(XmlSchemaObjectTable attributeUses, XmlSchemaAnyAttribute attributeWildcard) {
1876 StringBuilder sb = new StringBuilder();
1879 foreach (XmlSchemaAttribute attribute in attributeUses.Values) {
1880 if (attribute.Use != XmlSchemaUse.Prohibited) {
1887 sb.Append(attribute.QualifiedName.Name);
1888 if (attribute.Use == XmlSchemaUse.Optional || attribute.Use == XmlSchemaUse.None) {
1893 if (attributeWildcard != null) {
1894 if (attributeUses.Count != 0) {
1898 sb.Append(attributeWildcard.NamespaceList.ToString());
1903 foreach (XmlSchemaAttribute attribute in attributeUses.Values) {
1904 if (attribute.Use == XmlSchemaUse.Prohibited) {
1911 sb.Append(attribute.QualifiedName.Name);
1915 return sb.ToString();
1919 private bool IsProcessContentsRestricted(XmlSchemaComplexType baseType, XmlSchemaAnyAttribute derivedAttributeWildcard, XmlSchemaAnyAttribute baseAttributeWildcard) {
1920 if (baseType == XmlSchemaComplexType.AnyType) {
1923 if ((int)derivedAttributeWildcard.ProcessContentsCorrect >= (int)baseAttributeWildcard.ProcessContentsCorrect) {
1929 private XmlSchemaAnyAttribute CompileAnyAttributeUnion(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) {
1933 else if (b == null) {
1937 XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Union(a, b, false); //false is for v1Compatd
1938 if (attribute == null) {
1939 SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a);
1946 private XmlSchemaAnyAttribute CompileAnyAttributeIntersection(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) {
1950 else if (b == null) {
1954 XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Intersection(a, b, false); //false is for v1Compat
1955 if (attribute == null) {
1956 SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a);
1962 private void CompileAttribute(XmlSchemaAttribute xa) {
1963 if (xa.IsProcessing) {
1964 SendValidationEvent(Res.Sch_AttributeCircularRef, xa);
1967 if (xa.AttDef != null) { //already compiled?
1970 xa.IsProcessing = true;
1971 SchemaAttDef decl = null;
1973 if (!xa.RefName.IsEmpty) {
1974 XmlSchemaAttribute a = (XmlSchemaAttribute)attributes[xa.RefName];
1976 throw new XmlSchemaException(Res.Sch_UndeclaredAttribute, xa.RefName.ToString(), xa);
1978 CompileAttribute(a);
1979 if (a.AttDef == null) {
1980 throw new XmlSchemaException(Res.Sch_RefInvalidAttribute, xa.RefName.ToString(), xa);
1982 decl = a.AttDef.Clone();
1983 XmlSchemaDatatype datatype = decl.Datatype;
1985 if (datatype != null) {
1986 if (a.FixedValue == null && a.DefaultValue == null) {
1987 SetDefaultFixed(xa, decl);
1989 else if (a.FixedValue != null) {
1990 if (xa.DefaultValue != null) {
1991 throw new XmlSchemaException(Res.Sch_FixedDefaultInRef, xa.RefName.ToString(), xa);
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);
2001 xa.SetAttributeType(a.AttributeSchemaType);
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;
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;
2019 throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, xa.SchemaTypeName.ToString(), xa);
2023 decl.SchemaType = DatatypeImplementation.AnySimpleType;
2024 decl.Datatype = DatatypeImplementation.AnySimpleType.Datatype;
2025 xa.SetAttributeType(DatatypeImplementation.AnySimpleType);
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);
2031 SetDefaultFixed(xa, decl);
2032 } //End of Else for !RefName.IsEmpty
2034 decl.SchemaAttribute = xa; //So this is available for PSVI
2037 catch (XmlSchemaException e) {
2038 if (e.SourceSchemaObject == null) {
2041 SendValidationEvent(e);
2042 xa.AttDef = SchemaAttDef.Empty;
2045 xa.IsProcessing = false;
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;
2056 if (xa.Use == XmlSchemaUse.Required) {
2057 decl.Presence = SchemaDeclBase.Use.RequiredFixed;
2060 decl.Presence = SchemaDeclBase.Use.Fixed;
2062 decl.DefaultValueRaw = decl.DefaultValueExpanded = xa.FixedValue;
2064 if(decl.Datatype != null) {
2065 if (decl.Datatype.TypeCode == XmlTypeCode.Id) {
2066 SendValidationEvent(Res.Sch_DefaultIdValue, xa);
2069 decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xa), true);
2075 case XmlSchemaUse.None:
2076 case XmlSchemaUse.Optional:
2077 decl.Presence = SchemaDeclBase.Use.Implied;
2079 case XmlSchemaUse.Required:
2080 decl.Presence = SchemaDeclBase.Use.Required;
2082 case XmlSchemaUse.Prohibited:
2088 private void CompileIdentityConstraint (XmlSchemaIdentityConstraint xi) {
2089 if (xi.IsProcessing) {
2090 xi.CompiledConstraint = CompiledIdentityConstraint.Empty;
2091 SendValidationEvent(Res.Sch_IdentityConstraintCircularRef, xi);
2095 if (xi.CompiledConstraint != null) {
2099 xi.IsProcessing = true;
2100 CompiledIdentityConstraint compic = null;
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];
2107 throw new XmlSchemaException(Res.Sch_UndeclaredIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi);
2109 CompileIdentityConstraint(ic);
2110 if (ic.CompiledConstraint == null) {
2111 throw new XmlSchemaException(Res.Sch_RefInvalidIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi);
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);
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);
2122 xi.CompiledConstraint = compic;
2124 catch (XmlSchemaException e) {
2125 if (e.SourceSchemaObject == null) {
2128 SendValidationEvent(e);
2129 xi.CompiledConstraint = CompiledIdentityConstraint.Empty;
2130 // empty is better than null here, stop quickly when circle referencing
2133 xi.IsProcessing = false;
2138 private void CompileElement(XmlSchemaElement xe) {
2139 if (xe.IsProcessing) {
2140 SendValidationEvent(Res.Sch_ElementCircularRef, xe);
2143 if (xe.ElementDecl != null) {
2146 xe.IsProcessing = true;
2147 SchemaElementDecl decl = null;
2149 if (!xe.RefName.IsEmpty) {
2150 XmlSchemaElement e = (XmlSchemaElement)elements[xe.RefName];
2152 throw new XmlSchemaException(Res.Sch_UndeclaredElement, xe.RefName.ToString(), xe);
2155 if (e.ElementDecl == null) {
2156 throw new XmlSchemaException(Res.Sch_RefInvalidElement, xe.RefName.ToString(), xe);
2158 xe.SetElementType(e.ElementSchemaType);
2159 decl = e.ElementDecl.Clone();
2162 if (xe.SchemaType != null) {
2163 xe.SetElementType(xe.SchemaType);
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);
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);
2176 if (examplar.IsProcessing) { //Circular subst group; already detected by now
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();
2185 xe.SetElementType(examplar.ElementSchemaType);
2186 decl = examplar.ElementDecl.Clone();
2190 xe.SetElementType(XmlSchemaComplexType.AnyType);
2191 decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone();
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;
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();
2212 Debug.Assert(decl != null);
2213 decl.Name = xe.QualifiedName;
2214 decl.IsAbstract = xe.IsAbstract;
2215 XmlSchemaComplexType ct = xe.ElementSchemaType as XmlSchemaComplexType;
2217 decl.IsAbstract |= ct.IsAbstract;
2219 decl.IsNillable = xe.IsNillable;
2220 decl.Block |= xe.BlockResolved;
2222 if (decl.Datatype != null) {
2223 decl.Datatype.VerifySchemaValid(notations, xe);
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;
2234 decl.Presence = SchemaDeclBase.Use.Fixed;
2235 decl.DefaultValueRaw = xe.FixedValue;
2237 if (decl.Datatype != null) {
2238 if (decl.Datatype.TypeCode == XmlTypeCode.Id) {
2239 SendValidationEvent(Res.Sch_DefaultIdValue, xe);
2242 decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe), true);
2245 else { //Mixed with emptiable particle
2246 decl.DefaultValueTyped = DatatypeImplementation.AnySimpleType.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe));
2250 throw new XmlSchemaException(Res.Sch_ElementCannotHaveValue, xe);
2254 if (xe.HasConstraints) {
2255 XmlSchemaObjectCollection constraints = xe.Constraints;
2256 CompiledIdentityConstraint[] compiledConstraints = new CompiledIdentityConstraint[constraints.Count];
2258 for (int i = 0; i < constraints.Count; ++i) {
2259 XmlSchemaIdentityConstraint constraint = (XmlSchemaIdentityConstraint)constraints[i];
2260 CompileIdentityConstraint(constraint);
2261 compiledConstraints[idx ++] = constraint.CompiledConstraint;
2263 decl.Constraints = compiledConstraints;
2265 decl.SchemaElement = xe; //So this is available for PSVI
2266 xe.ElementDecl = decl;
2268 catch (XmlSchemaException e) {
2269 if (e.SourceSchemaObject == null) {
2272 SendValidationEvent(e);
2273 xe.ElementDecl = SchemaElementDecl.Empty;
2276 xe.IsProcessing = false;
2280 private ContentValidator CompileComplexContent(XmlSchemaComplexType complexType) {
2281 if (complexType.ContentType == XmlSchemaContentType.Empty) {
2282 return ContentValidator.Empty;
2284 else if (complexType.ContentType == XmlSchemaContentType.TextOnly) {
2285 return ContentValidator.TextOnly;
2287 XmlSchemaParticle particle = complexType.ContentTypeParticle;
2288 if (particle == null || particle == XmlSchemaParticle.Empty) {
2289 if (complexType.ContentType == XmlSchemaContentType.ElementOnly) {
2290 return ContentValidator.Empty;
2293 return ContentValidator.Mixed;
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);
2306 return contentValidator;
2309 ParticleContentValidator contentValidator = new ParticleContentValidator(complexType.ContentType, CompilationSettings.EnableUpaCheck);
2311 string name = complexType.Name != null ? complexType.Name : string.Empty;
2312 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceVerbose, "CompileComplexContent: "+ name + DumpContentModel(particle));
2315 contentValidator.Start();
2316 complexType.HasWildCard = BuildParticleContentModel(contentValidator, particle);
2317 return contentValidator.Finish(true);
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);
2325 SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle2).ResolvedNamespace, ((XmlSchemaElement)e.Particle1).QualifiedName.ToString(), (XmlSchemaAny)e.Particle2);
2329 if (e.Particle2 is XmlSchemaElement) {
2330 SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle1).ResolvedNamespace, ((XmlSchemaElement)e.Particle2).QualifiedName.ToString(), (XmlSchemaElement)e.Particle2);
2333 SendValidationEvent(Res.Sch_NonDeterministicAnyAny, ((XmlSchemaAny)e.Particle1).ResolvedNamespace, ((XmlSchemaAny)e.Particle2).ResolvedNamespace, (XmlSchemaAny)e.Particle2);
2336 return XmlSchemaComplexType.AnyTypeContentValidator;
2338 catch(NotSupportedException) {
2339 SendValidationEvent(Res.Sch_ComplexContentModel, complexType, XmlSeverityType.Warning);
2340 return XmlSchemaComplexType.AnyTypeContentValidator;
2346 private string DumpContentModel(XmlSchemaParticle particle) {
2347 StringBuilder sb = new StringBuilder();
2348 DumpContentModelTo(sb, particle);
2349 return sb.ToString();
2352 private void DumpContentModelTo(StringBuilder sb, XmlSchemaParticle particle) {
2353 if (particle is XmlSchemaElement) {
2354 sb.Append(((XmlSchemaElement)particle).QualifiedName);
2356 else if (particle is XmlSchemaAny) {
2358 sb.Append(((XmlSchemaAny)particle).NamespaceList.ToString());
2361 else if (particle is XmlSchemaAll) {
2362 XmlSchemaAll all = (XmlSchemaAll)particle;
2365 for (int i = 0; i < all.Items.Count; ++i) {
2366 XmlSchemaElement localElement = (XmlSchemaElement)all.Items[i];
2373 sb.Append(localElement.QualifiedName.Name);
2374 if (localElement.MinOccurs == decimal.Zero) {
2380 else if (particle is XmlSchemaGroupBase) {
2381 XmlSchemaGroupBase gb = (XmlSchemaGroupBase)particle;
2383 string delimeter = (particle is XmlSchemaChoice) ? " | " : ", ";
2385 for (int i = 0; i < gb.Items.Count; ++i) {
2390 sb.Append(delimeter);
2392 DumpContentModelTo(sb, (XmlSchemaParticle)gb.Items[i]);
2396 Debug.Assert(particle == XmlSchemaParticle.Empty);
2399 if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) {
2402 else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) {
2405 else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) {
2408 else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) {
2412 sb.Append("{" + particle.MinOccurs.ToString(NumberFormatInfo.InvariantInfo) +", " + particle.MaxOccurs.ToString(NumberFormatInfo.InvariantInfo) + "}");
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);
2423 else if (particle is XmlSchemaAny) {
2425 XmlSchemaAny any = (XmlSchemaAny)particle;
2426 contentValidator.AddNamespaceList(any.NamespaceList, any);
2428 else if (particle is XmlSchemaGroupBase) {
2429 XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items;
2430 bool isChoice = particle is XmlSchemaChoice;
2431 contentValidator.OpenGroup();
2433 for (int i = 0; i < particles.Count; ++i) {
2434 Debug.Assert(!((XmlSchemaParticle)particles[i]).IsEmpty);
2438 else if (isChoice) {
2439 contentValidator.AddChoice();
2442 contentValidator.AddSequence();
2444 hasWildCard = BuildParticleContentModel(contentValidator, (XmlSchemaParticle)particles[i]);
2446 contentValidator.CloseGroup();
2449 Debug.Assert(false);
2451 if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) {
2454 else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) {
2455 contentValidator.AddQMark();
2457 else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) {
2458 contentValidator.AddStar();
2460 else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) {
2461 contentValidator.AddPlus();
2464 contentValidator.AddLeafRange(particle.MinOccurs, particle.MaxOccurs);
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);
2477 XmlSchemaElement element = (XmlSchemaElement)complexType.LocalElements[localElement.QualifiedName];
2478 if (element.ElementSchemaType != localElement.ElementSchemaType) {
2479 SendValidationEvent(Res.Sch_ElementTypeCollision, particle);
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]);
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);
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]);
2504 private void CompileComplexTypeElements(XmlSchemaComplexType complexType) {
2505 if (complexType.IsProcessing) {
2506 SendValidationEvent(Res.Sch_TypeCircularRef, complexType);
2509 complexType.IsProcessing = true;
2511 if (complexType.ContentTypeParticle != XmlSchemaParticle.Empty) {
2512 CompileParticleElements(complexType, complexType.ContentTypeParticle);
2516 complexType.IsProcessing = false;
2520 private XmlSchemaSimpleType GetSimpleType(XmlQualifiedName name) {
2521 XmlSchemaSimpleType type = schemaTypes[name] as XmlSchemaSimpleType;
2523 CompileSimpleType(type);
2526 type = DatatypeImplementation.GetSimpleTypeFromXsdType(name);
2531 private XmlSchemaComplexType GetComplexType(XmlQualifiedName name) {
2532 XmlSchemaComplexType type = schemaTypes[name] as XmlSchemaComplexType;
2534 CompileComplexType(type);
2539 private XmlSchemaType GetAnySchemaType(XmlQualifiedName name) {
2540 XmlSchemaType type = (XmlSchemaType)schemaTypes[name];
2542 if (type is XmlSchemaComplexType) {
2543 CompileComplexType((XmlSchemaComplexType)type);
2546 CompileSimpleType((XmlSchemaSimpleType)type);
2550 else { //Its is a built-in simpleType
2551 XmlSchemaSimpleType simpleType = DatatypeImplementation.GetSimpleTypeFromXsdType(name);
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);
2562 to.Parent = from.Parent;
2566 private bool IsFixedEqual(SchemaDeclBase baseDecl, SchemaDeclBase derivedDecl) {
2568 if (baseDecl.Presence == SchemaDeclBase.Use.Fixed || baseDecl.Presence == SchemaDeclBase.Use.RequiredFixed) {
2569 object baseFixedValue = baseDecl.DefaultValueTyped;
2570 object derivedFixedValue = derivedDecl.DefaultValueTyped;
2572 Debug.Assert(baseFixedValue != null);
2573 if (derivedDecl.Presence != SchemaDeclBase.Use.Fixed && derivedDecl.Presence != SchemaDeclBase.Use.RequiredFixed) {
2576 Debug.Assert(derivedFixedValue != null);
2577 XmlSchemaDatatype baseDatatype = baseDecl.Datatype;
2578 XmlSchemaDatatype derivedDatatype = derivedDecl.Datatype;
2580 if (baseDatatype.Variety == XmlSchemaDatatypeVariety.Union) {
2581 if (derivedDatatype.Variety == XmlSchemaDatatypeVariety.Union) {
2582 if ( !derivedDatatype.IsEqual(baseFixedValue, derivedFixedValue) ) {
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}
2595 else if (!derivedDatatype.IsEqual(baseFixedValue, derivedFixedValue)) {
2603 } // namespace System.Xml