如何实现简单的XPath查找

时间:2009-07-23 03:13:38

标签: .net xml linq xpath linq-to-xml

我们有一个XML文件,其实现非常简单XLink

<root xmlns:xlink="http://www.w3.org/1999/xlink">
  <firstChild id="ID1" />
  ...
  <ref xlink:href="#ID1" />
</root>

让我们假设XLink实现不会比这更复杂。但重要的是,所引用的元素(在本例中为firstChild)可以出现在文档中的任何位置,层次结构中的任何位置。

在XPath查找中,您可以找到&lt; ref&gt;所引用的元素。节点使用如下表达式:

//*[@id='ID1']

使用LINQ to XML的最佳等价物是什么?我已经考虑过这些问题:

XDocument doc = XDocument.Load("file.xml");
var dest = xDoc.Descendants().Where(e => (string)e.Attribute("id") == "ID1").SingleOrDefault();

我还没有真正测试过它。但总的来说,如果XML文档非常大,那么LINQ方式是否效率低(因为它使用了XDocument上所有后代的枚举)?恢复到XPathNavigator并使用XPath表达式会更好吗?

如果在LINQ中可以做这种事情,那么有没有比我写的更好的方法? LINQ对我来说还只有几天的时间......它真棒,但我想知道它是否对某些操作有效率限制。

3 个答案:

答案 0 :(得分:3)

XPathNavigator在这里不会更有效率,因为它仍然需要枚举所有后代才能找到它们 - 那里没有魔法尘埃。如果您希望它比它更有效,那么您将需要一个索引,并且没有内置的XML API提供开箱即用的功能,因此您必须推出自己的索引。例如:

XDocument doc = ...;
var id2elem = (from e in doc.Descendants()
               let id = e.Attribute("id")
               where id != null
               select new { Id = id.Value, Element = e })
              .ToDictionary(kv => kv.Id, kv => kv.Element);

然后根据需要使用该字典按ID查找节点。显然,如果查找相对频繁,这是值得的,而不是只需要做一次或两次。

答案 1 :(得分:1)

如果我是你,我会以同样的方式做到这一点。除了where子句:

from e in xDoc.Descendants()
let id = e.Attribute("id") ? e.Attribute("id").Value : null
where (id == "ID")
select e

所以不需要进行类型转换。

关于你的第一个问题,据我所知,微软停止了对XPath实现的开发,所以我相信,即使不是,目前,与XPath相比,LINQ to XML将有更好的优化。

答案 2 :(得分:0)

from e in doc.Descendants()
where (string)e.Attribute("id") != null
select e;