Вообще говоря, если вы собираетесь использовать дерево исходного документа только один раз, вы ничего не получите от его десериализации в какую-то специализированную объектную модель.Расходы на допуск - анализ XML - могут значительно снизить затраты на его использование, и любое увеличение производительности, которое вы получите от представления проанализированного XML в чем-то более эффективном, чем дерево узлов XML, будет незначительным.
Однако, если вы используете данные в исходном документе снова и снова, может иметь смысл проанализировать эти данные в более доступной структуре.Вот почему в XSLT есть элемент xsl:key
и функция key()
: поиск узла XML в хэш-таблице может быть намного быстрее, чем линейный поиск в списке узлов XML, поэтому стоит добавить эту возможность вlanguage.
Чтобы обратиться к вашему конкретному примеру, итерация по List<Thing>
будет выполняться с той же скоростью, что и итерация по List<XmlNode>
.То, что сделает XSLT медленнее, это не итерация.Это поиск и то, что вы делаете с найденными узлами.При выполнении запроса XPath Things/Thing
выполняется итерация по дочерним элементам текущего узла, выполняется сравнение строк, чтобы проверить имя каждого элемента, и, если элемент соответствует, он выполняет итерацию по дочерним узлам этого элемента и выполняет другое сравнение строк для каждого.(На самом деле, я не знаю точно, что он выполняет сравнение строк. Насколько я знаю, процессор XSLT хэшировал имена в исходном документе и XPath и выполняет целочисленные сравнения значений хеш-функции.) Это дорогочасть операции, а не фактическая итерация по результирующему набору узлов.
Кроме того, почти все, что вы делаете с результирующими узлами в XSLT, будет включать линейный поиск по набору узлов.Доступ к свойству объекта в C # отсутствует.Доступ к MyThing.MyProperty
будет быстрее, чем к нему через <xsl:value-of select='MyProperty'/>
.
Как правило, это не имеет значения, потому что синтаксический анализ XML стоит дорого, независимо от того, десериализуете ли вы его в пользовательскую объектную модель или * 1016.*.Но есть еще один случай, в котором это может быть актуально: если исходный документ очень большой и вам нужна только небольшая его часть.
Когда вы используете XSLT, вы, по сути, дважды просматриваете XML.Сначала вы создаете исходное дерево документов в памяти, а затем преобразование обрабатывает это дерево.Если вам нужно выполнить какой-нибудь неприятный XPath, например //*[@some-attribute='some-value']
, чтобы найти 200 элементов в документе с миллионами элементов, вы в основном посещаете каждый из этих миллионов узлов дважды.
Это сценарий, в котором это может бытьСтоит использовать XmlReader
вместо XSLT (или перед использованием XSLT).Вы можете реализовать метод, который пересекает поток XML и тестирует каждый элемент, чтобы увидеть, представляет ли он интерес, создавая исходное дерево, которое содержит только ваши интересные узлы.Или, если вы хотите по-настоящему сойти с ума, вы можете реализовать подкласс XmlReader
, который пропускает неинтересные узлы, и передавать его в качестве входных данных XslCompiledTemplate.Transform()
.(Однако я подозреваю, что если бы вы знали достаточно о том, как работает XmlReader
для его подкласса, вам, вероятно, не понадобилось бы задавать этот вопрос, во-первых.) Этот подход позволяет вам посетить 1 000 200 узлов вместо 2 000 000.Это также боль в заднице, но иногда искусство требует жертв от художника.