Сравнение LINQ to XML с DOM

В этом разделе описываются некоторые основные различия между LINQ to XML и текущим преобладающим программным интерфейсом API XML, а именно моделью DOM консорциума W3C.

Новые способы построения XML-деревьев

В W3C DOM XML-дерево строится снизу вверх, т. е. создается документ, создаются элементы, а затем элементы добавляются в документ.

В качестве примера ниже показан типичный способ создания XML-дерева при помощи реализации DOM от Майкрософт, XmlDocument:

XmlDocument doc = new XmlDocument();
XmlElement name = doc.CreateElement("Name");
name.InnerText = "Patrick Hines";
XmlElement phone1 = doc.CreateElement("Phone");
phone1.SetAttribute("Type", "Home");
phone1.InnerText = "206-555-0144";        
XmlElement phone2 = doc.CreateElement("Phone");
phone2.SetAttribute("Type", "Work");
phone2.InnerText = "425-555-0145";        
XmlElement street1 = doc.CreateElement("Street1");        
street1.InnerText = "123 Main St";
XmlElement city = doc.CreateElement("City");
city.InnerText = "Mercer Island";
XmlElement state = doc.CreateElement("State");
state.InnerText = "WA";
XmlElement postal = doc.CreateElement("Postal");
postal.InnerText = "68042";
XmlElement address = doc.CreateElement("Address");
address.AppendChild(street1);
address.AppendChild(city);
address.AppendChild(state);
address.AppendChild(postal);
XmlElement contact = doc.CreateElement("Contact");
contact.AppendChild(name);
contact.AppendChild(phone1);
contact.AppendChild(phone2);
contact.AppendChild(address);
XmlElement contacts = doc.CreateElement("Contacts");
contacts.AppendChild(contact);
doc.AppendChild(contacts);
Dim doc As XmlDocument = New XmlDocument()
Dim name As XmlElement = doc.CreateElement("Name")
name.InnerText = "Patrick Hines"
Dim phone1 As XmlElement = doc.CreateElement("Phone")
phone1.SetAttribute("Type", "Home")
phone1.InnerText = "206-555-0144"
Dim phone2 As XmlElement = doc.CreateElement("Phone")
phone2.SetAttribute("Type", "Work")
phone2.InnerText = "425-555-0145"
Dim street1 As XmlElement = doc.CreateElement("Street1")
street1.InnerText = "123 Main St"
Dim city As XmlElement = doc.CreateElement("City")
city.InnerText = "Mercer Island"
Dim state As XmlElement = doc.CreateElement("State")
state.InnerText = "WA"
Dim postal As XmlElement = doc.CreateElement("Postal")
postal.InnerText = "68042"
Dim address As XmlElement = doc.CreateElement("Address")
address.AppendChild(street1)
address.AppendChild(city)
address.AppendChild(state)
address.AppendChild(postal)
Dim contact As XmlElement = doc.CreateElement("Contact")
contact.AppendChild(name)
contact.AppendChild(phone1)
contact.AppendChild(phone2)
contact.AppendChild(address)
Dim contacts As XmlElement = doc.CreateElement("Contacts")
contacts.AppendChild(contact)
doc.AppendChild(contacts)
Console.WriteLine(doc.OuterXml)

Такой стиль программирования не дает визуального представления о деталях структуры XML-дерева. LINQ to XML поддерживает такой подход к построению XML-дерева, но также предлагает и альтернативный способ, функциональное построение. При функциональном построении для создания XML-дерева используются конструкторы XElement и XAttribute.

Вот как можно построить такое же XML-дерево с помощью функционального построения LINQ to XML.

XElement contacts =
    new XElement("Contacts",
        new XElement("Contact",
            new XElement("Name", "Patrick Hines"),
            new XElement("Phone", "206-555-0144", 
                new XAttribute("Type", "Home")),
            new XElement("phone", "425-555-0145",
                new XAttribute("Type", "Work")),
            new XElement("Address",
                new XElement("Street1", "123 Main St"),
                new XElement("City", "Mercer Island"),
                new XElement("State", "WA"),
                new XElement("Postal", "68042")
            )
        )
    );

Обратите внимание, что отступы в коде, который строит XML-дерево, показывают структуру базового документа XML.

В Visual Basic код для построения XML-дерева еще проще, так как он использует XML-литерал.

Dim contacts = _
    <Contacts>
        <Contact>
            <Name>Patrick Hines</Name>
            <Phone Type="Home">206-555-0144</Phone>
            <Phone Type="Work">425-555-0145</Phone>
            <Address>
                <Street1>123 Main St</Street1>
                <City>Mercer Island</City>
                <State>WA</State>
                <Postal>68042</Postal>
            </Address>
        </Contact>
    </Contacts>

