Я хотел посмотреть, какое из этих предложенных решений работает лучше всего, поэтому я провел несколько сравнительных тестов. Из интереса я также сравнил методы LINQ с простым старым методом System.Xml, предложенным Грегом. Вариация была интересной и не такой, как я ожидал: самые медленные методы были более чем в 3 раза медленнее, чем самые быстрые .
Результаты упорядочены от самых быстрых до самых медленных:
- CreateReader - Instance Hunter (0,113 секунды)
- Обычный старый System.Xml - Грег Херлман (0,134 секунды)
- Агрегат с конкатенацией строк - Майк Пауэлл (0,324 секунды)
- StringBuilder - Vin (0,333 секунды)
- String.Join на массив - Терри (0,360 секунд)
- String.Concat по массиву - Марчин Косерадзки (0.364)
метод
Я использовал один XML-документ с 20 одинаковыми узлами (называемый «подсказка»):
<hint>
<strong>Thinking of using a fake address?</strong>
<br />
Please don't. If we can't verify your address we might just
have to reject your application.
</hint>
Числа, показанные в секундах выше, являются результатом извлечения «внутреннего XML» из 20 узлов 1000 раз подряд и получения среднего (среднего) из 5 запусков. Я не включил время, необходимое для загрузки и синтаксического анализа XML в XmlDocument
(для метода System.Xml ) или XDocument
(для всех остальных).
Я использовал следующие алгоритмы LINQ: (C # - все берут XElement
«родителя» и возвращают внутреннюю строку XML)
CreateReader:
var reader = parent.CreateReader();
reader.MoveToContent();
return reader.ReadInnerXml();
Агрегировать с конкатенацией строк:
return parent.Nodes().Aggregate("", (b, node) => b += node.ToString());
StringBuilder:
StringBuilder sb = new StringBuilder();
foreach(var node in parent.Nodes()) {
sb.Append(node.ToString());
}
return sb.ToString();
String.Join на массив:
return String.Join("", parent.Nodes().Select(x => x.ToString()).ToArray());
String.Concat в массиве:
return String.Concat(parent.Nodes().Select(x => x.ToString()).ToArray());
Я не показал здесь алгоритм «Простой старый System.Xml», так как он просто вызывает .InnerXml на узлах.
Вывод
Если важна производительность (например, много XML, часто анализируется), я бы использовал CreateReader
метод Дэниела каждый раз . Если вы просто делаете несколько запросов, возможно, вы захотите использовать более краткий метод Майка Aggregate.
Если вы используете XML для больших элементов с большим количеством узлов (возможно, с сотнями), вы, вероятно, начнете видеть преимущества использования StringBuilder
метода Aggregate, но не более CreateReader
. Я не думаю , что Join
и Concat
методы когда - либо будут более эффективными в этих условиях из - за штраф преобразования большого списка большого массива (даже очевидном здесь с небольшими списками).
parent.CreateNavigator().InnerXml
(нуженusing System.Xml.XPath
метод расширения)..ToArray()
внутренняя часть.Concat
, но, похоже, она ускоряется.ToString()
за этого ответа . Кажется, еще быстрее ...var reader = parent.CreateReader();
в операторе использования.Я думаю, что это гораздо лучший метод (в VB его не должно быть сложно перевести):
Дан XElement x:
источник
Как насчет использования этого метода "extension" в XElement? работал на меня!
ИЛИ использовать немного Linq
Примечание : код выше должен использовать
element.Nodes()
в противоположностьelement.Elements()
. Очень важно запомнить разницу между двумя.element.Nodes()
дает вам все какXText
иXAttribute
т. д., ноXElement
только элемент.источник
С должным уважением к тем, кто нашел и доказал лучший подход (спасибо!), Здесь он обернут в метод расширения:
источник
Держите это простым и эффективным:
источник
Я закончил тем, что использовал это:
источник
Лично я закончил писать
InnerXml
метод расширения с использованием метода Aggregate:Мой клиентский код будет таким же лаконичным, как и в старом пространстве имен System.Xml:
источник
@ Грег: Похоже, вы отредактировали свой ответ, чтобы он был совершенно другим. На что мой ответ - да, я мог бы сделать это с помощью System.Xml, но надеялся получить удовольствие от LINQ to XML.
Я оставлю свой исходный ответ ниже на тот случай, если кому-то еще будет интересно, почему я не могу просто использовать свойство .Value XElement, чтобы получить то, что мне нужно:
@Greg: свойство Value объединяет все текстовое содержимое любых дочерних узлов. Поэтому, если элемент body содержит только текст, он работает, но если он содержит XHTML, я получаю объединенный весь текст, но ни один из тегов.
источник
<root>random text <sub1>child</sub1> <sub2>child</sub2></root>
), который сталrandom text childchild
черезXElement.Parse(...).Value
// использование Regex может быть быстрее, просто обрезать начальный и конечный тег элемента
источник
IndexOf
:var xml = root.ToString(); var begin = xml.IndexOf('>')+1; var end = xml.LastIndexOf('<'); return xml.Substring(begin, end-begin);
Работает doc.ToString () или doc.ToString (SaveOptions). См. Http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.tostring(v=vs.110).aspx
источник
Можно ли использовать объекты пространства имен System.Xml для выполнения работы здесь вместо использования LINQ? Как вы уже упоминали, XmlNode.InnerXml - это именно то, что вам нужно.
источник
Интересно, если (обратите внимание, я избавился от b + = и просто есть b +)
может быть немного менее эффективным, чем
Не уверен на 100% ... но взглянув на Aggregate () и string.Join () в Reflector ... Я думаю, что я прочитал это как Aggregate, просто добавляя возвращаемое значение, так что по сути вы получите:
строка = строка + строка
В отличие от string.Join, там есть упоминание о FastStringAllocation или о чем-то еще, что заставляет меня задуматься о том, что ребята из Microsoft могли бы добавить туда дополнительное повышение производительности. Конечно, мой .ToArray () называет это моим отрицанием, но я просто хотел предложить другое предложение.
источник
знаешь? Лучше всего вернуться к CDATA :( Я смотрю на решения здесь, но я думаю, что CDATA - самый простой и дешевый, но не самый удобный способ разработки с этим
источник
Сделаю работу за вас
источник
источник