递归搜索XmlSchemaDocument的元素部分

时间:2016-12-21 13:15:25

标签: c# loops xsd out-of-memory xmldocument

在下面的代码中,我在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);}
    }

让孩子们:

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中有一个循环时我才会遇到这个问题 - 如图所示: xsd example 有什么方法可以在找不到元素时停止迭代,但是有这样的循环吗?

1 个答案:

答案 0 :(得分:0)

您需要跟踪已搜索过的内容。 然后GetNextChildren可以检查它是否已经处理了该元素,它可以忽略它。从main函数调用它应传入一个新的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)。我认为元素组也是如此。