In the code below, I am searching for an element in an XmlSchemaDocument. The iteration works just fine if the element is part of the XmlSchemaDocument.
public void FindSchemaElement(string elementName, string dataType, List<XmlSchemaElement> allChildren, string parentName)
{
try
{
List<XmlSchemaElement> temp = new List<XmlSchemaElement>();
temp.AddRange(allChildren);
foreach (XmlSchemaElement e in allChildren)
{
if (e.Name != elementName && e.RefName.Name != elementName &&
(dataType == "" || e.SchemaTypeName.Name != dataType)) continue;
if (e.Parent == null || e.Parent is XmlSchema)
{
ElementToBeFound = e;
return;
}
var parent = e.Parent;
while (parent != null && parent.GetType() != typeof(XmlSchemaElement))
parent = parent.Parent;
if (parent != null && ((XmlSchemaElement) parent).Name == parentName)
{
ElementToBeFound = e;
return;
}
if (parent == null || parent.GetType() == typeof(XmlSchema)) ElementToBeFound = e;
}
if (ElementToBeFound != null) return;
_childrenList.Clear();
if (temp.Count > 0)
GetNextChildren(temp, dataType, elementName, parentName);
}
catch(Exception exception){Debug.WriteLine("FindSchemaElement: "+exception.Message);}
}
Getting the children:
private void GetNextChildren(List<XmlSchemaElement> allChildren, string dataType, string elementName, string parentName = "")
{
try
{
foreach (XmlSchemaElement e in allChildren)
GetChildren(e);
if (parentName != string.Empty)
FindSchemaElement(elementName, dataType, _childrenList, parentName);
else
FindSubsGroups(elementName, dataType, _childrenList);
}
catch (Exception ex)
{ Debug.WriteLine("GetNextChildren: " + ex.Message); }
}
In GetChildren() - I am just checking the type of the element (sequence, choice element) and if it is an element, I am adding it to the _childrenList.
However, if the element cannot be found, I get stuck in a loop and I eventually run out of memory (the .xsd files that I am using are quite large).
I noticed that I have this issue only when, in the .xsd, there is a loop - as seen in the picture:
Is there any way to stop the iteration when the element has not been found but there is such a loop?
You need to keep track of what you've already searched. Then GetNextChildren can check and if its already processed that element it can ignore it. The call to it from your main function should pass in a new HashSet
GetNextChildren(new HashSet<XmlSchemaElement>(), ....);
Your codes a bit all over the place so I've just done the bit that prevents infinite recursion.
private void GetNextChildren(HashSet<XmlSchemaElement> searchedElements, List<XmlSchemaElement> allChildren, string dataType, string elementName, string parentName = "")
{
try
{
foreach (XmlSchemaElement e in allChildren)
{
if (searchedElements.Contains(e) == false)
{
searchedElements.Add(e);
// Search for it
// GetNextChildren(searchedElements, ....);
}
}
}
catch (Exception ex)
{ Debug.WriteLine("GetNextChildren: " + ex.Message); }
}
You should also note that schemas can include each other in a circular was as well (a.xsd includes b.xsd and b.xsd includes a.xsd). I think the same is also true for element group.