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

时间:2011-12-16 06:04:28

标签: c# .net-4.0 linq-to-xml xmldocument xpathnavigator

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

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

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

  2. 使用XPath,LINQ to Xml会有什么性能影响?

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

2 个答案:

答案 0 :(得分:6)

只是添加到此处已经说明的内容,整体性能似乎取决于您对相关文档的实际操作。这是我基于简单的实验运行得出的结果,比较了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);
    }

here

下载books.xml

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

的操作
XElement.Element("book").Element("author").Element("firstname").SomethingElse()

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

答案 1 :(得分:3)

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

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

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

相关问题