XmlNode检查是否存在chidnodes列表
我想做一个函数,将采取一个XmlNode,并检查是否每个后续的孩子存在,我有问题。XmlNode检查是否存在chidnodes列表
的功能应该有类似
private string GetValueForNodeIfExists(XmlNode node, List<string> childNodes){...}
一个例子说明我想完成什么签名: 我需要知道,如果一个节点的孩子(也可能是一个孩子的孩子)存在。 如果我有一个节点有一个名为“child”的子节点,并且“child”节点有一个名为“grandchild”的节点,并且该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块中,如果我发现了一个空异常,那么我会知道该节点不存在。
所有帮助表示赞赏
所有您需要do是使用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;
}
我会用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>
如果你没有结婚到XmlDocument的,并且可以使用Linq2Xml(或者想学习新的东西),另一种方法是:
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 ABC
过滤由,发现2个元素
过滤用b,发现1个元素
过滤通过C,发现1个元素
值
列表abc
通过a筛选,找到2个元素
过滤用b,发现1个元素
过滤通过C,发现1个元素
值
是否每个节点必须直接后代? –
如果您发现与您的模式匹配的多个结果会发生什么('IEnumerable'?) –