XmlNode检查是否存在chidnode列表

时间:2016-12-16 18:43:31

标签: c# xml

我正在尝试创建一个带有XmlNode的函数,并检查每个后续子节点是否存在并且遇到问题。

该函数应具有类似于

的签名
private string GetValueForNodeIfExists(XmlNode node, List<string> childNodes){...}

说明我想要完成的内容的示例: 我需要知道节点的孩子(可能还有孩子的孩子)是否存在。 如果我有一个节点,其中有一个名为“child”的子节点,而“child”节点有一个名为“grandchild”的节点,并且该孙子节点有一个名为“greatGrandchild”的节点,那么我想检查每个序列是否为null或者不,所以检查以下内容:

node['child'] != null
node['child']['grandchild'] != null
node['child']['grandchild']['greatGrandchild'] != null

我正在检查的节点名称作为List<string>传递给函数,其中索引与我正在检查的节点的深度相关。例如,在上面的示例中,我传入的列表是List<string> checkedasd = new List<String> {"child", "grandchild", "greatGrandchild" };

我不确定如何以编程方式附加每个['nodeName']表达式然后执行表达式。如果我能弄明白,我的策略是将所有内容都放在try块中,如果我发现了Null异常,那么我就知道节点不存在。

感谢所有帮助

3 个答案:

答案 0 :(得分:4)

我会使用Linq2Xml和XPATH

var childNodes = new List<string>() { "child", "grandchild", "greatGrandchild" };
var xpath = "//" + string.Join("/", childNodes);

var xDoc = XDocument.Load(filename);
var xElem = xDoc.XPathSelectElement(xpath);

if(xElem!=null) //<--- No need for try- catch block
    Console.WriteLine(xElem.Value);

PS:我使用以下xml

测试了上面代码
<root>
    <child>
        <grandchild>
            <greatGrandchild>
                a
            </greatGrandchild>
        </grandchild>
    </child>
</root>

答案 1 :(得分:1)

如果您未与XmlDocument结婚并且可以使用Linq2Xml(或想要学习新内容),则另一种选择可能是:

DotNetFiddle

using System;
using System.Xml;
using System.Linq;
using System.Xml.Linq;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        //var xDoc = XDocument.Load(filename);
        var XDoc = XDocument.Parse(@"<root><a><b><c>value</c></b></a><b><c>no</c></b><a><c>no</c></a></root>");
        Console.WriteLine("Params a b c ");
        foreach(var nodeValue in XDoc.Root.GetValueForNodeIfExists("a", "b", "c"))
        {
            Console.WriteLine(nodeValue);
        }

        Console.WriteLine("List a b c ");
        foreach(var nodeValue in XDoc.Root.GetValueForNodeIfExists("a", "b", "c"))
        {
            Console.WriteLine(nodeValue);
        }
    }
}   


internal static class XElementExtensions
{
    public static IEnumerable<string> GetValueForNodeIfExists(this XElement node, params string[] childNodesNames)
    {
        return GetValueForNodeIfExists(node, childNodesNames.ToList());
    }

    public static IEnumerable<string> GetValueForNodeIfExists(this XElement node, IEnumerable<string> childNodesNames)
    {
        IEnumerable<XElement> nodes = new List<XElement> { node };

        foreach(var name in childNodesNames)
        {
            nodes = FilterChildrenByName(nodes, name);
        }

        var result = nodes.Select(n => n.Value);

        return result;
    }

    private static IEnumerable<XElement> FilterChildrenByName(IEnumerable<XElement> nodes, string filterName)
    {
        var result = nodes
            .SelectMany(n => n.Elements(filterName));

        Console.WriteLine("Filtering by {0}, found {1} elements", filterName, result.Count());

        return result;          
    }
}

结果:

  

Params a b c

     

按a过滤,找到2个元素

     

按b过滤,找到1个元素

     

按c过滤,找到1个元素

     

     

列出b c

     

按a过滤,找到2个元素

     

按b过滤,找到1个元素

     

按c过滤,找到1个元素

     

答案 2 :(得分:0)

您需要做的就是使用XPath:

private string GetValueForNodeIfExists(XmlNode node, List<string> childNodes)
{
    var xpath = string.Join("/", childNodes.ToArray());

    var foundNode = node.SelectSingleNode(xpath);

    return foundNode != null ? foundNode.InnerText : null;
}

您还可以扩展已有的内容并循环显示值,直到获得空值或到达结尾:

private string GetValueForNodeIfExists(XmlNode node, List<string> childNodes)
{
    foreach (var nodeName in childNodes)
    {
         if (node != null)
         {
             node = node[nodeName];
         }
    }

    return node != null ? node.InnerText : null;
}