Просто добавьте к тому, что уже было сказано здесь, общая производительность, похоже, зависит от того, что вы на самом деле делаете с данным документом. Это то, к чему я пришел, основываясь на простом экспериментальном прогоне, сравнивающем производительность парсинга между XElement и XPathNavigator.
Если вы выбираете узлы, проходите через эти узлы и читаете некоторые значения атрибутов:
- XElement.Element работает быстрее, чем XElement.CreateNavigator.Select by
приблизительный коэффициент 1,5.
- XElement.CreateNavigator.Select быстрее
чем XPathNavigator. Выберите примерно в 0,5 раза.
- XPathNavigator.Select выполняется быстрее, чем XElement.XPathSelectElement,
приблизительный коэффициент 0,5.
С другой стороны, если вы также читаете значение дочерних узлов каждого узла, становится немного интереснее:
- XElement.Element работает быстрее, чем XElement.XPathSelectElements, приблизительно в 0,5 раза.
- 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);
}
с books.xml, загруженным с здесь
В целом, похоже, что API синтаксического анализа XElement, за исключением расширений XPath, обеспечивает лучшую производительность, а также более прост в использовании, если ваш документ несколько плоский. Если у вас есть глубоко вложенные структуры, где вы должны сделать что-то вроде
XElement.Element("book").Element("author").Element("firstname").SomethingElse()
тогда XElement.XPathSelectElement может обеспечить лучший компромисс между производительностью и удобством сопровождения кода.