递归搜索 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)。我想元素组也是一样。