哪个是性能最佳的:XPathNavigator与XPath vs Linq到Xml查询?

我有一个应用程序,我使用XPathNavigator迭代节点。 它工作正常。

但我想知道如果我使用LINQ to Xml ….

  1. 我会得到什么好处(性能,可维护性)?

  2. 有了XPath,LINQ to Xml的性能如何?

我正在使用C#.net,VS 2010,我的.xml是中等大小。

好吧, XPathNavigator通常比Linq to XML更快地Linq to XML查询。 但总有’但’。

Linq to XML肯定会使您的代码更具可读性和可维护性。 阅读linq查询然后分析XPath更容易(至少对我来说)。 此外 – 在编写查询时,您将获得智能感知,这将有助于使您的代码更正。 如果您需要, Linq to XML还可以轻松修改数据。 XPathNavigator为您提供只读访问权限。

另一方面,如果你真的需要最佳性能, XPathNavigator可能就是你要走的路。 它只取决于您当前的情况以及您要完成的任务。 如果性能不是问题(XML文件相当小,您不会对此文件发出很多请求等),您可以轻松地使用Linq to XML 。 否则贴近XPathNavigator

只是为了添加已经在此处陈述的内容,整体性能似乎取决于您对相关文档的实际操作。 这是我基于一个简单的实验运行得出的结论,比较了XElement与XPathNavigator之间的解析性能。

如果要选择节点,则遍历这些节点并读取某些属性值:

  • XElement.Element比XElement.CreateNavigator.Select快大约1.5倍。
  • XElement.CreateNavigator.Select比XPathNavigator.Select更快,大约为0.5。
  • XPathNavigator.Select比XElement.XPathSelectElement快大约0.5倍。

另一方面,如果您还在阅读每个节点的子节点的值,那么它会变得有趣:

  • XElement.Element比XElement.XPathSelectElements快大约0.5倍。
  • XElement.XPathSelectElement比XPathNavigator.Select快大约3倍。
  • XPathNavigator.Select比XElement.CreateNavigator.Select快大约0.5倍。

这些结论基于以下代码:

  [Test] public void CompareXPathNavigatorToXPathSelectElement() { var max = 100000; Stopwatch watch = new Stopwatch(); watch.Start(); bool parseChildNodeValues = true; ParseUsingXPathNavigatorSelect(max, watch, parseChildNodeValues); ParseUsingXElementElements(watch, max, parseChildNodeValues); ParseUsingXElementXPathSelect(watch, max, parseChildNodeValues); ParseUsingXPathNavigatorFromXElement(watch, max, parseChildNodeValues); } private static void ParseUsingXPathNavigatorSelect(int max, Stopwatch watch, bool parseChildNodeValues) { var document = new XPathDocument(@"data\books.xml"); var navigator = document.CreateNavigator(); for (var i = 0; i < max; i++) { var books = navigator.Select("/catalog/book"); while (books.MoveNext()) { var location = books.Current; var book = new Book(); book.Id = location.GetAttribute("id", ""); if (!parseChildNodeValues) continue; book.Title = location.SelectSingleNode("title").Value; book.Genre = location.SelectSingleNode("genre").Value; book.Price = location.SelectSingleNode("price").Value; book.PublishDate = location.SelectSingleNode("publish_date").Value; book.Author = location.SelectSingleNode("author").Value; } } watch.Stop(); Console.WriteLine("Time using XPathNavigator.Select = " + watch.ElapsedMilliseconds); } private static void ParseUsingXElementElements(Stopwatch watch, int max, bool parseChildNodeValues) { watch.Restart(); var element = XElement.Load(@"data\books.xml"); for (var i = 0; i < max; i++) { var books = element.Elements("book"); foreach (var xElement in books) { var book = new Book(); book.Id = xElement.Attribute("id").Value; if (!parseChildNodeValues) continue; book.Title = xElement.Element("title").Value; book.Genre = xElement.Element("genre").Value; book.Price = xElement.Element("price").Value; book.PublishDate = xElement.Element("publish_date").Value; book.Author = xElement.Element("author").Value; } } watch.Stop(); Console.WriteLine("Time using XElement.Elements = " + watch.ElapsedMilliseconds); } private static void ParseUsingXElementXPathSelect(Stopwatch watch, int max, bool parseChildNodeValues) { XElement element; watch.Restart(); element = XElement.Load(@"data\books.xml"); for (var i = 0; i < max; i++) { var books = element.XPathSelectElements("book"); foreach (var xElement in books) { var book = new Book(); book.Id = xElement.Attribute("id").Value; if (!parseChildNodeValues) continue; book.Title = xElement.Element("title").Value; book.Genre = xElement.Element("genre").Value; book.Price = xElement.Element("price").Value; book.PublishDate = xElement.Element("publish_date").Value; book.Author = xElement.Element("author").Value; } } watch.Stop(); Console.WriteLine("Time using XElement.XpathSelectElement = " + watch.ElapsedMilliseconds); } private static void ParseUsingXPathNavigatorFromXElement(Stopwatch watch, int max, bool parseChildNodeValues) { XElement element; watch.Restart(); element = XElement.Load(@"data\books.xml"); for (var i = 0; i < max; i++) { // now we can use an XPath expression var books = element.CreateNavigator().Select("book"); while (books.MoveNext()) { var location = books.Current; var book = new Book(); book.Id = location.GetAttribute("id", ""); if (!parseChildNodeValues) continue; book.Title = location.SelectSingleNode("title").Value; book.Genre = location.SelectSingleNode("genre").Value; book.Price = location.SelectSingleNode("price").Value; book.PublishDate = location.SelectSingleNode("publish_date").Value; book.Author = location.SelectSingleNode("author").Value; } } watch.Stop(); Console.WriteLine("Time using XElement.Createnavigator.Select = " + watch.ElapsedMilliseconds); } 

从这里下载books.xml

总的来说,如果你的文档有点扁平,看起来XElement解析API(不包括XPath扩展)可以提供最佳性能,同时也更容易使用。 如果你有深层嵌套结构,你必须做类似的事情

 XElement.Element("book").Element("author").Element("firstname").SomethingElse() 

然后XElement.XPathSelectElement可以提供性能和代码可维护性之间的最佳折衷。