public ChildInfo Clone(string newName, bool isList) { var newChild = new ChildInfo(newName, m_type, isList); if (m_rules != null) { foreach (var rule in m_rules) { newChild.AddRule(rule); } } return(newChild); }
public void TestValidation() { DomNodeType type = new DomNodeType("child"); ChildInfo test = new ChildInfo("test", type); CollectionAssert.IsEmpty(test.Rules); var rule = new SimpleChildRule(); test.AddRule(rule); Utilities.TestSequenceEqual(test.Rules, rule); Assert.True(test.Validate(null, null)); Assert.True(rule.Validated); }
public TestDataValidator() { m_childType = new DomNodeType("child"); m_parentType = new DomNodeType("parent"); m_parentType.Define(new ExtensionInfo<ValidationContext>()); m_parentType.Define(new ExtensionInfo<DataValidator>()); m_childCountRule = new ChildCountRule(2, 3); m_childInfo = new ChildInfo("child", m_childType, true); m_parentType.Define(m_childInfo); m_childInfo.AddRule(m_childCountRule); m_parent = new DomNode(m_parentType); m_parent.InitializeExtensions(); m_validationContext = m_parent.As<ValidationContext>(); m_child1 = new DomNode(m_childType); m_child2 = new DomNode(m_childType); m_child3 = new DomNode(m_childType); m_child4 = new DomNode(m_childType); }
private void WalkParticle(XmlSchemaParticle particle, DomNodeType nodeType) { XmlSchemaElement element = particle as XmlSchemaElement; if (element != null) { XmlSchemaSimpleType simpleType = element.ElementSchemaType as XmlSchemaSimpleType; if (simpleType != null && element.MaxOccurs == 1) { XmlAttributeType attributeType = GetAttributeType(simpleType); string fieldName = GetFieldName(element.QualifiedName); XmlAttributeInfo attributeInfo = new XmlAttributeInfo(fieldName, attributeType); nodeType.Define(attributeInfo); m_annotations.Add(attributeInfo, GetAnnotation(element)); attributeInfo.IsElement = true; if (element.DefaultValue != null) { if (element.FixedValue != null) { throw new InvalidOperationException(string.Format("Schema element {0} cannot have both a default value and a fixed value", element.QualifiedName)); } attributeInfo.DefaultValue = attributeType.Convert(element.DefaultValue); } else if (element.FixedValue != null) { attributeInfo.DefaultValue = attributeType.Convert(element.FixedValue); } } else { DomNodeType childNodeType = null; if (simpleType != null) { bool firstTime; childNodeType = WrapSimpleType(simpleType, out firstTime); // The collada.xsd's ListOfUInts element breaks the generated Schema.cs file otherwise. if (firstTime) { // Add the value attribute XmlAttributeType valueAttributeType = GetAttributeType(simpleType); var valueAttributeInfo = new XmlAttributeInfo(string.Empty, valueAttributeType); childNodeType.Define(valueAttributeInfo); } } else { XmlSchemaComplexType complexType = element.ElementSchemaType as XmlSchemaComplexType; if (complexType != null) { childNodeType = GetNodeType(complexType, element); } } if (childNodeType != null) { int minOccurs = (int)Math.Min(element.MinOccurs, Int32.MaxValue); int maxOccurs = (int)Math.Min(element.MaxOccurs, Int32.MaxValue); if (particle.Parent is XmlSchemaChoice) { var parent = (XmlSchemaChoice)particle.Parent; if (parent.MinOccurs != 1) { minOccurs = (int)Math.Min(Math.Max(element.MinOccurs, parent.MinOccurs), Int32.MaxValue); } if (parent.MaxOccurs != 1) { maxOccurs = (int)Math.Min(Math.Max(element.MaxOccurs, parent.MaxOccurs), Int32.MaxValue); } } else if (particle.Parent is XmlSchemaSequence) { var parent = (XmlSchemaSequence)particle.Parent; if (parent.MinOccurs != 1) { minOccurs = (int)Math.Min(Math.Max(element.MinOccurs, parent.MinOccurs), Int32.MaxValue); } if (parent.MaxOccurs != 1) { maxOccurs = (int)Math.Min(Math.Max(element.MaxOccurs, parent.MaxOccurs), Int32.MaxValue); } } ChildInfo childInfo = new ChildInfo(GetFieldName(element.QualifiedName), childNodeType, maxOccurs > 1); if ((minOccurs > 0 || maxOccurs < Int32.MaxValue) && minOccurs <= maxOccurs) { childInfo.AddRule(new ChildCountRule(minOccurs, maxOccurs)); } // Check for substitution groups if (!element.RefName.IsEmpty) { m_refElements.Add(childInfo, element.RefName); } nodeType.Define(childInfo); m_annotations.Add(childInfo, GetAnnotation(element)); } } } else { XmlSchemaGroupBase grp = particle as XmlSchemaSequence; if (grp == null) { grp = particle as XmlSchemaChoice; } if (grp == null) { grp = particle as XmlSchemaAll; } if (grp != null) { foreach (XmlSchemaParticle subParticle in grp.Items) { WalkParticle(subParticle, nodeType); } } } }
/// <summary> /// Converts schemas to NodeTypes, AttributeTypes, and root elements</summary> /// <param name="schemaSet">Schemas to register</param> public void Load(XmlSchemaSet schemaSet) { if (!schemaSet.IsCompiled) { schemaSet.Compile(); } System.Collections.ICollection schemas = schemaSet.Schemas(); foreach (XmlSchema schema in schemas) { string targetNamespace = schema.TargetNamespace; if (string.IsNullOrEmpty(targetNamespace)) { throw new InvalidOperationException("Schema has no target namespace"); } // only register the schema once; targetNamespaces must be globally unique if (!m_typeCollections.ContainsKey(targetNamespace)) { XmlQualifiedName[] nameSpaces = schema.Namespaces.ToArray(); XmlSchemaTypeCollection typeCollection = new XmlSchemaTypeCollection(nameSpaces, targetNamespace, this); m_typeCollections.Add(targetNamespace, typeCollection); } } try { m_annotations = new Dictionary <NamedMetadata, IList <XmlNode> >(); m_typeNameSet = new HashSet <string>(); m_localElementSet = new Dictionary <XmlSchemaElement, XmlQualifiedName>(); // collect global element & type names so we do not generate local type names that collides with those foreach (XmlSchemaElement element in schemaSet.GlobalElements.Values) { m_typeNameSet.Add(element.QualifiedName.Name); } foreach (XmlSchemaType type in schemaSet.GlobalTypes.Values) { if (type is XmlSchemaComplexType) { m_typeNameSet.Add(type.Name); } } var substitutionGroups = new Multimap <XmlQualifiedName, ChildInfo>(); // Get types reachable from global elements foreach (XmlSchemaElement element in schemaSet.GlobalElements.Values) { XmlSchemaType type = element.ElementSchemaType; DomNodeType nodeType = GetNodeType(type, element); ChildInfo childInfo = new ChildInfo(GetFieldName(element.QualifiedName), nodeType); m_annotations.Add(childInfo, GetAnnotation(element)); // Keep list of substitution groups if (!element.SubstitutionGroup.IsEmpty) { substitutionGroups.Add(element.SubstitutionGroup, childInfo); } // only add root elements once; root element names must be globally unique string name = element.QualifiedName.ToString(); if (!m_rootElements.ContainsKey(name)) { m_rootElements[name] = childInfo; } } // Get global complex type definitions foreach (XmlSchemaType type in schemaSet.GlobalTypes.Values) { if (type is XmlSchemaComplexType) { GetNodeType(type, null); } } // Parse substitution groups foreach (var kvp in m_refElements) { XmlQualifiedName refName = kvp.Value; ChildInfo childInfo = kvp.Key; var substitutions = CreateSubstitutions(substitutionGroups, refName).ToArray(); if (substitutions.Length > 0) { childInfo.AddRule(new SubstitutionGroupChildRule(substitutions)); } } // Preserve annotation from any types that were redefined foreach (XmlSchema schema in schemas) { foreach (XmlSchemaObject schemaInclude in schema.Includes) { XmlSchemaRedefine schemaRedefine = schemaInclude as XmlSchemaRedefine; if (schemaRedefine != null) { MergeRedefinedTypeAnnotations(schemaRedefine); } } } // Sort DomNodeTypes, so that base types are always before derived types // Bucket sort by depth in the inheritance tree // Time: O(n * d) with n = number of DomNodeTypes, d = depth of inheritance tree var sortedTypes = new List <List <DomNodeType> >(); foreach (DomNodeType type in GetNodeTypes()) { // Get inheritance depth of current type int depth = 0; DomNodeType curType = type; while (curType != null && curType != DomNodeType.BaseOfAllTypes) { depth++; curType = curType.BaseType; } // We don't need to merge annotations for BaseAllTypes (level 0) // and its immediate child types (level 1) int idx = depth - 2; if (idx >= 0) { while (sortedTypes.Count <= idx) { sortedTypes.Add(new List <DomNodeType>()); } sortedTypes[idx].Add(type); } } // Merge type annotations with base type annotations foreach (var list in sortedTypes) { foreach (DomNodeType type in list) { if (type.BaseType != null && type.BaseType != DomNodeType.BaseOfAllTypes) { IList <XmlNode> baseAnnotations; IList <XmlNode> annotations; if (m_annotations.TryGetValue(type.BaseType, out baseAnnotations) && m_annotations.TryGetValue(type, out annotations)) { // Call protected virtual merge method - allowing clients to define if & how annotations are being merged IEnumerable <XmlNode> mergedAnnotations = MergeInheritedTypeAnnotations(baseAnnotations, annotations); m_annotations[type] = mergedAnnotations as IList <XmlNode> ?? mergedAnnotations.ToList(); } } } } // Call before the DomNodeTypes are frozen. Note that iterating through Attributes or // calling 'SetIdAttribute' freezes the attributes on DomNodeType. OnSchemaSetLoaded(schemaSet); // Set up ID attributes where xs:ID has been specified foreach (DomNodeType nodeType in GetNodeTypes()) { foreach (var attribute in nodeType.Attributes.OfType <XmlAttributeInfo>()) { if (((XmlAttributeType)attribute.Type).XmlTypeCode == XmlTypeCode.Id) { nodeType.SetIdAttribute(attribute.Name); } } } // Attach annotation as metadata to the associated type so that other classes can find it foreach (var keyValuePair in m_annotations) { if (keyValuePair.Value.Count > 0) { keyValuePair.Key.SetTag <IEnumerable <XmlNode> >(keyValuePair.Value); } } ParseAnnotations(schemaSet, m_annotations); // Call this after the ID attributes have been set and after the DomNodeTypes are frozen. OnDomNodeTypesFrozen(schemaSet); } finally { m_annotations = null; m_typeNameSet = null; m_localElementSet = null; } }
private void WalkParticle(XmlSchemaParticle particle, DomNodeType nodeType) { XmlSchemaElement element = particle as XmlSchemaElement; if (element != null) { XmlSchemaSimpleType simpleType = element.ElementSchemaType as XmlSchemaSimpleType; if (simpleType != null && element.MaxOccurs == 1) { XmlAttributeType attributeType = GetAttributeType(simpleType); string fieldName = GetFieldName(element.QualifiedName); XmlAttributeInfo attributeInfo = new XmlAttributeInfo(fieldName, attributeType); nodeType.Define(attributeInfo); m_annotations.Add(attributeInfo, GetAnnotation(element)); attributeInfo.IsElement = true; if (element.DefaultValue != null) { if (element.FixedValue != null) throw new InvalidOperationException(string.Format("Schema element {0} cannot have both a default value and a fixed value", element.QualifiedName)); attributeInfo.DefaultValue = attributeType.Convert(element.DefaultValue); } else if (element.FixedValue != null) { attributeInfo.DefaultValue = attributeType.Convert(element.FixedValue); } } else { DomNodeType childNodeType = null; if (simpleType != null) { childNodeType = WrapSimpleType(simpleType); // Add the value attribute XmlAttributeType valueAttributeType = GetAttributeType(simpleType); var valueAttributeInfo = new XmlAttributeInfo(string.Empty, valueAttributeType); childNodeType.Define(valueAttributeInfo); } else { XmlSchemaComplexType complexType = element.ElementSchemaType as XmlSchemaComplexType; if (complexType != null) childNodeType = GetNodeType(complexType, element); } if (childNodeType != null) { int minOccurs = (int)Math.Min(element.MinOccurs, Int32.MaxValue); int maxOccurs = (int)Math.Min(element.MaxOccurs, Int32.MaxValue); // If <xs:choice> is within a <xs:sequence>, choose the most relaxed constraints. if (particle.Parent is XmlSchemaChoice && particle.Parent.Parent is XmlSchemaSequence) { XmlSchemaChoice parent = (XmlSchemaChoice)particle.Parent; int parentMinOccurs = (int)Math.Min(parent.MinOccurs, Int32.MaxValue); int parentMaxOccurs = (int)Math.Min(parent.MaxOccurs, Int32.MaxValue); minOccurs = Math.Min(parentMinOccurs, minOccurs); maxOccurs = Math.Max(parentMaxOccurs, maxOccurs); } ChildInfo childInfo = new ChildInfo(GetFieldName(element.QualifiedName), childNodeType, maxOccurs > 1); if (minOccurs > 0 || maxOccurs < Int32.MaxValue) { childInfo.AddRule(new ChildCountRule(minOccurs, maxOccurs)); } // Check for substitution groups if (!element.RefName.IsEmpty) { m_refElements.Add(childInfo, element.RefName); } nodeType.Define(childInfo); m_annotations.Add(childInfo, GetAnnotation(element)); } } } else { // if sequence, continue collecting elements XmlSchemaSequence sequence = particle as XmlSchemaSequence; if (sequence != null) { foreach (XmlSchemaParticle subParticle in sequence.Items) WalkParticle(subParticle, nodeType); } else { XmlSchemaChoice choice = particle as XmlSchemaChoice; if (choice != null) { // for now, treat choice as if it were a sequence foreach (XmlSchemaParticle subParticle in choice.Items) WalkParticle(subParticle, nodeType); } } } }
/// <summary> /// Converts schemas to NodeTypes, AttributeTypes, and root elements</summary> /// <param name="schemaSet">Schemas to register</param> public void Load(XmlSchemaSet schemaSet) { if (!schemaSet.IsCompiled) schemaSet.Compile(); System.Collections.ICollection schemas = schemaSet.Schemas(); foreach (XmlSchema schema in schemas) { string targetNamespace = schema.TargetNamespace; if (string.IsNullOrEmpty(targetNamespace)) throw new InvalidOperationException("Schema has no target namespace"); // only register the schema once; targetNamespaces must be globally unique if (!m_typeCollections.ContainsKey(targetNamespace)) { XmlQualifiedName[] nameSpaces = schema.Namespaces.ToArray(); XmlSchemaTypeCollection typeCollection = new XmlSchemaTypeCollection(nameSpaces, targetNamespace, this); m_typeCollections.Add(targetNamespace, typeCollection); } } try { m_annotations = new Dictionary<NamedMetadata, IList<XmlNode>>(); m_typeNameSet = new HashSet<string>(); m_localElementSet = new Dictionary<XmlSchemaElement, XmlQualifiedName>(); // collect global element & type names so we do not generate local type names that collides with those foreach (XmlSchemaElement element in schemaSet.GlobalElements.Values) m_typeNameSet.Add(element.QualifiedName.Name); foreach (XmlSchemaType type in schemaSet.GlobalTypes.Values) { if (type is XmlSchemaComplexType) { m_typeNameSet.Add(type.Name); } } var substitutionGroups = new Multimap<XmlQualifiedName, ChildInfo>(); // Get types reachable from global elements foreach (XmlSchemaElement element in schemaSet.GlobalElements.Values) { XmlSchemaType type = element.ElementSchemaType; DomNodeType nodeType = GetNodeType(type, element); ChildInfo childInfo = new ChildInfo(GetFieldName(element.QualifiedName), nodeType); m_annotations.Add(childInfo, GetAnnotation(element)); // Keep list of substitution groups if (!element.SubstitutionGroup.IsEmpty) { substitutionGroups.Add(element.SubstitutionGroup, childInfo); } // only add root elements once; root element names must be globally unique string name = element.QualifiedName.ToString(); if (!m_rootElements.ContainsKey(name)) { m_rootElements[name] = childInfo; } } // Get global complex type definitions foreach (XmlSchemaType type in schemaSet.GlobalTypes.Values) { if (type is XmlSchemaComplexType) { GetNodeType(type, null); } } // Parse substitution groups foreach (var kvp in m_refElements) { XmlQualifiedName refName = kvp.Value; ChildInfo childInfo = kvp.Key; var substitutions = substitutionGroups.Find(refName).ToArray(); if (substitutions.Length > 0) { childInfo.AddRule(new SubstitutionGroupChildRule(substitutions)); } } // Preserve annotation from any types that were redefined foreach (XmlSchema schema in schemas) { foreach (XmlSchemaObject schemaInclude in schema.Includes) { XmlSchemaRedefine schemaRedefine = schemaInclude as XmlSchemaRedefine; if (schemaRedefine != null) MergeRedefinedTypeAnnotations(schemaRedefine); } } // Sort DomNodeTypes, so that base types are always before derived types // Bucket sort by depth in the inheritance tree // Time: O(n * d) with n = number of DomNodeTypes, d = depth of inheritance tree var sortedTypes = new List<List<DomNodeType>>(); foreach (DomNodeType type in GetNodeTypes()) { // Get inheritance depth of current type int depth = 0; DomNodeType curType = type; while (curType != null && curType != DomNodeType.BaseOfAllTypes) { depth++; curType = curType.BaseType; } // We don't need to merge annotations for BaseAllTypes (level 0) // and its immediate child types (level 1) int idx = depth - 2; if (idx >= 0) { while (sortedTypes.Count <= idx) sortedTypes.Add(new List<DomNodeType>()); sortedTypes[idx].Add(type); } } // Merge type annotations with base type annotations foreach (var list in sortedTypes) { foreach (DomNodeType type in list) { if (type.BaseType != null && type.BaseType != DomNodeType.BaseOfAllTypes) { IList<XmlNode> baseAnnotations; IList<XmlNode> annotations; if (m_annotations.TryGetValue(type.BaseType, out baseAnnotations) && m_annotations.TryGetValue(type, out annotations)) { // Call protected virtual merge method - allowing clients to define if & how annotations are being merged IEnumerable<XmlNode> mergedAnnotations = MergeInheritedTypeAnnotations(baseAnnotations, annotations); m_annotations[type] = mergedAnnotations as IList<XmlNode> ?? mergedAnnotations.ToList(); } } } } // Call before the DomNodeTypes are frozen. Note that iterating through Attributes or // calling 'SetIdAttribute' freezes the attributes on DomNodeType. OnSchemaSetLoaded(schemaSet); // Set up ID attributes where xs:ID has been specified foreach (DomNodeType nodeType in GetNodeTypes()) { foreach (var attribute in nodeType.Attributes.OfType<XmlAttributeInfo>()) { if (((XmlAttributeType)attribute.Type).XmlTypeCode == XmlTypeCode.Id) nodeType.SetIdAttribute(attribute.Name); } } // Attach annotation as metadata to the associated type so that other classes can find it foreach (var keyValuePair in m_annotations) { if (keyValuePair.Value.Count > 0) { keyValuePair.Key.SetTag<IEnumerable<XmlNode>>(keyValuePair.Value); } } ParseAnnotations(schemaSet, m_annotations); // Call this after the ID attributes have been set and after the DomNodeTypes are frozen. OnDomNodeTypesFrozen(schemaSet); } finally { m_annotations = null; m_typeNameSet = null; m_localElementSet = null; } }
private void WalkParticle(XmlSchemaParticle particle, DomNodeType nodeType) { XmlSchemaElement element = particle as XmlSchemaElement; if (element != null) { XmlSchemaSimpleType simpleType = element.ElementSchemaType as XmlSchemaSimpleType; if (simpleType != null && element.MaxOccurs == 1) { XmlAttributeType attributeType = GetAttributeType(simpleType); string fieldName = GetFieldName(element.QualifiedName); XmlAttributeInfo attributeInfo = new XmlAttributeInfo(fieldName, attributeType); nodeType.Define(attributeInfo); m_annotations.Add(attributeInfo, GetAnnotation(element)); attributeInfo.IsElement = true; if (element.DefaultValue != null) { if (element.FixedValue != null) { throw new InvalidOperationException(string.Format("Schema element {0} cannot have both a default value and a fixed value", element.QualifiedName)); } attributeInfo.DefaultValue = attributeType.Convert(element.DefaultValue); } else if (element.FixedValue != null) { attributeInfo.DefaultValue = attributeType.Convert(element.FixedValue); } } else { DomNodeType childNodeType = null; if (simpleType != null) { childNodeType = WrapSimpleType(simpleType); // Add the value attribute XmlAttributeType valueAttributeType = GetAttributeType(simpleType); var valueAttributeInfo = new XmlAttributeInfo(string.Empty, valueAttributeType); childNodeType.Define(valueAttributeInfo); } else { XmlSchemaComplexType complexType = element.ElementSchemaType as XmlSchemaComplexType; if (complexType != null) { childNodeType = GetNodeType(complexType, element); } } if (childNodeType != null) { int minOccurs = (int)Math.Min(element.MinOccurs, Int32.MaxValue); int maxOccurs = (int)Math.Min(element.MaxOccurs, Int32.MaxValue); // If <xs:choice> is within a <xs:sequence>, choose the most relaxed constraints. if (particle.Parent is XmlSchemaChoice && particle.Parent.Parent is XmlSchemaSequence) { XmlSchemaChoice parent = (XmlSchemaChoice)particle.Parent; int parentMinOccurs = (int)Math.Min(parent.MinOccurs, Int32.MaxValue); int parentMaxOccurs = (int)Math.Min(parent.MaxOccurs, Int32.MaxValue); minOccurs = Math.Min(parentMinOccurs, minOccurs); maxOccurs = Math.Max(parentMaxOccurs, maxOccurs); } ChildInfo childInfo = new ChildInfo(GetFieldName(element.QualifiedName), childNodeType, maxOccurs > 1); if (minOccurs > 0 || maxOccurs < Int32.MaxValue) { childInfo.AddRule(new ChildCountRule(minOccurs, maxOccurs)); } // Check for substitution groups if (!element.RefName.IsEmpty) { m_refElements.Add(childInfo, element.RefName); } nodeType.Define(childInfo); m_annotations.Add(childInfo, GetAnnotation(element)); } } } else { // if sequence, continue collecting elements XmlSchemaSequence sequence = particle as XmlSchemaSequence; if (sequence != null) { foreach (XmlSchemaParticle subParticle in sequence.Items) { WalkParticle(subParticle, nodeType); } } else { XmlSchemaChoice choice = particle as XmlSchemaChoice; if (choice != null) { // for now, treat choice as if it were a sequence foreach (XmlSchemaParticle subParticle in choice.Items) { WalkParticle(subParticle, nodeType); } } } } }
private void WalkParticle(XmlSchemaParticle particle, DomNodeType nodeType) { XmlSchemaElement element = particle as XmlSchemaElement; if (element != null) { XmlSchemaSimpleType simpleType = element.ElementSchemaType as XmlSchemaSimpleType; if (simpleType != null && element.MaxOccurs == 1) { bool forceSerialize = element.MinOccurs == 1; XmlAttributeType attributeType = GetAttributeType(simpleType); string fieldName = GetFieldName(element.QualifiedName); XmlAttributeInfo attributeInfo = new XmlAttributeInfo(fieldName, attributeType, forceSerialize); nodeType.Define(attributeInfo); m_annotations.Add(attributeInfo, GetAnnotation(element)); attributeInfo.IsElement = true; if (element.DefaultValue != null) { if (element.FixedValue != null) throw new InvalidOperationException(string.Format("Schema element {0} cannot have both a default value and a fixed value", element.QualifiedName)); attributeInfo.DefaultValue = attributeType.Convert(element.DefaultValue); } else if (element.FixedValue != null) { attributeInfo.DefaultValue = attributeType.Convert(element.FixedValue); } } else { DomNodeType childNodeType = null; if (simpleType != null) { bool firstTime; childNodeType = WrapSimpleType(simpleType, out firstTime); // The collada.xsd's ListOfUInts element breaks the generated Schema.cs file otherwise. if (firstTime) { // Add the value attribute XmlAttributeType valueAttributeType = GetAttributeType(simpleType); var valueAttributeInfo = new XmlAttributeInfo(string.Empty, valueAttributeType); childNodeType.Define(valueAttributeInfo); } } else { XmlSchemaComplexType complexType = element.ElementSchemaType as XmlSchemaComplexType; if (complexType != null) childNodeType = GetNodeType(complexType, element); } if (childNodeType != null) { int minOccurs = (int)Math.Min(element.MinOccurs, Int32.MaxValue); int maxOccurs = (int)Math.Min(element.MaxOccurs, Int32.MaxValue); if (particle.Parent is XmlSchemaChoice) { var parent = (XmlSchemaChoice)particle.Parent; if (parent.MinOccurs != 1) minOccurs = (int)Math.Min(Math.Max(element.MinOccurs, parent.MinOccurs), Int32.MaxValue); if (parent.MaxOccurs != 1) maxOccurs = (int)Math.Min(Math.Max(element.MaxOccurs, parent.MaxOccurs), Int32.MaxValue); } else if (particle.Parent is XmlSchemaSequence) { var parent = (XmlSchemaSequence)particle.Parent; if (parent.MinOccurs != 1) minOccurs = (int)Math.Min(Math.Max(element.MinOccurs, parent.MinOccurs), Int32.MaxValue); if (parent.MaxOccurs != 1) maxOccurs = (int)Math.Min(Math.Max(element.MaxOccurs, parent.MaxOccurs), Int32.MaxValue); } ChildInfo childInfo = new ChildInfo(GetFieldName(element.QualifiedName), childNodeType, maxOccurs > 1); if ( (minOccurs > 0 || maxOccurs < Int32.MaxValue) && minOccurs <= maxOccurs) { childInfo.AddRule(new ChildCountRule(minOccurs, maxOccurs)); } // Check for substitution groups if (!element.RefName.IsEmpty) { m_refElements.Add(childInfo, element.RefName); } nodeType.Define(childInfo); m_annotations.Add(childInfo, GetAnnotation(element)); } } } else { // handle xs:all, xs:sequence and xs:choice XmlSchemaGroupBase grp = particle as XmlSchemaSequence; if(grp == null) grp = particle as XmlSchemaChoice; if (grp == null) grp = particle as XmlSchemaAll; if (grp != null) { foreach (XmlSchemaParticle subParticle in grp.Items) WalkParticle(subParticle, nodeType); } } }