LINQ to XML и DOM

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

Новые способы создания деревьев 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 также поддерживает альтернативный подход, функциональное построение, которое лучше показывает структуру. Этот подход можно сделать с XElement помощью конструкторов и XAttribute конструкторов. В Visual Basic также можно использовать XML-литералы. В этом примере демонстрируется построение одного и того же 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")
            )
        )
    );
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. В версии Visual Basic используются XML-литералы.

Дополнительные сведения см. в деревах 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-документа. Ниже приведен фрагмент кода для создания элемента name в 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 назначит префиксы пространства имен во время сериализации, если они необходимы, или сериализуются с помощью пространств имен по умолчанию, если они не нужны. Если используются пространства имен по умолчанию, то в итоговом документе префиксов пространств имен не будет. Дополнительные сведения см. в обзоре пространств имен.

Еще одна проблема с 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 с использованием XSD и Extensions.

См. также