我们有一个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对我来说还只有几天的时间......它真棒,但我想知道它是否对某些操作有效率限制。
答案 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;