private void TraverseParticle(XmlSchemaParticle particle, XmlSchemaComplexType baseType, ClrContentTypeInfo typeInfo, XmlSchemaDerivationMethod derivationMethod) { if (particleStack == null) { particleStack = new Stack <ParticleData>(); } else { particleStack.Clear(); } if (propertyNameTypeTable == null) { propertyNameTypeTable = new Dictionary <string, ClrPropertyInfo>(); } else { propertyNameTypeTable.Clear(); } XmlSchemaParticle baseParticle = baseType.ContentTypeParticle; ParticleData particleData; GroupingInfo parentGroupInfo = null; StringBuilder regEx = new StringBuilder(); XmlSchemaGroupBase currentGroupBase = null; GroupingInfo currentGroupingInfo = null; int currentIndex = 0; while (true) { // dont interrogate a particle if we are past the end of the list if (currentGroupBase == null || currentIndex <= currentGroupBase.Items.Count) { ParticleType particleType = particle.GetParticleType(); switch (particleType) { case ParticleType.Element: { XmlSchemaElement elem = particle as XmlSchemaElement; ClrPropertyInfo propertyInfo = null; bool fromBaseType = false; if (derivationMethod == XmlSchemaDerivationMethod.Extension && typeInfo.IsDerived) { if (baseParticle.ContainsElement(elem)) { fromBaseType = true; } else if (!typeInfo.InlineBaseType && baseType.ContainsName(elem.QualifiedName)) { typeInfo.InlineBaseType = true; } } propertyInfo = BuildProperty(elem, fromBaseType); regEx.Append(propertyInfo.PropertyName); AppendOccurenceToRegex(propertyInfo, regEx); //Add to parent if (currentGroupingInfo == null) { //Not adding property to propertyNameTypeTable as this case will occur only for pointless groups, so they have just one property BuildAnnotationInformation(propertyInfo, elem, false, false); typeInfo.AddMember(propertyInfo); } else { BuildAnnotationInformation(propertyInfo, elem, currentGroupingInfo.ContentModelType == ContentModelType.Choice, currentGroupingInfo.IsNested); currentGroupingInfo.AddChild(propertyInfo); SetPropertyFlags(propertyInfo, currentGroupingInfo, elem.ElementSchemaType); } break; } case ParticleType.Any: { regEx.Append("any"); XmlSchemaAny any = particle as XmlSchemaAny; if (derivationMethod == XmlSchemaDerivationMethod.Extension && typeInfo.IsDerived) { if (baseParticle.ContainsWildCard(any)) { typeInfo.HasElementWildCard = true; //ANY property in the base type will be reused } } //Note we always create a property info object to keep the original nesting structure in the schema //so it can be used to create a correct FSM; on the other hand, typeInfo.HasElementWildCard will indicate whether //we need to create a property in the resulting object type. ClrWildCardPropertyInfo wcPropertyInfo = BuildAnyProperty(any, !typeInfo.HasElementWildCard); //Add to parent if (currentGroupingInfo == null) { typeInfo.AddMember(wcPropertyInfo); } else { currentGroupingInfo.AddChild(wcPropertyInfo); } if (!typeInfo.HasElementWildCard) { typeInfo.HasElementWildCard = true; } break; } case ParticleType.Sequence: case ParticleType.Choice: case ParticleType.All: regEx.Append("("); if (currentGroupBase != null) { //already there is a group that we are processing, push it on stack to process sub-group particleStack.Push( new ParticleData(currentGroupBase, currentGroupingInfo, currentIndex)); currentIndex = 0; //Re-start index for new group base } parentGroupInfo = currentGroupingInfo; //Assign parent before creating child groupInfo currentGroupBase = particle as XmlSchemaGroupBase; Debug.Assert(currentGroupBase != null); currentGroupingInfo = new GroupingInfo((ContentModelType)((int)particleType), GetOccurence(currentGroupBase)); //Add to parent if (parentGroupInfo == null) { typeInfo.AddMember(currentGroupingInfo); parentGroupInfo = currentGroupingInfo; //Assign first time } else { parentGroupInfo.AddChild(currentGroupingInfo); parentGroupInfo.HasChildGroups = true; currentGroupingInfo.IsNested = true; if (parentGroupInfo.IsRepeating) { currentGroupingInfo.IsRepeating = true; } if (currentGroupingInfo.IsRepeating) { parentGroupInfo.HasRepeatingGroups = true; } } break; } } //Drill down into items if (currentGroupBase != null && currentIndex < currentGroupBase.Items.Count) { // if this isnt the first, then we need a seperator if (currentIndex > 0) { regEx.Append(currentGroupingInfo.ContentModelType == ContentModelType.Choice ? " | " : ", "); } particle = (XmlSchemaParticle)currentGroupBase.Items[currentIndex++]; } else { if (currentGroupBase != null) { regEx.Append(")"); AppendOccurenceToRegex(currentGroupingInfo, regEx); } if (particleStack.Count > 0) { bool childGroupHasRecurringElements = currentGroupingInfo.HasRecurrentElements; bool childGroupHasRepeatingGroups = currentGroupingInfo.HasRepeatingGroups; particleData = particleStack.Pop(); currentGroupBase = particleData.currentGroupBase; currentGroupingInfo = particleData.currentGroupingInfo; currentGroupingInfo.HasRecurrentElements = childGroupHasRecurringElements; currentGroupingInfo.HasRepeatingGroups = childGroupHasRepeatingGroups; currentIndex = particleData.currentIndex; if (currentIndex < currentGroupBase.Items.Count) { particle = (XmlSchemaParticle)currentGroupBase.Items[currentIndex++]; regEx.Append(currentGroupingInfo.ContentModelType == ContentModelType.Choice ? "|" : ", "); } else { // we were already at the end of the parent group, so just continue currentIndex++; //we are off the end of this list } } else { //No more particles to process break; } } } if (regEx.Length != 0) { typeInfo.ContentModelRegEx = regEx.ToString(); } }
private void TraverseParticle(XmlSchemaParticle particle, XmlSchemaComplexType baseType, ClrContentTypeInfo typeInfo, XmlSchemaDerivationMethod derivationMethod) { if (this.particleStack != null) { this.particleStack.Clear(); } else { this.particleStack = new Stack <XsdToTypesConverter.ParticleData>(); } if (this.propertyNameTypeTable != null) { this.propertyNameTypeTable.Clear(); } else { this.propertyNameTypeTable = new Dictionary <string, ClrPropertyInfo>(); } XmlSchemaParticle baseParticle = baseType.ContentTypeParticle; GroupingInfo parentGroupInfo = null; StringBuilder regEx = new StringBuilder(); XmlSchemaGroupBase currentGroupBase = null; GroupingInfo currentGroupingInfo = null; int currentIndex = 0; while (true) { if ((currentGroupBase == null ? true : currentIndex <= currentGroupBase.Items.Count)) { ParticleType particleType = particle.GetParticleType(); switch (particleType) { case ParticleType.Sequence: case ParticleType.Choice: case ParticleType.All: { regEx.Append("("); if (currentGroupBase != null) { this.particleStack.Push(new XsdToTypesConverter.ParticleData(currentGroupBase, currentGroupingInfo, currentIndex)); currentIndex = 0; } parentGroupInfo = currentGroupingInfo; currentGroupBase = particle as XmlSchemaGroupBase; Debug.Assert(currentGroupBase != null); currentGroupingInfo = new GroupingInfo((ContentModelType)particleType, this.GetOccurence(currentGroupBase)); if (parentGroupInfo != null) { parentGroupInfo.AddChild(currentGroupingInfo); parentGroupInfo.HasChildGroups = true; currentGroupingInfo.IsNested = true; if (parentGroupInfo.IsRepeating) { currentGroupingInfo.IsRepeating = true; } if (currentGroupingInfo.IsRepeating) { parentGroupInfo.HasRepeatingGroups = true; } } else { typeInfo.AddMember(currentGroupingInfo); parentGroupInfo = currentGroupingInfo; } break; } case ParticleType.Element: { XmlSchemaElement elem = particle as XmlSchemaElement; ClrPropertyInfo propertyInfo = null; bool fromBaseType = false; if ((derivationMethod != XmlSchemaDerivationMethod.Extension ? false : typeInfo.IsDerived)) { if (baseParticle.ContainsElement(elem)) { fromBaseType = true; } else if ((typeInfo.InlineBaseType ? false : baseType.ContainsName(elem.QualifiedName))) { typeInfo.InlineBaseType = true; } } propertyInfo = this.BuildProperty(elem, fromBaseType); regEx.Append(propertyInfo.PropertyName); this.AppendOccurenceToRegex(propertyInfo, regEx); if (currentGroupingInfo != null) { this.BuildAnnotationInformation(propertyInfo, elem, currentGroupingInfo.ContentModelType == ContentModelType.Choice, currentGroupingInfo.IsNested); currentGroupingInfo.AddChild(propertyInfo); this.SetPropertyFlags(propertyInfo, currentGroupingInfo, elem.ElementSchemaType); } else { this.BuildAnnotationInformation(propertyInfo, elem, false, false); typeInfo.AddMember(propertyInfo); } break; } case ParticleType.Any: { regEx.Append("any"); XmlSchemaAny any = particle as XmlSchemaAny; if ((derivationMethod != XmlSchemaDerivationMethod.Extension ? false : typeInfo.IsDerived)) { if (baseParticle.ContainsWildCard(any)) { typeInfo.HasElementWildCard = true; } } ClrWildCardPropertyInfo wcPropertyInfo = this.BuildAnyProperty(any, !typeInfo.HasElementWildCard); if (currentGroupingInfo != null) { currentGroupingInfo.AddChild(wcPropertyInfo); } else { typeInfo.AddMember(wcPropertyInfo); } if (!typeInfo.HasElementWildCard) { typeInfo.HasElementWildCard = true; } break; } } } if ((currentGroupBase == null ? true : currentIndex >= currentGroupBase.Items.Count)) { if (currentGroupBase != null) { regEx.Append(")"); this.AppendOccurenceToRegex(currentGroupingInfo, regEx); } if (this.particleStack.Count <= 0) { break; } bool childGroupHasRecurringElements = currentGroupingInfo.HasRecurrentElements; bool childGroupHasRepeatingGroups = currentGroupingInfo.HasRepeatingGroups; XsdToTypesConverter.ParticleData particleData = this.particleStack.Pop(); currentGroupBase = particleData.currentGroupBase; currentGroupingInfo = particleData.currentGroupingInfo; currentGroupingInfo.HasRecurrentElements = childGroupHasRecurringElements; currentGroupingInfo.HasRepeatingGroups = childGroupHasRepeatingGroups; currentIndex = particleData.currentIndex; if (currentIndex >= currentGroupBase.Items.Count) { currentIndex++; } else { int num = currentIndex; currentIndex = num + 1; particle = (XmlSchemaParticle)currentGroupBase.Items[num]; regEx.Append((currentGroupingInfo.ContentModelType == ContentModelType.Choice ? "|" : ", ")); } } else { if (currentIndex > 0) { regEx.Append((currentGroupingInfo.ContentModelType == ContentModelType.Choice ? " | " : ", ")); } int num1 = currentIndex; currentIndex = num1 + 1; particle = (XmlSchemaParticle)currentGroupBase.Items[num1]; } } if (regEx.Length != 0) { typeInfo.ContentModelRegEx = regEx.ToString(); } }