Класс расширений MSDN - System.Xml.XPath гласит:
При использовании этих методов существует некоторое снижение производительности. Использование запросов LINQ to XML повышает производительность.
И XPathSelectElement — это метод расширения.
У меня есть следующий XML. Мне нужно найти сообщения и объединить их. Проблема в том, что мне нужно выбрать только сообщения, которые находятся в разделе Status/StatusMsg/StatusDetail. С помощью Descendants я получаю все сообщения, даже за пределами обязательных элементов.
Этого можно правильно добиться с помощью XPathSelectElement. Но поскольку XPathSelectElement является методом расширения, он имеет некоторое снижение производительности, как показано в обзоре производительности LINQ to XML с XPath, в котором говорится:
В большинстве случаев случаях выполнение запроса XPath приведет к увеличению времени выполнения в 5 раз по сравнению с запросом с использованием стандартного LINQ to XML.
Каков наилучший способ сделать это без использования метода расширения в LINQ to XML с использованием C#?
Примечание. Есть ли способ настроить Descendants для этой цели?
XML
XDocument xDoc = XDocument.Parse(@"
INVOICE
2
A
B
C
OUTSIDE
");
КОД
// Descendants
var messageArrayWithOutside = xDoc.Descendants(@"StatusDetail")
.Select(
x => x.Element("Message") == null ? String.Empty : x.Element("Message").Value.Trim()
).ToArray();
var textAll = string.Join(", ", messageArrayWithOutside);
//XPathSelectElements
var messageArray = xDoc.XPathSelectElements(@"Status/StatusMsg/StatusDetail")
.Select(
x => x.Element("Message") == null ? String.Empty : x.Element("Message").Value.Trim()
).ToArray();
var text = string.Join(", ", messageArray);
ОБНОВЛЕНИЕ
XPath кажется быстрее, чем использование Descendants в два раза. Есть идеи, почему?
// Descendants
Stopwatch stopWatchDescendants = new Stopwatch();
stopWatchDescendants.Start();
var messageArrayDecendants = xDoc.Descendants("StatusMsg")
.Descendants("StatusDetail")
.Select(
x => x.Element("Message") == null ?string.Empty : x.Element("Message").Value.Trim()
).ToArray();
var textDecendants = string.Join(", ", messageArrayDecendants);
stopWatchDescendants.Stop();
TimeSpan tsDescendants = stopWatchDescendants.Elapsed;
//XPathSelectElements
Stopwatch stopWatchXPath = new Stopwatch();
stopWatchXPath.Start();
var messageArrayXPath = xDoc.XPathSelectElements(@"Status/StatusMsg/StatusDetail")
.Select(
x => x.Element("Message") == null ? String.Empty : x.Element("Message").Value.Trim()
).ToArray();
var textXPath = string.Join(", ", messageArrayXPath);
stopWatchXPath.Stop();
TimeSpan tsXPath = stopWatchXPath.Elapsed;
if (tsXPath > tsDescendants)
{
Console.WriteLine("LINQ is fast");
}
if (tsDescendants > tsXPath)
{
Console.WriteLine("XPath is fast");
}
Console.WriteLine("XPath :" + tsXPath.ToString());
Console.WriteLine("LINQ :" + tsDescendants.ToString());
Подробнее здесь: https://stackoverflow.com/questions/155 ... ion-method