如何重写导航节点列表的代码

时间:2010-12-06 14:21:42

标签: c# refactoring

我刚刚写了一些代码,正如我写的那样,我认为这将是一个很好的搜索特定节点的通用方法。当我完成后,我实际上意识到这是一团糟:D

public String sqlReading(String fileName, String path, String nodeId )
{
    XmlDocument doc = new XmlDocument();
    doc.Load(fileName);

    XmlNodeList names = doc.SelectNodes(path);
    foreach (XmlNode xmlDocSearchTerm in names)
    {
        //if the attribute of the node i start at is the same as where i am now
        if (xmlDocSearchTerm.Attributes.Item(0).Value.ToString().Equals(nodeId))
        {
            //get a list of all of its child nodes
            XmlNodeList childNodes = xmlDocSearchTerm.ChildNodes;

            foreach (XmlNode node in childNodes)
            {
                //if there is a node in here called gui display, go inside
                if (node.Name.Equals("GUIDisplay"))
                {
                    XmlNodeList list = node.ChildNodes;
                    //find the sqlsearchstring tag inside of here
                    foreach (XmlNode finalNode in list)
                    {
                        if (finalNode.Name.Equals("sqlSearchString"))
                        {
                            return node.InnerText;
                        }
                    }
                }
            }
        }
    }
    return "";
}

我打算做的是基于路径 - 我会开始并检查该元素是否具有我正在寻找的ID,如果它确实那么我想进入那里并且不会停止直到我到达sqlsearchstring标签被深埋两层。我已经设法了,但问题是,现在我似乎已经几乎硬编码了一个反向循环的标记路径。我怎么能改变我的代码来阻止我这样做呢?

它来自第二个出错的地方。

由于

3 个答案:

答案 0 :(得分:1)

我不确定这是否完全正确(因为我没有XML文档可以尝试使用,但类似的东西应该可以使用

var innerTexts = XDocument.Load(fileName)
    .Elements(path)
    .Where(n => n.Attributes().ElementAt(0).Value == nodeId)
    .SelectMany(n => n.Elements())
    .Where(n => n.Name == "GUIDisplay")
    .SelectMany(n => n.Elements())
    .Where(n => n.Name == "sqlSearchString")
    .Select(n => n.ToString());

答案 1 :(得分:1)

没有测试过,但我相信这样的东西可以使用xpath。但是我不确定属性的名称,还是它始终是第一个属性?

public String sqlReading(String fileName, String path, String nodeId)
{
    XmlDocument doc = new XmlDocument();
    doc.Load(fileName);

    XmlNode foundNode = doc.SelectNodes(path).SelectSingleNode("*[@id='" + nodeId + "']/GUIDisplay/sqlSearchString");
    if (foundNode != null)
        return foundNode.InnerText;
    return string.Empty;

}

答案 2 :(得分:0)

我会说递归是一个安全的赌注(用于迭代嵌套的子节点)虽然,从我收集的结构来看,结构保持不变。考虑到这一点,为什么不使用[XmlDocumentObj].SelectSingleNode("/[nodeId='"+nodeId+"']")(或一些传真)呢?这可以按属性名进行搜索,除非XML结构总是被更改,并且你永远不会有常量标记(在这种情况下,XPath可能是一个好主意)。