在XML文件中测试XPath的最佳方法是什么?

时间:2008-10-28 22:09:20

标签: c# xml

最近我一直在使用XPathDocument和XNavigator来解析给定XPath和属性的XML文件。当我事先知道XPath是什么时,它工作得非常好。

有时候,XPath将是几个可能的XPath值之一,我希望能够测试给定的XPath是否存在。

如果我的命名错误,这就是我所谓的XPath - 给出这个XML blob:

<foo>
    <bar baz="This is the value of the attribute named baz">
</foo>

我可能正在寻找我称之为“// foo / bar”的XPath,然后读取属性“baz”来获取值。

我用来执行此操作的代码示例:

XPathDocument document = new XPathDocument(filename);
XPathNavigator navigator = document.CreateNavigator();
XPathNavigator node = navigator.SelectSingleNode("//foo/bar");
if(node.HasAttributes)
{
    Console.WriteLine(node.GetAttribute("baz", string.Empty));
}

现在,如果对navigator.SelectSingleNode的调用失败,它将返回NullReferenceException或XPathException。我可以捕获这两个并重构上面的测试,以查看给定的XPath是否返回异常,但我想知道是否有更好的方法?

我没有在Intellisense中看到任何明显的东西。 XPathNavigator有.HasAttributes和.HasChildren但是没有一次遍历一个节点的路径,我没有看到任何更好的使用。

7 个答案:

答案 0 :(得分:10)

如果您已经提供了有效的XPath,但它与任何内容都不匹配,SelectSingleNode将不会抛出一个NullReferenceException - 它将只返回null。

如果你传递SelectSingleNode一些语法上无效的XPath,那就是它会抛出XPathException

通常,您只需要测试返回值是否为null。

答案 1 :(得分:1)

 var baz = navigator.SelectSingleNode("//foo/bar/@baz");
 if (baz != null) Console.WriteLine(baz);

答案 2 :(得分:1)

我认为通过执行navigator.SelectSingleNode(...)来创建XMLNode对象并不好。

您必须使用navigator.Evaluate()代替:

if (Convert.ToBoolean(navigator.Evaluate(@"boolean(//foo/bar)"))) {...}

答案 3 :(得分:0)

从内存中,可能包含错误。

XDocument doc = XDocument.Load("foo.xml");

var att = from a in doc.Descendants("bar")
          select a.Attribute("baz")

foreach (var item in att) {
    if (item != null) { ... }
}

答案 4 :(得分:0)

如果node == nullnode.HasAttributes会抛出NullReferenceException。当//foo/bar与XML文档中的任何元素都不匹配时,就会出现这种情况。

答案 5 :(得分:0)

var node = XDocument.Load(filename)
                    .Descendants("bar")
                    .SingleOrDefault(e=>e.Attribute("baz") != null);

if (node != null) Console.WriteLine(node.Attribute("baz").Value);

答案 6 :(得分:0)

我可能在xpath中更具体。

        var doc = XDocument.Load(fileName);

        var results = from r in doc.XPathSelectElements("/foo/bar[count(@baz) > 0]")
                      select r.Attribute("baz");

        foreach (String s in results)
            Console.WriteLine(s);