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 SchemaCollectionCompiler : BaseProcessor {
17 bool compileContentModel;
18 XmlSchemaObjectTable examplars = new XmlSchemaObjectTable();
19 Stack complexTypeStack = new Stack();
22 public SchemaCollectionCompiler(XmlNameTable nameTable, ValidationEventHandler eventHandler)
23 : base(nameTable, null, eventHandler) {
26 public bool Execute(XmlSchema schema, SchemaInfo schemaInfo, bool compileContentModel) {
27 this.compileContentModel = compileContentModel;
38 private void Prepare() {
39 foreach (XmlSchemaElement element in this.schema.Elements.Values) {
40 if (!element.SubstitutionGroup.IsEmpty) {
41 XmlSchemaSubstitutionGroup substitutionGroup = (XmlSchemaSubstitutionGroup)this.examplars[element.SubstitutionGroup];
42 if (substitutionGroup == null) {
43 substitutionGroup = new XmlSchemaSubstitutionGroupV1Compat();
44 substitutionGroup.Examplar = element.SubstitutionGroup;
45 examplars.Add(element.SubstitutionGroup, substitutionGroup);
47 ArrayList members = substitutionGroup.Members;
48 Debug.Assert(!members.Contains(element));
54 private void Cleanup() {
55 foreach (XmlSchemaGroup group in this.schema.Groups.Values) {
58 foreach (XmlSchemaAttributeGroup attributeGroup in this.schema.AttributeGroups.Values) {
59 CleanupAttributeGroup(attributeGroup);
61 foreach (XmlSchemaType type in this.schema.SchemaTypes.Values) {
62 if (type is XmlSchemaComplexType) {
63 CleanupComplexType((XmlSchemaComplexType)type);
66 CleanupSimpleType((XmlSchemaSimpleType)type);
69 foreach (XmlSchemaElement element in this.schema.Elements.Values) {
70 CleanupElement(element);
72 foreach (XmlSchemaAttribute attribute in this.schema.Attributes.Values) {
73 CleanupAttribute(attribute);
78 internal static void Cleanup(XmlSchema schema) {
79 for (int i = 0; i < schema.Includes.Count; ++i) {
80 XmlSchemaExternal include = (XmlSchemaExternal)schema.Includes[i];
81 if (include.Schema != null) {
82 Cleanup(include.Schema);
84 XmlSchemaRedefine rdef = include as XmlSchemaRedefine;
86 rdef.AttributeGroups.Clear();
88 rdef.SchemaTypes.Clear();
90 for (int j = 0; j < rdef.Items.Count; ++j) {
91 object item = rdef.Items[j];
92 XmlSchemaAttribute attr;
93 XmlSchemaAttributeGroup attrgroup;
94 XmlSchemaComplexType complextype;
95 XmlSchemaSimpleType simpletype;
96 XmlSchemaElement element;
99 if ((attr = item as XmlSchemaAttribute) != null) {
100 CleanupAttribute(attr);
102 else if ((attrgroup = item as XmlSchemaAttributeGroup) != null) {
103 CleanupAttributeGroup(attrgroup);
105 else if ((complextype = item as XmlSchemaComplexType) != null) {
106 CleanupComplexType(complextype);
108 else if ((simpletype = item as XmlSchemaSimpleType) != null) {
109 CleanupSimpleType(simpletype);
111 else if ((element = item as XmlSchemaElement) != null) {
112 CleanupElement(element);
114 else if ((group = item as XmlSchemaGroup) != null) {
121 for (int i = 0; i < schema.Items.Count; ++i) {
122 object item = schema.Items[i];
123 XmlSchemaAttribute attr;
124 XmlSchemaAttributeGroup attrgroup;
125 XmlSchemaComplexType complextype;
126 XmlSchemaSimpleType simpletype;
127 XmlSchemaElement element;
128 XmlSchemaGroup group;
130 if ((attr = item as XmlSchemaAttribute) != null) {
131 CleanupAttribute(attr);
133 else if ((attrgroup = schema.Items[i] as XmlSchemaAttributeGroup) != null) {
134 CleanupAttributeGroup(attrgroup);
136 else if ((complextype = schema.Items[i] as XmlSchemaComplexType) != null) {
137 CleanupComplexType(complextype);
139 else if ((simpletype = schema.Items[i] as XmlSchemaSimpleType) != null) {
140 CleanupSimpleType(simpletype);
142 else if ((element = schema.Items[i] as XmlSchemaElement) != null) {
143 CleanupElement(element);
145 else if ((group = schema.Items[i] as XmlSchemaGroup) != null) {
149 schema.Attributes.Clear();
150 schema.AttributeGroups.Clear();
151 schema.SchemaTypes.Clear();
152 schema.Elements.Clear();
153 schema.Groups.Clear();
154 schema.Notations.Clear();
156 schema.IdentityConstraints.Clear();
159 private void Compile() {
160 this.schema.SchemaTypes.Insert(DatatypeImplementation.QnAnyType, XmlSchemaComplexType.AnyType);
162 foreach (XmlSchemaSubstitutionGroupV1Compat substitutionGroup in examplars.Values) {
163 CompileSubstitutionGroup(substitutionGroup);
165 foreach (XmlSchemaGroup group in this.schema.Groups.Values) {
168 foreach (XmlSchemaAttributeGroup attributeGroup in this.schema.AttributeGroups.Values) {
169 CompileAttributeGroup(attributeGroup);
171 foreach (XmlSchemaType type in this.schema.SchemaTypes.Values) {
172 if (type is XmlSchemaComplexType) {
173 CompileComplexType((XmlSchemaComplexType)type);
176 CompileSimpleType((XmlSchemaSimpleType)type);
179 foreach (XmlSchemaElement element in this.schema.Elements.Values) {
180 if (element.ElementDecl == null) {
181 CompileElement(element);
184 foreach (XmlSchemaAttribute attribute in this.schema.Attributes.Values) {
185 if (attribute.AttDef == null) {
186 CompileAttribute(attribute);
189 foreach (XmlSchemaIdentityConstraint identityConstraint in this.schema.IdentityConstraints.Values) {
190 if (identityConstraint.CompiledConstraint == null) {
191 CompileIdentityConstraint(identityConstraint);
194 while (this.complexTypeStack.Count > 0) {
195 XmlSchemaComplexType type = (XmlSchemaComplexType)complexTypeStack.Pop();
196 CompileCompexTypeElements(type);
198 foreach (XmlSchemaType type in this.schema.SchemaTypes.Values) {
199 if (type is XmlSchemaComplexType) {
200 CheckParticleDerivation((XmlSchemaComplexType)type);
203 foreach (XmlSchemaElement element in this.schema.Elements.Values) {
204 if (element.ElementSchemaType is XmlSchemaComplexType && element.SchemaTypeName == XmlQualifiedName.Empty) { // only local schemaTypes
205 CheckParticleDerivation((XmlSchemaComplexType)element.ElementSchemaType);
208 foreach (XmlSchemaSubstitutionGroup substitutionGroup in examplars.Values) {
209 CheckSubstitutionGroup(substitutionGroup);
212 this.schema.SchemaTypes.Remove(DatatypeImplementation.QnAnyType); //For backward compatibility
215 private void Output(SchemaInfo schemaInfo) {
216 foreach (XmlSchemaElement element in this.schema.Elements.Values) {
217 schemaInfo.TargetNamespaces[element.QualifiedName.Namespace] = true;
218 schemaInfo.ElementDecls.Add(element.QualifiedName, element.ElementDecl);
220 foreach (XmlSchemaAttribute attribute in this.schema.Attributes.Values) {
221 schemaInfo.TargetNamespaces[attribute.QualifiedName.Namespace] = true;
222 schemaInfo.AttributeDecls.Add(attribute.QualifiedName, attribute.AttDef);
224 foreach (XmlSchemaType type in this.schema.SchemaTypes.Values) {
225 schemaInfo.TargetNamespaces[type.QualifiedName.Namespace] = true;
226 XmlSchemaComplexType complexType = type as XmlSchemaComplexType;
227 if (complexType == null || (!complexType.IsAbstract && type != XmlSchemaComplexType.AnyType)) {
228 schemaInfo.ElementDeclsByType.Add(type.QualifiedName, type.ElementDecl);
231 foreach (XmlSchemaNotation notation in this.schema.Notations.Values) {
232 schemaInfo.TargetNamespaces[notation.QualifiedName.Namespace] = true;
233 SchemaNotation no = new SchemaNotation(notation.QualifiedName);
234 no.SystemLiteral = notation.System;
235 no.Pubid = notation.Public;
236 if (!schemaInfo.Notations.ContainsKey(no.Name.Name)) {
237 schemaInfo.Notations.Add(no.Name.Name, no);
242 private static void CleanupAttribute(XmlSchemaAttribute attribute) {
243 if (attribute.SchemaType != null) {
244 CleanupSimpleType((XmlSchemaSimpleType)attribute.SchemaType);
246 attribute.AttDef = null;
249 private static void CleanupAttributeGroup(XmlSchemaAttributeGroup attributeGroup) {
250 CleanupAttributes(attributeGroup.Attributes);
251 attributeGroup.AttributeUses.Clear();
252 attributeGroup.AttributeWildcard = null;
255 private static void CleanupComplexType(XmlSchemaComplexType complexType) {
256 if (complexType.ContentModel != null) { //simpleContent or complexContent
257 if (complexType.ContentModel is XmlSchemaSimpleContent) {
258 XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent)complexType.ContentModel;
259 if (simpleContent.Content is XmlSchemaSimpleContentExtension) {
260 XmlSchemaSimpleContentExtension simpleExtension = (XmlSchemaSimpleContentExtension)simpleContent.Content;
261 CleanupAttributes(simpleExtension.Attributes);
263 else { //simpleContent.Content is XmlSchemaSimpleContentRestriction
264 XmlSchemaSimpleContentRestriction simpleRestriction = (XmlSchemaSimpleContentRestriction)simpleContent.Content;
265 CleanupAttributes(simpleRestriction.Attributes);
268 else { // complexType.ContentModel is XmlSchemaComplexContent
269 XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complexType.ContentModel;
270 if (complexContent.Content is XmlSchemaComplexContentExtension) {
271 XmlSchemaComplexContentExtension complexExtension = (XmlSchemaComplexContentExtension)complexContent.Content;
272 CleanupParticle(complexExtension.Particle);
273 CleanupAttributes(complexExtension.Attributes);
276 else { //XmlSchemaComplexContentRestriction
277 XmlSchemaComplexContentRestriction complexRestriction = (XmlSchemaComplexContentRestriction)complexContent.Content;
278 CleanupParticle(complexRestriction.Particle);
279 CleanupAttributes(complexRestriction.Attributes);
283 else { //equals XmlSchemaComplexContent with baseType is anyType
284 CleanupParticle(complexType.Particle);
285 CleanupAttributes(complexType.Attributes);
287 complexType.LocalElements.Clear();
288 complexType.AttributeUses.Clear();
289 complexType.SetAttributeWildcard(null);
290 complexType.SetContentTypeParticle(XmlSchemaParticle.Empty);
291 complexType.ElementDecl = null;
294 private static void CleanupSimpleType(XmlSchemaSimpleType simpleType) {
295 simpleType.ElementDecl = null;
298 private static void CleanupElement(XmlSchemaElement element) {
299 if (element.SchemaType != null) {
300 XmlSchemaComplexType complexType = element.SchemaType as XmlSchemaComplexType;
301 if (complexType != null) {
302 CleanupComplexType(complexType);
305 CleanupSimpleType((XmlSchemaSimpleType)element.SchemaType);
308 for (int i = 0; i < element.Constraints.Count; ++i) {
309 ((XmlSchemaIdentityConstraint)element.Constraints[i]).CompiledConstraint = null;
311 element.ElementDecl = null;
314 private static void CleanupAttributes(XmlSchemaObjectCollection attributes) {
315 for (int i = 0; i < attributes.Count; ++i) {
316 XmlSchemaAttribute attribute = attributes[i] as XmlSchemaAttribute;
317 if (attribute != null) {
318 CleanupAttribute(attribute);
323 private static void CleanupGroup(XmlSchemaGroup group) {
324 CleanupParticle(group.Particle);
325 group.CanonicalParticle = null;
328 private static void CleanupParticle(XmlSchemaParticle particle) {
329 if (particle is XmlSchemaElement) {
330 CleanupElement((XmlSchemaElement)particle);
332 else if (particle is XmlSchemaGroupBase) {
333 XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items;
334 for (int i = 0; i < particles.Count; ++i) {
335 CleanupParticle((XmlSchemaParticle)particles[i]);
340 private void CompileSubstitutionGroup(XmlSchemaSubstitutionGroupV1Compat substitutionGroup) {
341 if (substitutionGroup.IsProcessing && substitutionGroup.Members.Count > 0) {
342 SendValidationEvent(Res.Sch_SubstitutionCircularRef, (XmlSchemaElement)substitutionGroup.Members[0]);
345 XmlSchemaElement examplar = (XmlSchemaElement)this.schema.Elements[substitutionGroup.Examplar];
346 if (substitutionGroup.Members.Contains(examplar)) {// already checked
349 substitutionGroup.IsProcessing = true;
350 if (examplar != null) {
351 if (examplar.FinalResolved == XmlSchemaDerivationMethod.All) {
352 SendValidationEvent(Res.Sch_InvalidExamplar, examplar);
355 for (int i = 0; i < substitutionGroup.Members.Count; ++i) {
356 XmlSchemaElement element = (XmlSchemaElement)substitutionGroup.Members[i];
357 //Chain to other head's that are members of this head's substGroup
358 XmlSchemaSubstitutionGroupV1Compat g = (XmlSchemaSubstitutionGroupV1Compat)examplars[element.QualifiedName];
360 CompileSubstitutionGroup(g);
361 for (int j = 0; j < g.Choice.Items.Count; ++j) {
362 substitutionGroup.Choice.Items.Add(g.Choice.Items[j]);
366 substitutionGroup.Choice.Items.Add(element);
369 substitutionGroup.Choice.Items.Add(examplar);
370 substitutionGroup.Members.Add(examplar); // Compiled mark
372 else if (substitutionGroup.Members.Count > 0) {
373 SendValidationEvent(Res.Sch_NoExamplar, (XmlSchemaElement)substitutionGroup.Members[0]);
375 substitutionGroup.IsProcessing = false;
378 private void CheckSubstitutionGroup(XmlSchemaSubstitutionGroup substitutionGroup) {
379 XmlSchemaElement examplar = (XmlSchemaElement)this.schema.Elements[substitutionGroup.Examplar];
380 if (examplar != null) {
381 for (int i = 0; i < substitutionGroup.Members.Count; ++i) {
382 XmlSchemaElement element = (XmlSchemaElement)substitutionGroup.Members[i];
384 if (element != examplar) {
385 if (!XmlSchemaType.IsDerivedFrom(element.ElementSchemaType, examplar.ElementSchemaType, examplar.FinalResolved)) {
386 SendValidationEvent(Res.Sch_InvalidSubstitutionMember, (element.QualifiedName).ToString(), (examplar.QualifiedName).ToString(), element);
393 private void CompileGroup(XmlSchemaGroup group) {
394 if (group.IsProcessing) {
395 SendValidationEvent(Res.Sch_GroupCircularRef, group);
396 group.CanonicalParticle = XmlSchemaParticle.Empty;
399 group.IsProcessing = true;
400 if (group.CanonicalParticle == null) {
401 group.CanonicalParticle = CannonicalizeParticle(group.Particle, true, true);
403 Debug.Assert(group.CanonicalParticle != null);
404 group.IsProcessing = false;
408 private void CompileSimpleType(XmlSchemaSimpleType simpleType) {
409 if (simpleType.IsProcessing) {
410 throw new XmlSchemaException(Res.Sch_TypeCircularRef, simpleType);
412 if (simpleType.ElementDecl != null) { // already compiled
415 simpleType.IsProcessing = true;
417 if (simpleType.Content is XmlSchemaSimpleTypeList) {
418 XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList)simpleType.Content;
419 XmlSchemaDatatype datatype;
420 simpleType.SetBaseSchemaType(DatatypeImplementation.AnySimpleType);
421 if (list.ItemTypeName.IsEmpty) {
422 CompileSimpleType(list.ItemType);
423 list.BaseItemType = list.ItemType;
424 datatype = list.ItemType.Datatype;
427 XmlSchemaSimpleType type = GetSimpleType(list.ItemTypeName);
429 if ((type.FinalResolved & XmlSchemaDerivationMethod.List) != 0) {
430 SendValidationEvent(Res.Sch_BaseFinalList, simpleType);
432 list.BaseItemType = type;
433 datatype = type.Datatype;
436 throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, list.ItemTypeName.ToString(), simpleType);
439 simpleType.SetDatatype(datatype.DeriveByList(simpleType));
440 simpleType.SetDerivedBy(XmlSchemaDerivationMethod.List);
442 else if (simpleType.Content is XmlSchemaSimpleTypeRestriction) {
443 XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)simpleType.Content;
444 XmlSchemaDatatype datatype;
445 if (restriction.BaseTypeName.IsEmpty) {
446 CompileSimpleType(restriction.BaseType);
447 simpleType.SetBaseSchemaType(restriction.BaseType);
448 datatype = restriction.BaseType.Datatype;
450 else if (simpleType.Redefined != null && restriction.BaseTypeName == simpleType.Redefined.QualifiedName) {
451 CompileSimpleType((XmlSchemaSimpleType)simpleType.Redefined);
452 simpleType.SetBaseSchemaType(simpleType.Redefined.BaseXmlSchemaType);
453 datatype = simpleType.Redefined.Datatype;
456 if (restriction.BaseTypeName.Equals(DatatypeImplementation.QnAnySimpleType)) {
457 throw new XmlSchemaException(Res.Sch_InvalidSimpleTypeRestriction, restriction.BaseTypeName.ToString(), simpleType);
459 XmlSchemaSimpleType type = GetSimpleType(restriction.BaseTypeName);
461 if ((type.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
462 SendValidationEvent(Res.Sch_BaseFinalRestriction, simpleType);
464 simpleType.SetBaseSchemaType(type);
465 datatype = type.Datatype;
468 throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, restriction.BaseTypeName.ToString(), simpleType);
471 simpleType.SetDatatype(datatype.DeriveByRestriction(restriction.Facets, NameTable, simpleType));
472 simpleType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
474 else { //simpleType.Content is XmlSchemaSimpleTypeUnion
475 XmlSchemaSimpleType[] baseTypes = CompileBaseMemberTypes(simpleType);
476 simpleType.SetBaseSchemaType(DatatypeImplementation.AnySimpleType);
477 simpleType.SetDatatype(XmlSchemaDatatype.DeriveByUnion(baseTypes, simpleType));
478 simpleType.SetDerivedBy(XmlSchemaDerivationMethod.Union);
481 catch (XmlSchemaException e) {
482 if (e.SourceSchemaObject == null) {
483 e.SetSource(simpleType);
485 SendValidationEvent(e);
486 simpleType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype);
489 SchemaElementDecl decl = new SchemaElementDecl();
490 decl.ContentValidator = ContentValidator.TextOnly;
491 decl.SchemaType = simpleType;
492 decl.Datatype = simpleType.Datatype;
493 simpleType.ElementDecl = decl;
494 simpleType.IsProcessing = false;
498 private XmlSchemaSimpleType[] CompileBaseMemberTypes(XmlSchemaSimpleType simpleType) {
499 XmlSchemaSimpleType unionMember;
500 ArrayList memberTypeDefinitions = new ArrayList();
502 XmlSchemaSimpleTypeUnion mainUnion = (XmlSchemaSimpleTypeUnion)simpleType.Content;
504 XmlQualifiedName[] mainMemberTypes = mainUnion.MemberTypes;
505 if (mainMemberTypes != null) {
506 for (int i = 0; i < mainMemberTypes.Length; ++i) {
507 unionMember = GetSimpleType(mainMemberTypes[i]);
508 if (unionMember != null) {
509 if (unionMember.Datatype.Variety == XmlSchemaDatatypeVariety.Union) { //union of union
510 CheckUnionType(unionMember, memberTypeDefinitions, simpleType);
512 else { //its list or atomic
513 memberTypeDefinitions.Add(unionMember);
515 //Check derivation method of the member that is referenced
516 if ((unionMember.FinalResolved & XmlSchemaDerivationMethod.Union) != 0) {
517 SendValidationEvent(Res.Sch_BaseFinalUnion, simpleType);
521 throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, mainMemberTypes[i].ToString(), simpleType);
526 //Now add the baseTypes that are defined inside the union itself
527 XmlSchemaObjectCollection mainBaseTypes = mainUnion.BaseTypes; //
528 if (mainBaseTypes != null) {
529 for (int i = 0; i < mainBaseTypes.Count; ++i) {
530 XmlSchemaSimpleType st = (XmlSchemaSimpleType)mainBaseTypes[i];
531 CompileSimpleType(st);
532 if (st.Datatype.Variety == XmlSchemaDatatypeVariety.Union) { //union of union
533 CheckUnionType(st, memberTypeDefinitions, simpleType);
535 else { //its list or atomic
536 memberTypeDefinitions.Add(st);
541 mainUnion.SetBaseMemberTypes(memberTypeDefinitions.ToArray(typeof(XmlSchemaSimpleType)) as XmlSchemaSimpleType[]);
542 return mainUnion.BaseMemberTypes;
545 private void CheckUnionType(XmlSchemaSimpleType unionMember, ArrayList memberTypeDefinitions, XmlSchemaSimpleType parentType) {
546 XmlSchemaDatatype unionDatatype = unionMember.Datatype;
547 if (unionMember.DerivedBy == XmlSchemaDerivationMethod.Restriction && (unionDatatype.HasLexicalFacets || unionDatatype.HasValueFacets) ) {
548 SendValidationEvent(Res.Sch_UnionFromUnion, parentType);
551 Datatype_union uniondt = unionMember.Datatype as Datatype_union;
552 memberTypeDefinitions.AddRange(uniondt.BaseMemberTypes);
556 private void CompileComplexType(XmlSchemaComplexType complexType) {
557 if (complexType.ElementDecl != null) { //already compiled
560 if (complexType.IsProcessing) {
561 SendValidationEvent(Res.Sch_TypeCircularRef, complexType);
564 complexType.IsProcessing = true;
565 if (complexType.ContentModel != null) { //simpleContent or complexContent
566 if (complexType.ContentModel is XmlSchemaSimpleContent) {
567 XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent)complexType.ContentModel;
568 complexType.SetContentType(XmlSchemaContentType.TextOnly);
569 if (simpleContent.Content is XmlSchemaSimpleContentExtension) {
570 CompileSimpleContentExtension(complexType, (XmlSchemaSimpleContentExtension)simpleContent.Content);
572 else { //simpleContent.Content is XmlSchemaSimpleContentRestriction
573 CompileSimpleContentRestriction(complexType, (XmlSchemaSimpleContentRestriction)simpleContent.Content);
576 else { // complexType.ContentModel is XmlSchemaComplexContent
577 XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complexType.ContentModel;
578 if (complexContent.Content is XmlSchemaComplexContentExtension) {
579 CompileComplexContentExtension(complexType, complexContent, (XmlSchemaComplexContentExtension)complexContent.Content);
581 else { // complexContent.Content is XmlSchemaComplexContentRestriction
582 CompileComplexContentRestriction(complexType, complexContent, (XmlSchemaComplexContentRestriction)complexContent.Content);
586 else { //equals XmlSchemaComplexContent with baseType is anyType
587 complexType.SetBaseSchemaType(XmlSchemaComplexType.AnyType);
588 CompileLocalAttributes(XmlSchemaComplexType.AnyType, complexType, complexType.Attributes, complexType.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
589 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
590 complexType.SetContentTypeParticle(CompileContentTypeParticle(complexType.Particle, true));
591 complexType.SetContentType(GetSchemaContentType(complexType, null, complexType.ContentTypeParticle));
594 foreach(XmlSchemaAttribute attribute in complexType.AttributeUses.Values) {
595 if (attribute.Use != XmlSchemaUse.Prohibited) {
596 XmlSchemaDatatype datatype = attribute.Datatype;
597 if (datatype != null && datatype.TokenizedType == XmlTokenizedType.ID) {
599 SendValidationEvent(Res.Sch_TwoIdAttrUses, complexType);
607 SchemaElementDecl decl = new SchemaElementDecl();
608 decl.ContentValidator = CompileComplexContent(complexType);
609 decl.SchemaType = complexType;
610 decl.IsAbstract = complexType.IsAbstract;
611 decl.Datatype = complexType.Datatype;
612 decl.Block = complexType.BlockResolved;
613 decl.AnyAttribute = complexType.AttributeWildcard;
614 foreach(XmlSchemaAttribute attribute in complexType.AttributeUses.Values) {
615 if (attribute.Use == XmlSchemaUse.Prohibited) {
616 if (!decl.ProhibitedAttributes.ContainsKey(attribute.QualifiedName)) {
617 decl.ProhibitedAttributes.Add(attribute.QualifiedName, attribute.QualifiedName);
621 if (!decl.AttDefs.ContainsKey(attribute.QualifiedName) && attribute.AttDef != null && attribute.AttDef.Name != XmlQualifiedName.Empty && attribute.AttDef != SchemaAttDef.Empty) {
622 decl.AddAttDef(attribute.AttDef);
627 complexType.ElementDecl = decl;
629 complexType.IsProcessing = false;
633 private void CompileSimpleContentExtension(XmlSchemaComplexType complexType, XmlSchemaSimpleContentExtension simpleExtension) {
634 XmlSchemaComplexType baseType = null;
635 if (complexType.Redefined != null && simpleExtension.BaseTypeName == complexType.Redefined.QualifiedName) {
636 baseType = (XmlSchemaComplexType)complexType.Redefined;
637 CompileComplexType(baseType);
638 complexType.SetBaseSchemaType(baseType);
639 complexType.SetDatatype(baseType.Datatype);
642 XmlSchemaType bto = GetAnySchemaType(simpleExtension.BaseTypeName);
644 SendValidationEvent(Res.Sch_UndeclaredType, simpleExtension.BaseTypeName.ToString(), complexType);
647 complexType.SetBaseSchemaType(bto);
648 complexType.SetDatatype(bto.Datatype);
650 baseType = bto as XmlSchemaComplexType;
652 if (baseType != null) {
653 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) {
654 SendValidationEvent(Res.Sch_BaseFinalExtension, complexType);
656 if (baseType.ContentType != XmlSchemaContentType.TextOnly) {
657 SendValidationEvent(Res.Sch_NotSimpleContent, complexType);
660 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension);
661 CompileLocalAttributes(baseType, complexType, simpleExtension.Attributes, simpleExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension);
664 private void CompileSimpleContentRestriction(XmlSchemaComplexType complexType, XmlSchemaSimpleContentRestriction simpleRestriction) {
665 XmlSchemaComplexType baseType = null;
666 XmlSchemaDatatype datatype = null;
667 if (complexType.Redefined != null && simpleRestriction.BaseTypeName == complexType.Redefined.QualifiedName) {
668 baseType = (XmlSchemaComplexType)complexType.Redefined;
669 CompileComplexType(baseType);
670 datatype = baseType.Datatype;
673 baseType = GetComplexType(simpleRestriction.BaseTypeName);
674 if (baseType == null) {
675 SendValidationEvent(Res.Sch_UndefBaseRestriction, simpleRestriction.BaseTypeName.ToString(), simpleRestriction);
678 if (baseType.ContentType == XmlSchemaContentType.TextOnly) {
679 if (simpleRestriction.BaseType == null) {
680 datatype = baseType.Datatype;
681 //There is a bug here. Need to check if simpleRestriction has facets.
682 //If yes, Need tp apply these facets as well.
685 CompileSimpleType(simpleRestriction.BaseType);
686 if(!XmlSchemaType.IsDerivedFromDatatype(simpleRestriction.BaseType.Datatype, baseType.Datatype, XmlSchemaDerivationMethod.None)) {
687 SendValidationEvent(Res.Sch_DerivedNotFromBase, simpleRestriction);
689 datatype = simpleRestriction.BaseType.Datatype;
692 else if (baseType.ContentType == XmlSchemaContentType.Mixed && baseType.ElementDecl.ContentValidator.IsEmptiable) {
693 if (simpleRestriction.BaseType != null) {
694 CompileSimpleType(simpleRestriction.BaseType);
695 complexType.SetBaseSchemaType(simpleRestriction.BaseType);
696 datatype = simpleRestriction.BaseType.Datatype;
699 SendValidationEvent(Res.Sch_NeedSimpleTypeChild, simpleRestriction);
703 SendValidationEvent(Res.Sch_NotSimpleContent, complexType);
706 if (baseType != null && baseType.ElementDecl != null) {
707 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
708 SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType);
711 if (baseType != null) {
712 complexType.SetBaseSchemaType(baseType);
714 if (datatype != null) {
716 complexType.SetDatatype(datatype.DeriveByRestriction(simpleRestriction.Facets, NameTable, complexType));
718 catch (XmlSchemaException e) {
719 if (e.SourceSchemaObject == null) {
720 e.SetSource(complexType);
722 SendValidationEvent(e);
723 complexType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype);
726 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
727 CompileLocalAttributes(baseType, complexType, simpleRestriction.Attributes, simpleRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
730 private void CompileComplexContentExtension(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentExtension complexExtension) {
731 XmlSchemaComplexType baseType = null;
732 if (complexType.Redefined != null && complexExtension.BaseTypeName == complexType.Redefined.QualifiedName) {
733 baseType = (XmlSchemaComplexType)complexType.Redefined;
734 CompileComplexType(baseType);
737 baseType = GetComplexType(complexExtension.BaseTypeName);
738 if (baseType == null) {
739 SendValidationEvent(Res.Sch_UndefBaseExtension, complexExtension.BaseTypeName.ToString(), complexExtension);
743 if (baseType != null && baseType.ElementDecl != null) {
744 if (baseType.ContentType == XmlSchemaContentType.TextOnly) {
745 SendValidationEvent(Res.Sch_NotComplexContent, complexType);
749 complexType.SetBaseSchemaType(baseType);
750 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) {
751 SendValidationEvent(Res.Sch_BaseFinalExtension, complexType);
753 CompileLocalAttributes(baseType, complexType, complexExtension.Attributes, complexExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension);
755 XmlSchemaParticle baseParticle = baseType.ContentTypeParticle;
756 XmlSchemaParticle extendedParticle = CannonicalizeParticle(complexExtension.Particle, true, true);
757 if (baseParticle != XmlSchemaParticle.Empty) {
758 if (extendedParticle != XmlSchemaParticle.Empty) {
759 XmlSchemaSequence compiledParticle = new XmlSchemaSequence();
760 compiledParticle.Items.Add(baseParticle);
761 compiledParticle.Items.Add(extendedParticle);
762 complexType.SetContentTypeParticle(CompileContentTypeParticle(compiledParticle, false));
765 complexType.SetContentTypeParticle(baseParticle);
767 XmlSchemaContentType contentType = GetSchemaContentType(complexType, complexContent, extendedParticle);
768 if (contentType == XmlSchemaContentType.Empty) { //Derived content type is empty, Get ContentType from base
769 contentType = baseType.ContentType;
771 complexType.SetContentType(contentType);
772 if (complexType.ContentType != baseType.ContentType) {
773 SendValidationEvent(Res.Sch_DifContentType, complexType);
777 complexType.SetContentTypeParticle(extendedParticle);
778 complexType.SetContentType(GetSchemaContentType(complexType, complexContent, complexType.ContentTypeParticle));
780 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension);
783 private void CompileComplexContentRestriction(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentRestriction complexRestriction) {
784 XmlSchemaComplexType baseType = null;
785 if (complexType.Redefined != null && complexRestriction.BaseTypeName == complexType.Redefined.QualifiedName) {
786 baseType = (XmlSchemaComplexType)complexType.Redefined;
787 CompileComplexType(baseType);
790 baseType = GetComplexType(complexRestriction.BaseTypeName);
791 if (baseType == null) {
792 SendValidationEvent(Res.Sch_UndefBaseRestriction, complexRestriction.BaseTypeName.ToString(), complexRestriction);
796 if (baseType != null && baseType.ElementDecl != null) {
797 if (baseType.ContentType == XmlSchemaContentType.TextOnly) {
798 SendValidationEvent(Res.Sch_NotComplexContent, complexType);
802 complexType.SetBaseSchemaType(baseType);
803 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
804 SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType);
806 CompileLocalAttributes(baseType, complexType, complexRestriction.Attributes, complexRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
808 complexType.SetContentTypeParticle(CompileContentTypeParticle(complexRestriction.Particle, true));
809 complexType.SetContentType(GetSchemaContentType(complexType, complexContent, complexType.ContentTypeParticle));
810 if (complexType.ContentType == XmlSchemaContentType.Empty) {
811 if (baseType.ElementDecl != null) {
812 Debug.Assert(baseType.ElementDecl.ContentValidator != null);
814 if (baseType.ElementDecl != null && !baseType.ElementDecl.ContentValidator.IsEmptiable) {
815 SendValidationEvent(Res.Sch_InvalidContentRestriction, complexType);
818 complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
821 private void CheckParticleDerivation(XmlSchemaComplexType complexType) {
822 XmlSchemaComplexType baseType = complexType.BaseXmlSchemaType as XmlSchemaComplexType;
823 if (baseType != null && baseType != XmlSchemaComplexType.AnyType && complexType.DerivedBy == XmlSchemaDerivationMethod.Restriction) {
824 if (!IsValidRestriction(complexType.ContentTypeParticle, baseType.ContentTypeParticle)) {
826 if(complexType.ContentTypeParticle != null && baseType.ContentTypeParticle != null) {
827 string position = string.Empty;
828 if (complexType.SourceUri != null) {
829 position = " in " + complexType.SourceUri + "(" + complexType.LineNumber + ", " + complexType.LinePosition + ")";
831 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType content restriction" + position);
832 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, " Base " + DumpContentModel(baseType.ContentTypeParticle));
833 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, " Derived " + DumpContentModel(complexType.ContentTypeParticle));
836 SendValidationEvent(Res.Sch_InvalidParticleRestriction, complexType);
841 private XmlSchemaParticle CompileContentTypeParticle(XmlSchemaParticle particle, bool substitution) {
842 XmlSchemaParticle ctp = CannonicalizeParticle(particle, true, substitution);
843 XmlSchemaChoice choice = ctp as XmlSchemaChoice;
844 if (choice != null && choice.Items.Count == 0) {
845 if (choice.MinOccurs != decimal.Zero) {
846 SendValidationEvent(Res.Sch_EmptyChoice, choice, XmlSeverityType.Warning);
848 return XmlSchemaParticle.Empty;
853 private XmlSchemaParticle CannonicalizeParticle(XmlSchemaParticle particle, bool root, bool substitution) {
854 if (particle == null || particle.IsEmpty) {
855 return XmlSchemaParticle.Empty;
857 else if (particle is XmlSchemaElement) {
858 return CannonicalizeElement((XmlSchemaElement)particle, substitution);
860 else if (particle is XmlSchemaGroupRef) {
861 return CannonicalizeGroupRef((XmlSchemaGroupRef)particle, root, substitution);
863 else if (particle is XmlSchemaAll) {
864 return CannonicalizeAll((XmlSchemaAll)particle, root, substitution);
866 else if (particle is XmlSchemaChoice) {
867 return CannonicalizeChoice((XmlSchemaChoice)particle, root, substitution);
869 else if (particle is XmlSchemaSequence) {
870 return CannonicalizeSequence((XmlSchemaSequence)particle, root, substitution);
877 private XmlSchemaParticle CannonicalizeElement(XmlSchemaElement element, bool substitution) {
878 if (!element.RefName.IsEmpty && substitution && (element.BlockResolved & XmlSchemaDerivationMethod.Substitution) == 0) {
879 XmlSchemaSubstitutionGroupV1Compat substitutionGroup = (XmlSchemaSubstitutionGroupV1Compat)examplars[element.QualifiedName];
880 if (substitutionGroup == null) {
884 XmlSchemaChoice choice = (XmlSchemaChoice)substitutionGroup.Choice.Clone();
885 choice.MinOccurs = element.MinOccurs;
886 choice.MaxOccurs = element.MaxOccurs;
895 private XmlSchemaParticle CannonicalizeGroupRef(XmlSchemaGroupRef groupRef, bool root, bool substitution) {
896 XmlSchemaGroup group;
897 if (groupRef.Redefined != null) {
898 group = groupRef.Redefined;
901 group = (XmlSchemaGroup)this.schema.Groups[groupRef.RefName];
904 SendValidationEvent(Res.Sch_UndefGroupRef, groupRef.RefName.ToString(), groupRef);
905 return XmlSchemaParticle.Empty;
907 if (group.CanonicalParticle == null) {
910 if (group.CanonicalParticle == XmlSchemaParticle.Empty) {
911 return XmlSchemaParticle.Empty;
913 XmlSchemaGroupBase groupBase = (XmlSchemaGroupBase)group.CanonicalParticle;
914 if (groupBase is XmlSchemaAll) {
916 SendValidationEvent(Res.Sch_AllRefNotRoot, "", groupRef);
917 return XmlSchemaParticle.Empty;
919 if (groupRef.MinOccurs != decimal.One || groupRef.MaxOccurs != decimal.One) {
920 SendValidationEvent(Res.Sch_AllRefMinMax, groupRef);
921 return XmlSchemaParticle.Empty;
924 else if (groupBase is XmlSchemaChoice && groupBase.Items.Count == 0) {
925 if (groupRef.MinOccurs != decimal.Zero) {
926 SendValidationEvent(Res.Sch_EmptyChoice, groupRef, XmlSeverityType.Warning);
928 return XmlSchemaParticle.Empty;
930 XmlSchemaGroupBase groupRefBase = (
931 (groupBase is XmlSchemaSequence) ? (XmlSchemaGroupBase)new XmlSchemaSequence() :
932 (groupBase is XmlSchemaChoice) ? (XmlSchemaGroupBase)new XmlSchemaChoice() :
933 (XmlSchemaGroupBase)new XmlSchemaAll()
935 groupRefBase.MinOccurs = groupRef.MinOccurs;
936 groupRefBase.MaxOccurs = groupRef.MaxOccurs;
937 for (int i = 0; i < groupBase.Items.Count; ++i) {
938 groupRefBase.Items.Add((XmlSchemaParticle)groupBase.Items[i]);
940 groupRef.SetParticle(groupRefBase);
944 private XmlSchemaParticle CannonicalizeAll(XmlSchemaAll all, bool root, bool substitution) {
945 if (all.Items.Count > 0) {
946 XmlSchemaAll newAll = new XmlSchemaAll();
947 newAll.MinOccurs = all.MinOccurs;
948 newAll.MaxOccurs = all.MaxOccurs;
949 newAll.SourceUri = all.SourceUri; // all is the only one that might need and error message
950 newAll.LineNumber = all.LineNumber;
951 newAll.LinePosition = all.LinePosition;
952 for (int i = 0; i < all.Items.Count; ++i) {
953 XmlSchemaParticle p = CannonicalizeParticle((XmlSchemaElement)all.Items[i], false, substitution);
954 if (p != XmlSchemaParticle.Empty) {
960 if (all.Items.Count == 0) {
961 return XmlSchemaParticle.Empty;
963 else if (root && all.Items.Count == 1) {
964 XmlSchemaSequence newSequence = new XmlSchemaSequence();
965 newSequence.MinOccurs = all.MinOccurs;
966 newSequence.MaxOccurs = all.MaxOccurs;
967 newSequence.Items.Add((XmlSchemaParticle)all.Items[0]);
970 else if (!root && all.Items.Count == 1 && all.MinOccurs == decimal.One && all.MaxOccurs == decimal.One) {
971 return (XmlSchemaParticle)all.Items[0];
974 SendValidationEvent(Res.Sch_NotAllAlone, all);
975 return XmlSchemaParticle.Empty;
982 private XmlSchemaParticle CannonicalizeChoice(XmlSchemaChoice choice, bool root, bool substitution) {
983 XmlSchemaChoice oldChoice = choice;
984 if (choice.Items.Count > 0) {
985 XmlSchemaChoice newChoice = new XmlSchemaChoice();
986 newChoice.MinOccurs = choice.MinOccurs;
987 newChoice.MaxOccurs = choice.MaxOccurs;
988 for (int i = 0; i < choice.Items.Count; ++i) {
989 XmlSchemaParticle p1 = CannonicalizeParticle((XmlSchemaParticle)choice.Items[i], false, substitution);
990 if (p1 != XmlSchemaParticle.Empty) {
991 if (p1.MinOccurs == decimal.One && p1.MaxOccurs == decimal.One && p1 is XmlSchemaChoice) {
992 XmlSchemaChoice particleChoice = (XmlSchemaChoice)p1;
993 for (int j = 0; j < particleChoice.Items.Count; ++j) {
994 newChoice.Items.Add(particleChoice.Items[j]);
998 newChoice.Items.Add(p1);
1004 if (!root && choice.Items.Count == 0) {
1005 if (choice.MinOccurs != decimal.Zero) {
1006 SendValidationEvent(Res.Sch_EmptyChoice, oldChoice, XmlSeverityType.Warning);
1008 return XmlSchemaParticle.Empty;
1010 else if (!root && choice.Items.Count == 1 && choice.MinOccurs == decimal.One && choice.MaxOccurs == decimal.One) {
1011 return (XmlSchemaParticle)choice.Items[0];
1018 private XmlSchemaParticle CannonicalizeSequence(XmlSchemaSequence sequence, bool root, bool substitution) {
1019 if (sequence.Items.Count > 0) {
1020 XmlSchemaSequence newSequence = new XmlSchemaSequence();
1021 newSequence.MinOccurs = sequence.MinOccurs;
1022 newSequence.MaxOccurs = sequence.MaxOccurs;
1023 for (int i = 0; i < sequence.Items.Count; ++i) {
1024 XmlSchemaParticle p1 = CannonicalizeParticle(( XmlSchemaParticle)sequence.Items[i], false, substitution);
1025 if (p1 != XmlSchemaParticle.Empty) {
1026 if (p1.MinOccurs == decimal.One && p1.MaxOccurs == decimal.One && p1 is XmlSchemaSequence) {
1027 XmlSchemaSequence particleSequence = (XmlSchemaSequence)p1;
1028 for (int j = 0; j < particleSequence.Items.Count; ++j) {
1029 newSequence.Items.Add(particleSequence.Items[j]);
1033 newSequence.Items.Add(p1);
1037 sequence = newSequence;
1039 if (sequence.Items.Count == 0) {
1040 return XmlSchemaParticle.Empty;
1042 else if (!root && sequence.Items.Count == 1 && sequence.MinOccurs == decimal.One && sequence.MaxOccurs == decimal.One) {
1043 return (XmlSchemaParticle)sequence.Items[0];
1050 private bool IsValidRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) {
1051 if (derivedParticle == baseParticle) {
1054 else if (derivedParticle == null || derivedParticle == XmlSchemaParticle.Empty) {
1055 return IsParticleEmptiable(baseParticle);
1057 else if (baseParticle == null || baseParticle == XmlSchemaParticle.Empty) {
1060 if (baseParticle is XmlSchemaElement) {
1061 if (derivedParticle is XmlSchemaElement) {
1062 return IsElementFromElement((XmlSchemaElement)derivedParticle, (XmlSchemaElement)baseParticle);
1068 else if (baseParticle is XmlSchemaAny) {
1069 if (derivedParticle is XmlSchemaElement) {
1070 return IsElementFromAny((XmlSchemaElement)derivedParticle, (XmlSchemaAny)baseParticle);
1072 else if (derivedParticle is XmlSchemaAny) {
1073 return IsAnyFromAny((XmlSchemaAny)derivedParticle, (XmlSchemaAny)baseParticle);
1076 return IsGroupBaseFromAny((XmlSchemaGroupBase)derivedParticle, (XmlSchemaAny)baseParticle);
1079 else if (baseParticle is XmlSchemaAll) {
1080 if (derivedParticle is XmlSchemaElement) {
1081 return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle, true);
1083 else if (derivedParticle is XmlSchemaAll) {
1084 return IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true);
1086 else if (derivedParticle is XmlSchemaSequence) {
1087 return IsSequenceFromAll((XmlSchemaSequence)derivedParticle, (XmlSchemaAll)baseParticle);
1090 else if (baseParticle is XmlSchemaChoice ) {
1091 if (derivedParticle is XmlSchemaElement) {
1092 return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle, false);
1094 else if (derivedParticle is XmlSchemaChoice) {
1095 return IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, false);
1097 else if (derivedParticle is XmlSchemaSequence) {
1098 return IsSequenceFromChoice((XmlSchemaSequence)derivedParticle, (XmlSchemaChoice)baseParticle);
1101 else if (baseParticle is XmlSchemaSequence) {
1102 if (derivedParticle is XmlSchemaElement) {
1103 return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle, true);
1105 else if (derivedParticle is XmlSchemaSequence) {
1106 return IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true);
1110 Debug.Assert(false);
1116 private bool IsElementFromElement(XmlSchemaElement derivedElement, XmlSchemaElement baseElement) {
1117 return (derivedElement.QualifiedName == baseElement.QualifiedName) &&
1118 (derivedElement.IsNillable == baseElement.IsNillable) &&
1119 IsValidOccurrenceRangeRestriction(derivedElement, baseElement) &&
1120 (baseElement.FixedValue == null || baseElement.FixedValue == derivedElement.FixedValue) &&
1121 ((derivedElement.BlockResolved | baseElement.BlockResolved) == derivedElement.BlockResolved) &&
1122 (derivedElement.ElementSchemaType != null) && (baseElement.ElementSchemaType != null) &&
1123 XmlSchemaType.IsDerivedFrom(derivedElement.ElementSchemaType, baseElement.ElementSchemaType, ~XmlSchemaDerivationMethod.Restriction);
1126 private bool IsElementFromAny(XmlSchemaElement derivedElement, XmlSchemaAny baseAny) {
1127 return baseAny.Allows(derivedElement.QualifiedName) &&
1128 IsValidOccurrenceRangeRestriction(derivedElement, baseAny);
1131 private bool IsAnyFromAny(XmlSchemaAny derivedAny, XmlSchemaAny baseAny) {
1132 return IsValidOccurrenceRangeRestriction(derivedAny, baseAny) &&
1133 NamespaceList.IsSubset(derivedAny.NamespaceList, baseAny.NamespaceList);
1136 private bool IsGroupBaseFromAny(XmlSchemaGroupBase derivedGroupBase, XmlSchemaAny baseAny) {
1137 decimal minOccurs, maxOccurs;
1138 CalculateEffectiveTotalRange(derivedGroupBase, out minOccurs, out maxOccurs);
1139 if (!IsValidOccurrenceRangeRestriction(minOccurs, maxOccurs, baseAny.MinOccurs, baseAny.MaxOccurs)) {
1142 // eliminate occurrance range check
1143 string minOccursAny = baseAny.MinOccursString;
1144 baseAny.MinOccurs = decimal.Zero;
1146 for (int i = 0; i < derivedGroupBase.Items.Count; ++i) {
1147 if (!IsValidRestriction((XmlSchemaParticle)derivedGroupBase.Items[i], baseAny)) {
1148 baseAny.MinOccursString = minOccursAny;
1152 baseAny.MinOccursString = minOccursAny;
1156 private bool IsElementFromGroupBase(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase, bool skipEmptableOnly) {
1157 bool isMatched = false;
1158 for (int i = 0; i < baseGroupBase.Items.Count; ++i) {
1159 XmlSchemaParticle baseParticle = (XmlSchemaParticle)baseGroupBase.Items[i];
1161 string minOccursElement = baseParticle.MinOccursString;
1162 string maxOccursElement = baseParticle.MaxOccursString;
1163 baseParticle.MinOccurs *= baseGroupBase.MinOccurs;
1164 if ( baseParticle.MaxOccurs != decimal.MaxValue) {
1165 if (baseGroupBase.MaxOccurs == decimal.MaxValue)
1166 baseParticle.MaxOccurs = decimal.MaxValue;
1168 baseParticle.MaxOccurs *= baseGroupBase.MaxOccurs;
1170 isMatched = IsValidRestriction(derivedElement, baseParticle);
1171 baseParticle.MinOccursString = minOccursElement;
1172 baseParticle.MaxOccursString = maxOccursElement;
1174 else if (skipEmptableOnly && !IsParticleEmptiable(baseParticle)) {
1181 private bool IsGroupBaseFromGroupBase(XmlSchemaGroupBase derivedGroupBase, XmlSchemaGroupBase baseGroupBase, bool skipEmptableOnly) {
1182 if (!IsValidOccurrenceRangeRestriction(derivedGroupBase, baseGroupBase) || derivedGroupBase.Items.Count > baseGroupBase.Items.Count) {
1186 for (int i = 0; i < baseGroupBase.Items.Count; ++i) {
1187 XmlSchemaParticle baseParticle = (XmlSchemaParticle)baseGroupBase.Items[i];
1188 if ((count < derivedGroupBase.Items.Count) && IsValidRestriction((XmlSchemaParticle)derivedGroupBase.Items[count], baseParticle)) {
1191 else if (skipEmptableOnly && !IsParticleEmptiable(baseParticle)) {
1195 if (count < derivedGroupBase.Items.Count) {
1201 private bool IsSequenceFromAll(XmlSchemaSequence derivedSequence, XmlSchemaAll baseAll) {
1202 if (!IsValidOccurrenceRangeRestriction(derivedSequence, baseAll) || derivedSequence.Items.Count > baseAll.Items.Count) {
1205 BitSet map = new BitSet(baseAll.Items.Count);
1206 for (int j = 0; j < derivedSequence.Items.Count; ++j) {
1207 int i = GetMappingParticle((XmlSchemaParticle)derivedSequence.Items[j], baseAll.Items);
1220 for (int i = 0; i < baseAll.Items.Count; i++) {
1221 if (!map[i] && !IsParticleEmptiable((XmlSchemaParticle)baseAll.Items[i])) {
1228 private bool IsSequenceFromChoice(XmlSchemaSequence derivedSequence, XmlSchemaChoice baseChoice) {
1229 decimal minOccurs, maxOccurs;
1230 CalculateSequenceRange(derivedSequence, out minOccurs, out maxOccurs);
1231 if (!IsValidOccurrenceRangeRestriction(minOccurs, maxOccurs, baseChoice.MinOccurs, baseChoice.MaxOccurs) || derivedSequence.Items.Count > baseChoice.Items.Count) {
1234 for (int i = 0; i < derivedSequence.Items.Count; ++i) {
1235 if (GetMappingParticle((XmlSchemaParticle)derivedSequence.Items[i], baseChoice.Items) < 0)
1241 private void CalculateSequenceRange(XmlSchemaSequence sequence, out decimal minOccurs, out decimal maxOccurs) {
1242 minOccurs = decimal.Zero; maxOccurs = decimal.Zero;
1243 for (int i = 0; i < sequence.Items.Count; ++i) {
1244 XmlSchemaParticle p = (XmlSchemaParticle)sequence.Items[i];
1246 minOccurs += p.MinOccurs;
1247 if (p.MaxOccurs == decimal.MaxValue)
1248 maxOccurs = decimal.MaxValue;
1249 else if (maxOccurs != decimal.MaxValue)
1250 maxOccurs += p.MaxOccurs;
1252 minOccurs *= sequence.MinOccurs;
1253 if (sequence.MaxOccurs == decimal.MaxValue) {
1254 maxOccurs = decimal.MaxValue;
1256 else if (maxOccurs != decimal.MaxValue) {
1257 maxOccurs *= sequence.MaxOccurs;
1261 private bool IsValidOccurrenceRangeRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) {
1262 return IsValidOccurrenceRangeRestriction(derivedParticle.MinOccurs, derivedParticle.MaxOccurs, baseParticle.MinOccurs, baseParticle.MaxOccurs);
1265 private bool IsValidOccurrenceRangeRestriction(decimal minOccurs, decimal maxOccurs, decimal baseMinOccurs, decimal baseMaxOccurs) {
1266 return (baseMinOccurs <= minOccurs) && (maxOccurs <= baseMaxOccurs);
1269 private int GetMappingParticle(XmlSchemaParticle particle, XmlSchemaObjectCollection collection) {
1270 for (int i = 0; i < collection.Count; i++) {
1271 if (IsValidRestriction(particle, (XmlSchemaParticle)collection[i]))
1277 private bool IsParticleEmptiable(XmlSchemaParticle particle) {
1278 decimal minOccurs, maxOccurs;
1279 CalculateEffectiveTotalRange(particle, out minOccurs, out maxOccurs);
1280 return minOccurs == decimal.Zero;
1283 private void CalculateEffectiveTotalRange(XmlSchemaParticle particle, out decimal minOccurs, out decimal maxOccurs) {
1284 if (particle is XmlSchemaElement || particle is XmlSchemaAny) {
1285 minOccurs = particle.MinOccurs;
1286 maxOccurs = particle.MaxOccurs;
1288 else if (particle is XmlSchemaChoice) {
1289 if (((XmlSchemaChoice)particle).Items.Count == 0) {
1290 minOccurs = maxOccurs = decimal.Zero;
1293 minOccurs = decimal.MaxValue;
1294 maxOccurs = decimal.Zero;
1295 XmlSchemaChoice choice = (XmlSchemaChoice) particle;
1296 for (int i = 0; i < choice.Items.Count; ++i) {
1298 CalculateEffectiveTotalRange((XmlSchemaParticle) choice.Items[i], out min, out max);
1299 if (min < minOccurs) {
1302 if (max > maxOccurs) {
1306 minOccurs *= particle.MinOccurs;
1307 if (maxOccurs != decimal.MaxValue) {
1308 if (particle.MaxOccurs == decimal.MaxValue)
1309 maxOccurs = decimal.MaxValue;
1311 maxOccurs *= particle.MaxOccurs;
1316 XmlSchemaObjectCollection collection = ((XmlSchemaGroupBase)particle).Items;
1317 if (collection.Count == 0) {
1318 minOccurs = maxOccurs = decimal.Zero;
1323 for (int i = 0; i < collection.Count; ++i) {
1325 CalculateEffectiveTotalRange((XmlSchemaParticle)collection[i], out min, out max);
1327 if (maxOccurs != decimal.MaxValue) {
1328 if (max == decimal.MaxValue)
1329 maxOccurs = decimal.MaxValue;
1334 minOccurs *= particle.MinOccurs;
1335 if (maxOccurs != decimal.MaxValue) {
1336 if (particle.MaxOccurs == decimal.MaxValue)
1337 maxOccurs = decimal.MaxValue;
1339 maxOccurs *= particle.MaxOccurs;
1345 private void PushComplexType(XmlSchemaComplexType complexType) {
1346 this.complexTypeStack.Push(complexType);
1349 private XmlSchemaContentType GetSchemaContentType(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaParticle particle) {
1350 if ((complexContent != null && complexContent.IsMixed) ||
1351 (complexContent == null && complexType.IsMixed)) {
1352 return XmlSchemaContentType.Mixed;
1354 else if (particle != null && !particle.IsEmpty) {
1355 return XmlSchemaContentType.ElementOnly;
1358 return XmlSchemaContentType.Empty;
1362 private void CompileAttributeGroup(XmlSchemaAttributeGroup attributeGroup) {
1363 if (attributeGroup.IsProcessing) {
1364 SendValidationEvent(Res.Sch_AttributeGroupCircularRef, attributeGroup);
1367 if (attributeGroup.AttributeUses.Count > 0) {// already checked
1370 attributeGroup.IsProcessing = true;
1371 XmlSchemaAnyAttribute anyAttribute = attributeGroup.AnyAttribute;
1372 for (int i = 0; i < attributeGroup.Attributes.Count; ++i) {
1373 XmlSchemaAttribute attribute = attributeGroup.Attributes[i] as XmlSchemaAttribute;
1374 if (attribute != null) {
1375 if (attribute.Use != XmlSchemaUse.Prohibited) {
1376 CompileAttribute(attribute);
1378 if (attributeGroup.AttributeUses[attribute.QualifiedName] == null) {
1379 attributeGroup.AttributeUses.Add(attribute.QualifiedName, attribute);
1382 SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attribute);
1385 else { // XmlSchemaAttributeGroupRef
1386 XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef)attributeGroup.Attributes[i];
1387 XmlSchemaAttributeGroup attributeGroupResolved;
1388 if (attributeGroup.Redefined != null && attributeGroupRef.RefName == attributeGroup.Redefined.QualifiedName) {
1389 attributeGroupResolved = (XmlSchemaAttributeGroup)attributeGroup.Redefined;
1392 attributeGroupResolved = (XmlSchemaAttributeGroup)this.schema.AttributeGroups[attributeGroupRef.RefName];
1394 if (attributeGroupResolved != null) {
1395 CompileAttributeGroup(attributeGroupResolved);
1396 foreach (XmlSchemaAttribute attributeValue in attributeGroupResolved.AttributeUses.Values) {
1397 if (attributeGroup.AttributeUses[attributeValue.QualifiedName] == null) {
1398 attributeGroup.AttributeUses.Add(attributeValue.QualifiedName, attributeValue);
1401 SendValidationEvent(Res.Sch_DupAttributeUse, attributeValue.QualifiedName.ToString(), attributeValue);
1404 anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroupResolved.AttributeWildcard);
1407 SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef);
1411 attributeGroup.AttributeWildcard = anyAttribute;
1412 attributeGroup.IsProcessing = false;
1416 private void CompileLocalAttributes(XmlSchemaComplexType baseType, XmlSchemaComplexType derivedType, XmlSchemaObjectCollection attributes, XmlSchemaAnyAttribute anyAttribute, XmlSchemaDerivationMethod derivedBy) {
1417 XmlSchemaAnyAttribute baseAttributeWildcard = baseType != null ? baseType.AttributeWildcard : null;
1418 for (int i = 0; i < attributes.Count; ++i) {
1419 XmlSchemaAttribute attribute = attributes[i] as XmlSchemaAttribute;
1420 if (attribute != null) {
1421 if (attribute.Use != XmlSchemaUse.Prohibited) {
1422 CompileAttribute(attribute);
1424 if (attribute.Use != XmlSchemaUse.Prohibited ||
1425 (attribute.Use == XmlSchemaUse.Prohibited && derivedBy == XmlSchemaDerivationMethod.Restriction && baseType != XmlSchemaComplexType.AnyType)) {
1427 if (derivedType.AttributeUses[attribute.QualifiedName] == null) {
1428 derivedType.AttributeUses.Add(attribute.QualifiedName, attribute);
1431 SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attribute);
1435 SendValidationEvent(Res.Sch_AttributeIgnored, attribute.QualifiedName.ToString(), attribute, XmlSeverityType.Warning);
1439 else { // is XmlSchemaAttributeGroupRef
1440 XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef)attributes[i];
1441 XmlSchemaAttributeGroup attributeGroup = (XmlSchemaAttributeGroup)this.schema.AttributeGroups[attributeGroupRef.RefName];
1442 if (attributeGroup != null) {
1443 CompileAttributeGroup(attributeGroup);
1444 foreach (XmlSchemaAttribute attributeValue in attributeGroup.AttributeUses.Values) {
1445 if (attributeValue.Use != XmlSchemaUse.Prohibited ||
1446 (attributeValue.Use == XmlSchemaUse.Prohibited && derivedBy == XmlSchemaDerivationMethod.Restriction && baseType != XmlSchemaComplexType.AnyType)) {
1447 if (derivedType.AttributeUses[attributeValue.QualifiedName] == null) {
1448 derivedType.AttributeUses.Add(attributeValue.QualifiedName, attributeValue);
1451 SendValidationEvent(Res.Sch_DupAttributeUse, attributeValue.QualifiedName.ToString(), attributeGroupRef);
1455 SendValidationEvent(Res.Sch_AttributeIgnored, attributeValue.QualifiedName.ToString(), attributeValue, XmlSeverityType.Warning);
1459 anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroup.AttributeWildcard);
1462 SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef);
1467 // check derivation rules
1468 if (baseType != null) {
1469 if (derivedBy == XmlSchemaDerivationMethod.Extension) {
1470 derivedType.SetAttributeWildcard(CompileAnyAttributeUnion(anyAttribute, baseAttributeWildcard));
1471 foreach(XmlSchemaAttribute attributeBase in baseType.AttributeUses.Values) {
1472 XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedType.AttributeUses[attributeBase.QualifiedName];
1473 if (attribute != null) {
1474 Debug.Assert(attribute.Use != XmlSchemaUse.Prohibited);
1475 if (attribute.AttributeSchemaType != attributeBase.AttributeSchemaType || attributeBase.Use == XmlSchemaUse.Prohibited) {
1476 SendValidationEvent(Res.Sch_InvalidAttributeExtension, attribute);
1480 derivedType.AttributeUses.Add(attributeBase.QualifiedName, attributeBase);
1484 else { // derivedBy == XmlSchemaDerivationMethod.Restriction
1485 // Schema Component Constraint: Derivation Valid (Restriction, Complex)
1486 if ((anyAttribute != null) && (baseAttributeWildcard == null || !XmlSchemaAnyAttribute.IsSubset(anyAttribute, baseAttributeWildcard))) {
1487 SendValidationEvent(Res.Sch_InvalidAnyAttributeRestriction, derivedType);
1490 derivedType.SetAttributeWildcard(anyAttribute); //complete wildcard
1493 // Add form the base
1494 foreach(XmlSchemaAttribute attributeBase in baseType.AttributeUses.Values) {
1495 XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedType.AttributeUses[attributeBase.QualifiedName];
1496 if (attribute == null) {
1497 derivedType.AttributeUses.Add(attributeBase.QualifiedName, attributeBase);
1500 if (attributeBase.Use == XmlSchemaUse.Prohibited && attribute.Use != XmlSchemaUse.Prohibited) {
1502 string position = string.Empty;
1503 if (derivedType.SourceUri != null) {
1504 position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")";
1506 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType attributes restriction" + position);
1507 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, " Base " + DumpAttributes(baseType.AttributeUses, baseType.AttributeWildcard));
1508 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, " Derived " + DumpAttributes(derivedType.AttributeUses, derivedType.AttributeWildcard));
1510 SendValidationEvent(Res.Sch_AttributeRestrictionProhibited, attribute);
1512 else if (attribute.Use == XmlSchemaUse.Prohibited) {
1515 else if (attributeBase.AttributeSchemaType == null || attribute.AttributeSchemaType == null || !XmlSchemaType.IsDerivedFrom(attribute.AttributeSchemaType, attributeBase.AttributeSchemaType, XmlSchemaDerivationMethod.Empty)) {
1516 SendValidationEvent(Res.Sch_AttributeRestrictionInvalid, attribute);
1521 // Check additional ones are valid restriction of base's wildcard
1522 foreach(XmlSchemaAttribute attribute in derivedType.AttributeUses.Values) {
1523 XmlSchemaAttribute attributeBase = (XmlSchemaAttribute)baseType.AttributeUses[attribute.QualifiedName];
1524 if (attributeBase != null) {
1527 if (baseAttributeWildcard == null || !baseAttributeWildcard.Allows(attribute.QualifiedName)) {
1529 string position = string.Empty;
1530 if (derivedType.SourceUri != null) {
1531 position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")";
1533 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType attributes restriction" + position);
1534 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, " Base " + DumpAttributes(baseType.AttributeUses, baseType.AttributeWildcard));
1535 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, " Derived " + DumpAttributes(derivedType.AttributeUses, derivedType.AttributeWildcard));
1537 SendValidationEvent(Res.Sch_AttributeRestrictionInvalidFromWildcard, attribute);
1543 derivedType.SetAttributeWildcard(anyAttribute);
1549 private string DumpAttributes(XmlSchemaObjectTable attributeUses, XmlSchemaAnyAttribute attributeWildcard) {
1550 StringBuilder sb = new StringBuilder();
1553 foreach (XmlSchemaAttribute attribute in attributeUses.Values) {
1554 if (attribute.Use != XmlSchemaUse.Prohibited) {
1561 sb.Append(attribute.QualifiedName.Name);
1562 if (attribute.Use == XmlSchemaUse.Optional) {
1567 if (attributeWildcard != null) {
1568 if (attributeUses.Count != 0) {
1572 sb.Append(attributeWildcard.NamespaceList.ToString());
1577 foreach (XmlSchemaAttribute attribute in attributeUses.Values) {
1578 if (attribute.Use == XmlSchemaUse.Prohibited) {
1585 sb.Append(attribute.QualifiedName.Name);
1589 return sb.ToString();
1593 private XmlSchemaAnyAttribute CompileAnyAttributeUnion(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) {
1597 else if (b == null) {
1601 XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Union(a, b, true); //true for v1Compat
1602 if (attribute == null) {
1603 SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a);
1610 private XmlSchemaAnyAttribute CompileAnyAttributeIntersection(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) {
1614 else if (b == null) {
1618 XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Intersection(a, b, true); //true for v1Compat
1619 if (attribute == null) {
1620 SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a);
1626 private void CompileAttribute(XmlSchemaAttribute xa) {
1627 if (xa.IsProcessing) {
1628 SendValidationEvent(Res.Sch_AttributeCircularRef, xa);
1631 if (xa.AttDef != null) { //already compiled?
1634 xa.IsProcessing = true;
1635 SchemaAttDef decl = null;
1637 if (!xa.RefName.IsEmpty) {
1638 XmlSchemaAttribute a = (XmlSchemaAttribute)this.schema.Attributes[xa.RefName];
1640 throw new XmlSchemaException(Res.Sch_UndeclaredAttribute, xa.RefName.ToString(), xa);
1642 CompileAttribute(a);
1643 if (a.AttDef == null) {
1644 throw new XmlSchemaException(Res.Sch_RefInvalidAttribute, xa.RefName.ToString(), xa);
1646 decl = a.AttDef.Clone();
1647 if(decl.Datatype != null) {
1648 if(a.FixedValue != null) {
1649 if(xa.DefaultValue != null) {
1650 throw new XmlSchemaException(Res.Sch_FixedDefaultInRef, xa.RefName.ToString(), xa);
1652 else if(xa.FixedValue != null ) {
1653 if (xa.FixedValue != a.FixedValue) {
1654 throw new XmlSchemaException(Res.Sch_FixedInRef, xa.RefName.ToString(), xa);
1658 decl.Presence = SchemaDeclBase.Use.Fixed;
1659 decl.DefaultValueRaw = decl.DefaultValueExpanded = a.FixedValue;
1660 decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xa), true);
1663 else if (a.DefaultValue != null) {
1664 if(xa.DefaultValue == null && xa.FixedValue == null) {
1665 decl.Presence = SchemaDeclBase.Use.Default;
1666 decl.DefaultValueRaw = decl.DefaultValueExpanded = a.DefaultValue;
1667 decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xa), true);
1671 xa.SetAttributeType(a.AttributeSchemaType);
1674 decl = new SchemaAttDef(xa.QualifiedName);
1675 if (xa.SchemaType != null) {
1676 CompileSimpleType(xa.SchemaType);
1677 xa.SetAttributeType(xa.SchemaType);
1678 decl.SchemaType = xa.SchemaType;
1679 decl.Datatype = xa.SchemaType.Datatype;
1681 else if (!xa.SchemaTypeName.IsEmpty) {
1682 XmlSchemaSimpleType simpleType = GetSimpleType(xa.SchemaTypeName);
1683 if (simpleType != null) {
1684 xa.SetAttributeType(simpleType);
1685 decl.Datatype = simpleType.Datatype;
1686 decl.SchemaType = simpleType;
1689 throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, xa.SchemaTypeName.ToString(), xa);
1693 decl.SchemaType = DatatypeImplementation.AnySimpleType;
1694 decl.Datatype = DatatypeImplementation.AnySimpleType.Datatype;
1695 xa.SetAttributeType(DatatypeImplementation.AnySimpleType);
1698 if (decl.Datatype != null) {
1699 decl.Datatype.VerifySchemaValid(this.schema.Notations, xa);
1701 if (xa.DefaultValue != null || xa.FixedValue != null) {
1702 if (xa.DefaultValue != null) {
1703 decl.Presence = SchemaDeclBase.Use.Default;
1704 decl.DefaultValueRaw = decl.DefaultValueExpanded = xa.DefaultValue;
1707 decl.Presence = SchemaDeclBase.Use.Fixed;
1708 decl.DefaultValueRaw = decl.DefaultValueExpanded = xa.FixedValue;
1710 if(decl.Datatype != null) {
1711 decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xa), true);
1716 case XmlSchemaUse.None:
1717 case XmlSchemaUse.Optional:
1718 decl.Presence = SchemaDeclBase.Use.Implied;
1720 case XmlSchemaUse.Required:
1721 decl.Presence = SchemaDeclBase.Use.Required;
1723 case XmlSchemaUse.Prohibited:
1727 decl.SchemaAttribute = xa; //So this is available for PSVI
1730 catch (XmlSchemaException e) {
1731 if (e.SourceSchemaObject == null) {
1734 SendValidationEvent(e);
1735 xa.AttDef = SchemaAttDef.Empty;
1738 xa.IsProcessing = false;
1742 private void CompileIdentityConstraint (XmlSchemaIdentityConstraint xi) {
1743 if (xi.IsProcessing) {
1744 xi.CompiledConstraint = CompiledIdentityConstraint.Empty;
1745 SendValidationEvent(Res.Sch_IdentityConstraintCircularRef, xi);
1749 if (xi.CompiledConstraint != null) {
1753 xi.IsProcessing = true;
1754 CompiledIdentityConstraint compic = null;
1756 SchemaNamespaceManager xnmgr = new SchemaNamespaceManager(xi);
1757 compic = new CompiledIdentityConstraint(xi, xnmgr);
1758 if (xi is XmlSchemaKeyref) {
1759 XmlSchemaIdentityConstraint ic = (XmlSchemaIdentityConstraint)this.schema.IdentityConstraints[((XmlSchemaKeyref)xi).Refer];
1761 throw new XmlSchemaException(Res.Sch_UndeclaredIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi);
1763 CompileIdentityConstraint(ic);
1764 if (ic.CompiledConstraint == null) {
1765 throw new XmlSchemaException(Res.Sch_RefInvalidIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi);
1767 // keyref has the different cardinality with the key it referred
1768 if (ic.Fields.Count != xi.Fields.Count) {
1769 throw new XmlSchemaException(Res.Sch_RefInvalidCardin, xi.QualifiedName.ToString(), xi);
1771 // keyref can only refer to key/unique
1772 if (ic.CompiledConstraint.Role == CompiledIdentityConstraint.ConstraintRole.Keyref) {
1773 throw new XmlSchemaException(Res.Sch_ReftoKeyref, xi.QualifiedName.ToString(), xi);
1776 xi.CompiledConstraint = compic;
1778 catch (XmlSchemaException e) {
1779 if (e.SourceSchemaObject == null) {
1782 SendValidationEvent(e);
1783 xi.CompiledConstraint = CompiledIdentityConstraint.Empty;
1784 // empty is better than null here, stop quickly when circle referencing
1787 xi.IsProcessing = false;
1792 private void CompileElement(XmlSchemaElement xe) {
1793 if (xe.IsProcessing) {
1794 SendValidationEvent(Res.Sch_ElementCircularRef, xe);
1797 if (xe.ElementDecl != null) {
1800 xe.IsProcessing = true;
1801 SchemaElementDecl decl = null;
1803 if (!xe.RefName.IsEmpty) {
1804 XmlSchemaElement e = (XmlSchemaElement)this.schema.Elements[xe.RefName];
1806 throw new XmlSchemaException(Res.Sch_UndeclaredElement, xe.RefName.ToString(), xe);
1809 if (e.ElementDecl == null) {
1810 throw new XmlSchemaException(Res.Sch_RefInvalidElement, xe.RefName.ToString(), xe);
1812 xe.SetElementType(e.ElementSchemaType);
1813 decl = e.ElementDecl.Clone();
1816 if (xe.SchemaType != null) {
1817 xe.SetElementType(xe.SchemaType);
1819 else if (!xe.SchemaTypeName.IsEmpty) {
1820 xe.SetElementType(GetAnySchemaType(xe.SchemaTypeName));
1821 if (xe.ElementSchemaType == null) {
1822 throw new XmlSchemaException(Res.Sch_UndeclaredType, xe.SchemaTypeName.ToString(), xe);
1825 else if (!xe.SubstitutionGroup.IsEmpty) {
1826 XmlSchemaElement examplar = (XmlSchemaElement)this.schema.Elements[xe.SubstitutionGroup];
1827 if (examplar == null) {
1828 throw new XmlSchemaException(Res.Sch_UndeclaredEquivClass, xe.SubstitutionGroup.Name.ToString(CultureInfo.InvariantCulture), xe);
1830 if (examplar.IsProcessing) { //Circular subst group; already detected by now
1833 CompileElement(examplar);
1834 if (examplar.ElementDecl == null) { //If head is invalid, fall back to AnyType
1835 xe.SetElementType(XmlSchemaComplexType.AnyType);
1836 decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone();
1839 xe.SetElementType(examplar.ElementSchemaType);
1840 decl = examplar.ElementDecl.Clone();
1844 xe.SetElementType(XmlSchemaComplexType.AnyType);
1845 decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone();
1849 Debug.Assert(xe.ElementSchemaType != null);
1850 if (xe.ElementSchemaType is XmlSchemaComplexType) {
1851 XmlSchemaComplexType complexType = (XmlSchemaComplexType)xe.ElementSchemaType;
1852 CompileComplexType(complexType);
1853 if (complexType.ElementDecl != null) {
1854 decl = complexType.ElementDecl.Clone();
1855 // decl.LocalElements = complexType.LocalElementDecls;
1858 else if (xe.ElementSchemaType is XmlSchemaSimpleType) {
1859 XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)xe.ElementSchemaType;
1860 CompileSimpleType(simpleType);
1861 if (simpleType.ElementDecl != null) {
1862 decl = simpleType.ElementDecl.Clone();
1866 decl.Name = xe.QualifiedName;
1867 decl.IsAbstract = xe.IsAbstract;
1868 XmlSchemaComplexType ct = xe.ElementSchemaType as XmlSchemaComplexType;
1870 decl.IsAbstract |= ct.IsAbstract;
1872 decl.IsNillable = xe.IsNillable;
1873 decl.Block |= xe.BlockResolved;
1875 if (decl.Datatype != null) {
1876 decl.Datatype.VerifySchemaValid(this.schema.Notations, xe);
1879 if (xe.DefaultValue != null || xe.FixedValue != null) {
1880 if (decl.ContentValidator != null) {
1881 if (decl.ContentValidator.ContentType == XmlSchemaContentType.TextOnly) {
1882 if (xe.DefaultValue != null) {
1883 decl.Presence = SchemaDeclBase.Use.Default;
1884 decl.DefaultValueRaw = xe.DefaultValue;
1887 decl.Presence = SchemaDeclBase.Use.Fixed;
1888 decl.DefaultValueRaw = xe.FixedValue;
1890 if (decl.Datatype != null) {
1891 decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe), true);
1894 else if (decl.ContentValidator.ContentType != XmlSchemaContentType.Mixed || !decl.ContentValidator.IsEmptiable) {
1895 throw new XmlSchemaException(Res.Sch_ElementCannotHaveValue, xe);
1899 if (xe.HasConstraints) {
1900 XmlSchemaObjectCollection constraints = xe.Constraints;
1901 CompiledIdentityConstraint[] compiledConstraints = new CompiledIdentityConstraint[constraints.Count];
1903 for (int i = 0; i < constraints.Count; ++i) {
1904 XmlSchemaIdentityConstraint constraint = (XmlSchemaIdentityConstraint)constraints[i];
1905 CompileIdentityConstraint (constraint);
1906 compiledConstraints[idx ++] = constraint.CompiledConstraint;
1908 decl.Constraints = compiledConstraints;
1910 decl.SchemaElement = xe; //So this is available for PSVI
1911 xe.ElementDecl = decl;
1913 catch (XmlSchemaException e) {
1914 if (e.SourceSchemaObject == null) {
1917 SendValidationEvent(e);
1918 xe.ElementDecl = SchemaElementDecl.Empty;
1921 xe.IsProcessing = false;
1925 private ContentValidator CompileComplexContent(XmlSchemaComplexType complexType) {
1926 if (complexType.ContentType == XmlSchemaContentType.Empty) {
1927 return ContentValidator.Empty;
1929 else if (complexType.ContentType == XmlSchemaContentType.TextOnly) {
1930 return ContentValidator.TextOnly;
1932 XmlSchemaParticle particle = complexType.ContentTypeParticle;
1933 if (particle == null || particle == XmlSchemaParticle.Empty) {
1934 if (complexType.ContentType == XmlSchemaContentType.ElementOnly) {
1935 return ContentValidator.Empty;
1938 return ContentValidator.Mixed;
1941 PushComplexType(complexType);
1942 if (particle is XmlSchemaAll) {
1943 XmlSchemaAll all = (XmlSchemaAll)particle;
1944 AllElementsContentValidator contentValidator = new AllElementsContentValidator(complexType.ContentType, all.Items.Count, all.MinOccurs == decimal.Zero);
1945 for (int i = 0; i < all.Items.Count; ++i) {
1946 XmlSchemaElement localElement = (XmlSchemaElement)all.Items[i];
1947 if (!contentValidator.AddElement(localElement.QualifiedName, localElement, localElement.MinOccurs == decimal.Zero)) {
1948 SendValidationEvent(Res.Sch_DupElement, localElement.QualifiedName.ToString(), localElement);
1951 return contentValidator;
1954 ParticleContentValidator contentValidator = new ParticleContentValidator(complexType.ContentType);
1956 string name = complexType.Name != null ? complexType.Name : string.Empty;
1957 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceVerbose, "CompileComplexContent: "+ name + DumpContentModel(particle));
1960 contentValidator.Start();
1961 BuildParticleContentModel(contentValidator, particle);
1962 return contentValidator.Finish(compileContentModel);
1964 catch(UpaException e) {
1965 if (e.Particle1 is XmlSchemaElement) {
1966 if (e.Particle2 is XmlSchemaElement) {
1967 SendValidationEvent(Res.Sch_NonDeterministic, ((XmlSchemaElement)e.Particle1).QualifiedName.ToString(), (XmlSchemaElement)e.Particle2);
1970 SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle2).NamespaceList.ToString(), ((XmlSchemaElement)e.Particle1).QualifiedName.ToString(), (XmlSchemaAny)e.Particle2);
1974 if (e.Particle2 is XmlSchemaElement) {
1975 SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle1).NamespaceList.ToString(), ((XmlSchemaElement)e.Particle2).QualifiedName.ToString(), (XmlSchemaAny)e.Particle1);
1978 SendValidationEvent(Res.Sch_NonDeterministicAnyAny, ((XmlSchemaAny)e.Particle1).NamespaceList.ToString(), ((XmlSchemaAny)e.Particle2).NamespaceList.ToString() ,(XmlSchemaAny)e.Particle1);
1981 return XmlSchemaComplexType.AnyTypeContentValidator;
1983 catch(NotSupportedException) {
1984 SendValidationEvent(Res.Sch_ComplexContentModel, complexType, XmlSeverityType.Warning);
1985 return XmlSchemaComplexType.AnyTypeContentValidator;
1991 private string DumpContentModel(XmlSchemaParticle particle) {
1992 StringBuilder sb = new StringBuilder();
1993 DumpContentModelTo(sb, particle);
1994 return sb.ToString();
1997 private void DumpContentModelTo(StringBuilder sb, XmlSchemaParticle particle) {
1998 if (particle is XmlSchemaElement) {
1999 sb.Append(((XmlSchemaElement)particle).QualifiedName);
2001 else if (particle is XmlSchemaAny) {
2003 sb.Append(((XmlSchemaAny)particle).NamespaceList.ToString());
2006 else if (particle is XmlSchemaAll) {
2007 XmlSchemaAll all = (XmlSchemaAll)particle;
2010 for (int i = 0; i < all.Items.Count; ++i) {
2011 XmlSchemaElement localElement = (XmlSchemaElement)all.Items[i];
2018 sb.Append(localElement.QualifiedName.Name);
2019 if (localElement.MinOccurs == decimal.Zero) {
2025 else if (particle is XmlSchemaGroupBase) {
2026 XmlSchemaGroupBase gb = (XmlSchemaGroupBase)particle;
2028 string delimeter = (particle is XmlSchemaChoice) ? " | " : ", ";
2030 for (int i = 0; i < gb.Items.Count; ++i) {
2035 sb.Append(delimeter);
2037 DumpContentModelTo(sb, (XmlSchemaParticle)gb.Items[i]);
2041 Debug.Assert(particle == XmlSchemaParticle.Empty);
2044 if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) {
2047 else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) {
2050 else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) {
2053 else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) {
2057 sb.Append("{" + particle.MinOccurs.ToString(NumberFormatInfo.InvariantInfo) +", " + particle.MaxOccurs.ToString(NumberFormatInfo.InvariantInfo) + "}");
2062 private void BuildParticleContentModel(ParticleContentValidator contentValidator, XmlSchemaParticle particle) {
2063 if (particle is XmlSchemaElement) {
2064 XmlSchemaElement element = (XmlSchemaElement)particle;
2065 contentValidator.AddName(element.QualifiedName, element);
2067 else if (particle is XmlSchemaAny) {
2068 XmlSchemaAny any = (XmlSchemaAny)particle;
2069 contentValidator.AddNamespaceList(any.NamespaceList, any);
2071 else if (particle is XmlSchemaGroupBase) {
2072 XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items;
2073 bool isChoice = particle is XmlSchemaChoice;
2074 contentValidator.OpenGroup();
2076 for (int i = 0; i < particles.Count; ++i) {
2077 XmlSchemaParticle p = (XmlSchemaParticle)particles[i];
2078 Debug.Assert(!p.IsEmpty);
2082 else if (isChoice) {
2083 contentValidator.AddChoice();
2086 contentValidator.AddSequence();
2088 BuildParticleContentModel(contentValidator, p);
2090 contentValidator.CloseGroup();
2093 Debug.Assert(false);
2095 if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) {
2098 else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) {
2099 contentValidator.AddQMark();
2101 else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) {
2102 contentValidator.AddStar();
2104 else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) {
2105 contentValidator.AddPlus();
2108 contentValidator.AddLeafRange(particle.MinOccurs, particle.MaxOccurs);
2112 private void CompileParticleElements(XmlSchemaComplexType complexType, XmlSchemaParticle particle) {
2113 if (particle is XmlSchemaElement) {
2114 XmlSchemaElement localElement = (XmlSchemaElement)particle;
2115 CompileElement(localElement);
2116 if (complexType.LocalElements[localElement.QualifiedName] == null) {
2117 complexType.LocalElements.Add(localElement.QualifiedName, localElement);
2120 XmlSchemaElement element = (XmlSchemaElement)complexType.LocalElements[localElement.QualifiedName];
2121 if (element.ElementSchemaType != localElement.ElementSchemaType) {
2122 SendValidationEvent(Res.Sch_ElementTypeCollision, particle);
2126 else if (particle is XmlSchemaGroupBase) {
2127 XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items;
2128 for (int i = 0; i < particles.Count; ++i) {
2129 CompileParticleElements(complexType, (XmlSchemaParticle)particles[i]);
2134 private void CompileCompexTypeElements(XmlSchemaComplexType complexType) {
2135 if (complexType.IsProcessing) {
2136 SendValidationEvent(Res.Sch_TypeCircularRef, complexType);
2139 complexType.IsProcessing = true;
2140 if (complexType.ContentTypeParticle != XmlSchemaParticle.Empty) {
2141 CompileParticleElements(complexType, complexType.ContentTypeParticle);
2143 complexType.IsProcessing = false;
2146 private XmlSchemaSimpleType GetSimpleType(XmlQualifiedName name) {
2147 XmlSchemaSimpleType type = this.schema.SchemaTypes[name] as XmlSchemaSimpleType;
2149 CompileSimpleType(type);
2152 type = DatatypeImplementation.GetSimpleTypeFromXsdType(name);
2153 //Re-assign datatype impl for V1Compat
2155 if (type.TypeCode == XmlTypeCode.NormalizedString) {
2156 type = DatatypeImplementation.GetNormalizedStringTypeV1Compat();
2158 else if (type.TypeCode == XmlTypeCode.Token) {
2159 type = DatatypeImplementation.GetTokenTypeV1Compat();
2166 private XmlSchemaComplexType GetComplexType(XmlQualifiedName name) {
2167 XmlSchemaComplexType type = this.schema.SchemaTypes[name] as XmlSchemaComplexType;
2169 CompileComplexType(type);
2174 private XmlSchemaType GetAnySchemaType(XmlQualifiedName name) {
2175 XmlSchemaType type = (XmlSchemaType)this.schema.SchemaTypes[name];
2177 if (type is XmlSchemaComplexType) {
2178 CompileComplexType((XmlSchemaComplexType)type);
2181 CompileSimpleType((XmlSchemaSimpleType)type);
2185 else { //Its is a built-in simpleType
2186 XmlSchemaSimpleType simpleType = DatatypeImplementation.GetSimpleTypeFromXsdType(name);
2192 } // namespace System.Xml