递归搜索 XmlSchemaDocument 的元素部分
Recursive search for element part of XmlSchemaDocument
在下面的代码中,我在 XmlSchemaDocument 中搜索元素。如果元素是 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);}
}
获取 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); }
}
在 GetChildren() 中 - 我只是检查元素的类型(序列、选择元素),如果它是一个元素,我将它添加到 _childrenList。
但是,如果找不到该元素,我就会陷入循环,最终 运行 内存不足(我使用的 .xsd 文件非常大)。
我注意到只有在 .xsd 中有一个循环时我才会遇到这个问题 - 如图所示:
没有找到元素但是有这样的循环,有没有办法停止迭代?
您需要跟踪您已经搜索过的内容。
然后 GetNextChildren 可以检查它是否已经处理了该元素,它可以忽略它。从主函数调用它应该传入一个新的 HashSet
GetNextChildren(new HashSet<XmlSchemaElement>(), ....);
你的代码到处都是,所以我刚刚完成了防止无限递归的部分。
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); }
}
您还应注意,架构也可以在一个循环中相互包含(a.xsd 包含 b.xsd,b.xsd 包含 a.xsd)。我想元素组也是一样。
在下面的代码中,我在 XmlSchemaDocument 中搜索元素。如果元素是 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);}
}
获取 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); }
}
在 GetChildren() 中 - 我只是检查元素的类型(序列、选择元素),如果它是一个元素,我将它添加到 _childrenList。
但是,如果找不到该元素,我就会陷入循环,最终 运行 内存不足(我使用的 .xsd 文件非常大)。
我注意到只有在 .xsd 中有一个循环时我才会遇到这个问题 - 如图所示:
您需要跟踪您已经搜索过的内容。 然后 GetNextChildren 可以检查它是否已经处理了该元素,它可以忽略它。从主函数调用它应该传入一个新的 HashSet
GetNextChildren(new HashSet<XmlSchemaElement>(), ....);
你的代码到处都是,所以我刚刚完成了防止无限递归的部分。
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); }
}
您还应注意,架构也可以在一个循环中相互包含(a.xsd 包含 b.xsd,b.xsd 包含 a.xsd)。我想元素组也是一样。