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


LINQ to XML и DOM

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

Новые способы создания деревьев XML

В DOM W3C вы создаете 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.

Поддержка информации о схеме

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

См. также