Если есть готовый XML-документ и требуется создать XML-дерево на его основе, то можно открыть этот документ в редакторе, скопировать XML-данные в буфер обмена, открыть модуль Visual Basic в Visual Studio и вставить XML-данные непосредственно в редактор кода Visual Basic.

Дополнительные сведения см. в разделе Создание XML-деревьев.

Работа непосредственно с XML-элементами

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

  • Создавать XML-элементы, совсем не используя объект документа. Это упрощает программирование, когда необходимо работать с фрагментами XML-деревьев.

  • Загружать объекты T:System.Xml.Linq.XElement непосредственно из XML-файла.

  • Сериализовать объекты T:System.Xml.Linq.XElement в файл или поток.

Сравним это с W3C DOM, где XML-документ используется как логический контейнер для XML-дерева. В DOM XML-узлы, в том числе элементы и атрибуты, должны создаваться в контексте XML-документа. Вот фрагмент кода, предназначенного для создания элемента имени в DOM:

XmlDocument doc = new XmlDocument();
XmlElement name = doc.CreateElement("Name");
name.InnerText = "Patrick Hines";
doc.AppendChild(name);
Dim doc As XmlDocument = New XmlDocument()
Dim name As XmlElement = doc.CreateElement("Name")
name.InnerText = "Patrick Hines"
doc.AppendChild(name)

Если элемент требуется использовать в нескольких документах, нужно будет импортировать в эти документы узлы. LINQ to XML позволяет избавиться от этих сложностей.

При использовании LINQ to XML класс XDocument применяется только, если требуется добавить комментарий или инструкцию по обработке на корневом уровне документа.

Упрощенная обработка имен и пространств имен

В общем случае обработка имен, пространств имен и префиксов пространств имен является сложной частью в программировании на XML. LINQ to XML упрощает работу с ними, исключая необходимость использования полных префиксов пространств имен. Их можно использовать, если требуется управлять префиксами пространств имен. Однако, если принято решение явно не управлять префиксами пространств имен, то при сериализации LINQ to XML назначит префиксы пространств имен, если они необходимы, или, в противном случае, произведет сериализацию при помощи пространств имен по умолчанию. Если используются пространства имен по умолчанию, то в итоговом документе префиксов пространств имен не будет. Дополнительные сведения см. в разделе Работа с пространствами имен XML.

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

Поддержка статических методов для загрузки XML

LINQ to XML позволяет загружать XML при помощи статических методов, а не методов экземпляра. Это упрощает загрузку и синтаксический анализ. Дополнительные сведения см. в разделе Как загрузить XML из файла.

Удаление поддержки конструкций DTD

Исключив поддержку сущностей и ссылок на сущности, LINQ to XML еще более упрощает программирование на XML. Управление сущностями является весьма сложным процессом и поэтому редко используется. Удаление поддержки сущностей позволяет повысить производительность и упростить интерфейс программирования. При заполнении дерева LINQ to XML все сущности DTD раскрываются.

Поддержка фрагментов

LINQ to XML не предоставляет эквивалент класса XmlDocumentFragment. Однако во многих случаях понятие XmlDocumentFragment можно обрабатывать с помощью результата запроса, который типизируется как объект IEnumerable<T> объекта XNode или объект IEnumerable<T> объекта XElement.

Поддержка XPathNavigator

LINQ to XML обеспечивает поддержку XPathNavigator через методы расширения в пространстве имен System.Xml.XPath. Дополнительные сведения см. в разделе System.Xml.XPath.Extensions.

Поддержка пробелов и отступов

Обработка пробелов в LINQ to XML проще, чем в DOM.

Типичный сценарий состоит в чтении XML с отступами, создании XML-дерева в памяти без текстовых узлов с пробелами (то есть без сохранения пробелов), выполнении определенных операций над XML и сохранении XML с отступами. При сериализации XML с форматированием сохраняются только значимые пробелы XML-дерева. Это поведение LINQ to XML по умолчанию.

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

LINQ to XML хранит пробелы, как узлы XText, а не имеет сериализованный тип узла Whitespace, который есть в DOM.

Поддержка заметок

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

Поддержка сведений схемы

LINQ to XML обеспечивает поддержку проверки правильности по схеме XSD через методы расширения в пространстве имен System.Xml.Schema. Можно проверить XML-дерево на соответствие схеме XSD. XML-дерево можно заполнить при помощи модуля проверки после обработки схемы (PSVI). Дополнительные сведения см. в разделах Как выполнить проверку с помощью XSD (LINQ to XML) и Extensions.

См. также

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

Приступая к работе (LINQ to XML)