Перейти к основному содержимому

XML DOM

Разработчику

Что такое XML DOM

DOM (Document Object Model) — программный интерфейс к дереву XML (и HTML). Парсер загружает файл в память и предоставляет объекты для чтения, изменения, добавления и удаления узлов.

В экосистеме XML DOM тесно связан с XPath (глава) и отличается от потоковых API (SAX, XmlReader в .NET), которые не держат всё дерево в памяти.

ПодходПамятьУдобство
DOMВесь документПроизвольная навигация, правки
SAX / XmlReaderПотокБольшие файлы, только последовательное чтение
LINQ to XML (XDocument)Дерево, современный API .NETУдобнее классического DOM

Основы разметки: XML.


Конвейер обработки XML

Программа редко "просто читает файл". Типичная схема (по модели XML-процессора):

СтадияОтветственность
ПарсерКодировка, токены, дерево; ошибка → номер строки
ValidatorСоответствие XSD/DTD (опционально)
API доступаDOM (всё в памяти), SAX/StAX (события), LINQ to XML
ТрансформацияXSLT или обход дерева в коде

SAX — событийная модель

SAX (Simple API for XML) не строит полное дерево в памяти. Парсер вызывает обработчики (handlers) по мере чтения:

СобытиеКогда
startElementОткрывающий тег
charactersТекстовые данные
endElementЗакрывающий тег
startDocument / endDocumentНачало и конец
// Java JAXP — иллюстрация идеи
DefaultHandler handler = new DefaultHandler() {
@Override
public void startElement(String uri, String localName, String qName, Attributes attrs) {
// обработка открытия тега
}
};
SAXParserFactory.newInstance().newSAXParser().parse(new File("big.xml"), handler);

В .NET аналог — XmlReader (последовательное чтение без DOM):

using var reader = XmlReader.Create("big.xml");
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == "book")
{
string id = reader.GetAttribute("id");
}
}
КритерийDOM / XDocumentSAX / XmlReader
ПамятьВесь документO(1) относительно размера файла
НавигацияПроизвольная, XPathТолько вперёд по потоку
Изменение дереваДаНет (только генерация нового)
Типичный размерДо десятков МБГигабайтные логи и выгрузки

Для больших XML на сервере сначала оцените потоковый API; DOM удобен для небольших конфигов и сообщений интеграции.


Узлы XML DOM

Каждый фрагмент документа — узел с типом nodeType (в W3C DOM):

ТипКонстанта (типично)Пример
ElementELEMENT_NODE (1)<book>
AttributeATTRIBUTE_NODE (2)id="1"
TextTEXT_NODE (3)Война и мир
CDATA SectionCDATA_SECTION_NODE (4)<![CDATA[...]]>
Entity ReferenceENTITY_REFERENCE_NODE (5)&amp;
EntityENTITY_NODE (6)в DTD
Processing InstructionPROCESSING_INSTRUCTION_NODE (7)<?xml-stylesheet ...?>
CommentCOMMENT_NODE (8){/* ... */}
DocumentDOCUMENT_NODE (9)корень API
Document TypeDOCUMENT_TYPE_NODE (10)<!DOCTYPE ...>
Document FragmentDOCUMENT_FRAGMENT_NODE (11)временный контейнер
NotationNOTATION_NODE (12)в DTD

Доступ к узлам

После разбора документа доступны свойства и методы (имена близки в JavaScript, Java, .NET XmlDocument):

ОперацияИдея
documentElementКорневой элемент XML
getElementsByTagName('book')Коллекция по локальному имени (без учёта NS в старых API)
getAttribute('id')Значение атрибута элемента
childNodesВсе дочерние узлы, включая текст и комментарии
firstChild / lastChildПервый / последний дочерний
parentNodeРодитель
nodeValueТекст для текстовых узлов; для элементов — не всегда то, что ожидают новички

В .NET для новых проектов чаще используют XElement, XDocument; классический DOM — XmlDocument + SelectNodes с XPath.

Пример чтения (C# / XmlDocument):

var doc = new XmlDocument();
doc.Load("library.xml");
XmlNodeList books = doc.SelectNodes("/library/book");
foreach (XmlNode book in books)
{
string title = book.SelectSingleNode("title")?.InnerText;
string id = book.Attributes["id"]?.Value;
}

Тот же выбор через XPath описан в главе XPath.


NodeList и NodeMap

NodeList — упорядоченная коллекция узлов (результат getElementsByTagName, XPath). Может быть "живой": изменение дерева меняет список.

NamedNodeMap — атрибуты элемента, доступ по имени или индексу:

// Иллюстрация в стиле W3C DOM (браузер / legacy)
const attr = element.attributes.getNamedItem('id');

Важно: текст внутри <title>Война</title> часто представлен как дочерний текстовый узел, а не как "значение элемента" одной строкой — при обходе childNodes появляются "лишние" текстовые узлы с пробелами и переводами строк.


Обход дерева узлов

Три классических способа:


1. По дочерним узлам (рекурсия)

function traverse(node):
обработать(node)
for each child in node.childNodes:
traverse(child)

2. Обход в глубину (DFS)

Сначала вниз по ветке, затем к соседям — естественен для DOM.


3. TreeWalker / NodeIterator (W3C)

Фильтры по типу узла (только элементы, без пустого текста). В .NET аналог — собственные обходы или LINQ по Descendants().


Навигация по узлам

Свойство / методНаправление
parentNodeВверх
childNodesВниз на один уровень
nextSibling / previousSiblingСоседи на том же уровне
XPath /library/book[2]/titleДекларативный путь (XPath)

Смешанный контент — между <book> и <title> парсер может вставить текстовый узел с переводом строки — при nodeValue элемента book получится склейка текстов потомков, но не всегда так, как ожидается без InnerText / нормализации.

Создание и вставка (редактирование дерева):

  • createElement, createTextNode, setAttribute;
  • appendChild, insertBefore, removeChild, replaceChild.

После изменений документ сериализуют обратно в файл (Save в .NET).


DOM в браузере и на сервере

КонтекстAPI
БраузерDOMParser, document.implementation.createDocument — для XML; HTML использует тот же DOM, но другие правила
JavaDocumentBuilder, org.w3c.dom
.NETXmlDocument, предпочтительно XDocument
Pythonxml.dom.minidom (реже — lxml etree)

Для больших XML на сервере предпочтительны потоковые парсеры; DOM загружает весь файл в RAM.


Связь с XSLT и валидацией

  • XSLT-процессор внутри строит дерево исходника (часто DOM-подобное).
  • Валидация XSD может выполняться до или после построения DOM (XML, справочник).
  • Преобразование через XSLT: глава XSLT — DOM исходника напрямую не обязателен менять.
Практическое задание

Загрузите небольшой XML в IDE или скриптом, выведите список имён всех дочерних элементов корня и значения каждого атрибута id у элементов book.