I have an application in which I am using XPathNavigator to iterate nodes. It is working fine.
But I want to know that if I use LINQ to Xml....
What benefits(Performance, maintainability) I will get?
With XPath, LINQ to Xml what is the performance hit?
I am using C#.net, VS 2010 and my .xml is mid size.
An XPathNavigator object is created from a class that implements the IXPathNavigable interface such as the XPathDocument and XmlDocument classes. XPathNavigator objects created by XPathDocument objects are read-only while XPathNavigator objects created by XmlDocument objects can be edited.
LINQ to XML is a LINQ-enabled, in-memory XML programming interface that enables you to work with XML from within the . NET programming languages. LINQ to XML is like the Document Object Model (DOM) in that it brings the XML document into memory.
Just to add onto what has already been stated here, overall performance seems to depends on what you are actually doing with the document in question. This is what I have concluded based on a simple experimental run comparing parsing performance between XElement to XPathNavigator.
If you are selecting nodes, traversing these nodes and reading some attribute values:
On the other hand, if you are also reading the value of each node's children it gets a little interesting:
These conclusions are based on the following code:
[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 downloaded from here
Overall, it looks like the XElement parsing API, excluding the XPath extensions, gives you the best performance, while also easier to use, if your document is somewhat flat. If you have deep nested structures where you have to do something like
XElement.Element("book").Element("author").Element("firstname").SomethingElse()
then XElement.XPathSelectElement may provide the best compromise between performance and code maintainability.
Well, XPathNavigator
will generally be faster than Linq to XML
queries. But there's always 'but'.
Linq to XML
will definitely make your code more readable and maintainable. It's easier (at least for me) to read linq query then analyze XPath. Also - you will get intellisense when writing query which will help to make your code correct. Linq to XML
also gives you possibility to easily modify data, if that's what you need. XPathNavigator
gives you readonly access.
On the other hand, if you really need top performance, XPathNavigator
is probably the way to go. It simply depends on your current scenario and what you're trying to accomplish. If performance is not an issue (XML file is rather small, you won't make many requests to this file and so on) you can easily go with Linq to XML
. Otherwise stick close to XPathNavigator
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With