Поделиться через


Сравнение изменения XML-дерева в памяти с функциональным построением (LINQ to XML)

Обновлен: November 2007

Изменение XML-дерева на месте является традиционным подходом к изменению формы XML-документа. Стандартное приложение загружает документ в источник данных, например DOM или LINQ to XML, при помощи интерфейса программирования вставляет, удаляет узлы или изменяет их содержимое, а затем сохраняет XML в файл или передает по сети.

LINQ to XML позволяет действовать другим способом, что может быть полезно во многих ситуациях: функциональное построение. При функциональном построении изменение данных рассматривается как задача преобразования, а не как детализированное управление хранилищем данных. Если можно взять представление данных и эффективно преобразовать его из одной формы в другую, то результат будет таким же, как если бы в одном хранилище данных были произведены некоторые изменения, направленные на то, чтобы оно приняло другую форму. Основным элементом функционального построения является передача результатов запросов конструкторам XDocument и XElement.

Во многих случаях можно написать код для преобразования, затратив лишь часть того времени, которое ушло бы на внесение изменений в хранилище данных, причем этот код надежнее и его проще сопровождать. В таких случаях это более эффективный способ изменения данных, несмотря на то что для его реализации может потребоваться больше вычислительной мощности. Если разработчик знаком с функциональным подходом, то во многих случаях итоговый код получается проще для понимания. Проще найти код, который изменяет каждую часть дерева.

Вариант, когда XML-дерево изменяется на месте, в большей степени известен многим программистам DOM, а код, написанный при помощи функционального подхода, может показаться программисту, который еще не разобрался в этом методе, незнакомым. Если требуется внести лишь небольшое изменение в большое XML-дерево, то при изменении дерева на месте во многих случаях требуется меньше времени ЦП.

В этом разделе приведен пример, реализованный обоими методами.

Преобразование атрибутов в элементы

Для этого примера предположим, что требуется изменить следующий образец XML-документа, чтобы атрибуты стали элементами. Сначала в этом разделе представлен обычный способ изменения на месте. Затем показан способ функционального построения.

<?xml version="1.0" encoding="utf-8" ?>
<Root Data1="123" Data2="456">
  <Child1>Content</Child1>
</Root>

Изменение XML-дерева

Можно написать процедурный код, чтобы создать элементы из атрибутов, а затем удалить атрибуты. Вот как это делается:

XElement root = XElement.Load("Data.xml");
foreach (XAttribute att in root.Attributes()) {
    root.Add(new XElement(att.Name, (string)att));
}
root.Attributes().Remove();
Console.WriteLine(root);
Dim root As XElement = XElement.Load("Data.xml")
For Each att As XAttribute In root.Attributes()
    root.Add(New XElement(att.Name, att.Value))
Next
root.Attributes().Remove()
Console.WriteLine(root)

Этот код выводит следующие результаты:

<Root>
  <Child1>Content</Child1>
  <Data1>123</Data1>
  <Data2>456</Data2>
</Root>

Подход на основе функционального построения

В отличие от этого, функциональный подход основан на применении кода, предназначенного для формирования нового дерева, выбора и извлечения элементов и атрибутов из исходного дерева и их соответствующего преобразования по мере добавления в новое дерево. Пример функционального подхода выглядит примерно так:

XElement root = XElement.Load("Data.xml");
XElement newTree = new XElement("Root",
    root.Element("Child1"),
    from att in root.Attributes()
    select new XElement(att.Name, (string)att)
);
Console.WriteLine(newTree);
Dim root As XElement = XElement.Load("Data.xml")
Dim newTree As XElement = _
    <Root>
        <%= root.<Child1> %>
        <%= From att In root.Attributes() _
            Select New XElement(att.Name, att.Value) %>
    </Root>
Console.WriteLine(newTree)

В этом примере формируется такой же итоговый XML-документ, как и в первом примере. Но обратите внимание, что при функциональном подходе можно видеть итоговую структуру нового XML-документа. Можно видеть создание элемента Root, код, который получает по запросу элемент Child1 из исходного дерева, а также код, который преобразует атрибуты из исходного дерева в элементы в новом дереве.

В этом случае функциональный код вряд ли будет короче, чем код из первого примера, и совсем не проще. Но если в XML-дерево требуется внести много изменений, то подход, отличный от функционального, может стать довольно сложным и громоздким. В отличие от этого, при использовании функционального подхода происходит просто формирование требуемого XML-документа, когда соответствующие запросы и выражения встраиваются, чтобы получать по запросу нужное содержимое. При функциональном подходе получается код, более простой в сопровождении.

Обратите внимание, что в этом случае функциональный подход, вероятно, обеспечит более низкую производительность в сравнении с внесением изменений в дерево. Основная проблема заключается в том, что при функциональном подходе создается больше объектов, существующих в течение непродолжительного времени. Однако этим недостатком можно пренебречь, если использование функционального подхода позволяет повысить производительность работы программиста.

Это очень простой пример, однако он хорошо иллюстрирует различие в основах этих двух подходов. Функциональный подход обеспечивает большую производительность при преобразовании больших XML-документов.

См. также

Другие ресурсы

Изменение XML-деревьев (LINQ to XML)