哪一个在性能方面是最好的:带XPath的XPathNavigator vs带查询的Linq to Xml

本文关键字:XPathNavigator vs XPath 查询 Xml to Linq 性能 方面 哪一个 | 更新日期: 2023-09-27 18:18:06

我有一个使用XPathNavigator迭代节点的应用程序。

但是我想知道如果我使用LINQ到Xml....

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

  2. 使用XPath, LINQ到Xml的性能影响是什么?

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

哪一个在性能方面是最好的:带XPath的XPathNavigator vs带查询的Linq to Xml

在前面已经说过的基础上再补充一点,总体性能似乎取决于您实际对相关文档所做的操作。这是我通过比较XElement和XPathNavigator之间解析性能的简单实验得出的结论。

如果您正在选择节点,遍历这些节点并读取一些属性值:

  • XElement。元素比XElement.CreateNavigator.Select的速度快近似因子为1.5。
  • XElement.CreateNavigator。选择更快XPathNavigator。选择近似因子0.5。
  • XPathNavigator。Select比XElement快。XPathSelectElement由因子约为0.5。

另一方面,如果您还读取每个节点的子节点的值,那就有点有趣了:

  • XElement。Element比XElement快。XPathSelectElements .
  • XElement。XPathSelectElement比XPathNavigator快。选择近似因子为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);
    }

with books.xml从这里下载

总的来说,看起来XElement解析API(不包括XPath扩展)提供了最好的性能,同时如果文档比较平坦,也更容易使用。如果你有深度嵌套的结构你需要做一些像 这样的事情
XElement.Element("book").Element("author").Element("firstname").SomethingElse()

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

嗯,XPathNavigator通常会比Linq to XML查询快。但总有"但是"。

Linq to XML绝对会使你的代码更易读和可维护。阅读linq查询比分析XPath更容易(至少对我来说)。另外,当你写查询的时候,你会得到智能感知,这将有助于使你的代码正确。如果需要的话,Linq to XML还提供了轻松修改数据的可能性。XPathNavigator给你只读权限。

另一方面,如果你真的需要顶级性能,XPathNavigator可能是最好的选择。这完全取决于你当前的情况和你想要实现的目标。如果性能不是问题(XML文件相当小,您不会对该文件发出很多请求,等等),您可以轻松地使用Linq to XML。否则紧贴XPathNavigator