> **Источник:** https://python-all.ru/3.2/library/xml.dom.minidom.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# 19.8. [`xml.dom.minidom`](https://python-all.ru/3.2/library/xml.dom.minidom.html#module-xml.dom.minidom) – минимальная реализация DOM

**Исходный код:** [Lib/xml/dom/minidom.py](https://python-all.ru/src/3.2/Lib/xml/dom/minidom.py)

---

[`xml.dom.minidom`](https://python-all.ru/3.2/library/xml.dom.minidom.html#module-xml.dom.minidom) – это минимальная реализация интерфейса Document Object Model с API, похожим на API в других языках. Он задуман как более простой, чем полный DOM, и значительно меньше. Пользователям, которые ещё не знакомы с DOM, следует рассмотреть использование модуля [`xml.etree.ElementTree`](https://python-all.ru/3.2/library/xml.etree.elementtree.html#module-xml.etree.ElementTree) для обработки XML вместо этого.

> **Предупреждение**
>
> Модуль [`xml.dom.minidom`](https://python-all.ru/3.2/library/xml.dom.minidom.html#module-xml.dom.minidom) не является безопасным для злонамеренно сконструированных данных. Если требуется обрабатывать ненадёжные или неаутентифицированные данные, см. [*XML vulnerabilities*](https://python-all.ru/3.2/library/xml.html#xml-vulnerabilities).

Приложения DOM обычно начинают с разбора некоторого XML в DOM. С помощью [`xml.dom.minidom`](https://python-all.ru/3.2/library/xml.dom.minidom.html#module-xml.dom.minidom) это делается через функции parse:

```python
from xml.dom.minidom import parse, parseString

dom1 = parse('c:\\temp\\mydata.xml') # разобрать XML-файл по имени

datasource = open('c:\\temp\\mydata.xml')
dom2 = parse(datasource)   # разобрать открытый файл

dom3 = parseString('<myxml>Some data<empty/> some more data</myxml>')
```

Функция [`parse()`](https://python-all.ru/3.2/library/xml.dom.minidom.html#xml.dom.minidom.parse) может принимать либо имя файла, либо открытый файловый объект.

#### `xml.dom.minidom.parse(filename_or_file, parser=None, bufsize=None)`

Возвращает `Document` из переданных данных. *filename\_or\_file* может быть как именем файла, так и объектом, похожим на файл. *parser*, если задан, должен быть объектом парсера SAX2. Эта функция изменит обработчик документа парсера и активирует поддержку пространств имён; другие настройки парсера (например, установка резолвера сущностей) должны быть выполнены заранее.

Если XML находится в строке, можно использовать функцию [`parseString()`](https://python-all.ru/3.2/library/xml.dom.minidom.html#xml.dom.minidom.parseString) вместо этого:

#### `xml.dom.minidom.parseString(string, parser=None)`

Возвращает объект `Document`, представляющий *строку*. Этот метод создаёт объект `StringIO` для строки и передаёт его в [`parse()`](https://python-all.ru/3.2/library/xml.dom.minidom.html#xml.dom.minidom.parse).

Обе функции возвращают объект `Document`, представляющий содержимое документа.

Функции [`parse()`](https://python-all.ru/3.2/library/xml.dom.minidom.html#xml.dom.minidom.parse) и [`parseString()`](https://python-all.ru/3.2/library/xml.dom.minidom.html#xml.dom.minidom.parseString) подключают XML-парсер к «построителю DOM», который может принимать события парсинга от любого SAX-парсера и преобразовывать их в DOM-дерево. Названия функций, возможно, вводят в заблуждение, но их легко понять при изучении интерфейсов. Разбор документа завершается до возврата из этих функций; просто сами функции не предоставляют реализацию парсера.

Можно также создать `Document`, вызвав метод объекта «DOM Implementation». Этот объект можно получить, вызвав функцию `getDOMImplementation()` в пакете [`xml.dom`](https://python-all.ru/3.2/library/xml.dom.html#module-xml.dom) или в модуле [`xml.dom.minidom`](https://python-all.ru/3.2/library/xml.dom.minidom.html#module-xml.dom.minidom). Получив `Document`, можно добавлять к нему дочерние узлы для заполнения DOM:

```python
from xml.dom.minidom import getDOMImplementation

impl = getDOMImplementation()

newdoc = impl.createDocument(None, "some_tag", None)
top_element = newdoc.documentElement
text = newdoc.createTextNode('Some textual content.')
top_element.appendChild(text)
```

Получив объект DOM-документа, можно обращаться к частям XML-документа через его свойства и методы. Эти свойства определены в спецификации DOM. Основным свойством объекта документа является свойство `documentElement`. Оно даёт основной элемент XML-документа: тот, который содержит все остальные. Вот пример программы:

```python
dom3 = parseString("<myxml>Some data</myxml>")
assert dom3.documentElement.tagName == "myxml"
```

Когда работа с DOM-деревом завершена, можно по желанию вызвать метод `unlink()`, чтобы ускорить очистку уже не нужных объектов. `unlink()` является расширением DOM API, специфичным для [`xml.dom.minidom`](https://python-all.ru/3.2/library/xml.dom.minidom.html#module-xml.dom.minidom), которое делает узел и его потомков по сути бесполезными. В противном случае сборщик мусора Python в конечном итоге позаботится об объектах в дереве.

> **См. также**
>
> **[Спецификация объектной модели документа (DOM) уровня 1](https://python-all.ru/3.2/library/xml.dom.minidom.html)**
>
> Рекомендация W3C для DOM, поддерживаемая
>
> [`xml.dom.minidom`](https://python-all.ru/3.2/library/xml.dom.minidom.html#module-xml.dom.minidom)
>
> .

## 19.8.1. Объекты DOM

Определение DOM API для Python приведено в документации модуля [`xml.dom`](https://python-all.ru/3.2/library/xml.dom.html#module-xml.dom). В этом разделе перечислены различия между этим API и [`xml.dom.minidom`](https://python-all.ru/3.2/library/xml.dom.minidom.html#module-xml.dom.minidom).

#### `Node.unlink()`

Разрывает внутренние ссылки в DOM, чтобы дерево могло быть собрано сборщиком мусора в версиях Python без циклического GC. Даже когда циклический GC доступен, его использование может освободить большие объёмы памяти раньше, поэтому вызов этого метода на DOM-объектах, как только они больше не нужны, является хорошей практикой. Этот метод нужно вызывать только на объекте `Document`, но можно вызывать и на дочерних узлах, чтобы удалить их потомков.

Можно избежать явного вызова этого метода, используя оператор [`with`](https://python-all.ru/3.2/reference/compound_stmts.html#with). Следующий код автоматически вызовет unlink для *dom* при выходе из блока [`with`](https://python-all.ru/3.2/reference/compound_stmts.html#with):

```python
with xml.dom.minidom.parse(datasource) as dom:
    ... # Работать с DOM.
```

#### `Node.writexml(writer, indent="", addindent="", newl="")`

Записывает XML в объект writer. Writer должен иметь метод `write()`, соответствующий интерфейсу файлового объекта. Параметр *indent* задаёт отступ текущего узла. Параметр *addindent* задаёт дополнительный отступ для подузлов текущего узла. Параметр *newl* задаёт строку, используемую для завершения строк.

Для узла `Document` можно использовать дополнительный именованный аргумент *encoding* для указания поля кодировки в заголовке XML.

#### `Node.toxml(encoding=None)`

Возвращает строку или байтовую строку, содержащую XML, представленный узлом DOM.

При явном указании аргумента *encoding* [\[1\]](https://python-all.ru/3.2/library/xml.dom.minidom.html#id3) результатом будет байтовая строка в указанной кодировке. Рекомендуется всегда указывать кодировку; можно использовать любую, но аргумент «utf-8» – самый распространённый выбор, позволяющий избежать исключений [`UnicodeError`](https://python-all.ru/3.2/library/exceptions.html#UnicodeError) при наличии непредставимых текстовых данных.

Без аргумента *encoding* результатом будет строка Unicode, и XML-объявление в результирующей строке не указывает кодировку. Кодирование этой строки в кодировке, отличной от UTF-8, скорее всего, некорректно, так как UTF-8 является кодировкой XML по умолчанию.

#### `Node.toprettyxml(indent="", newl="", encoding="")`

Возвращает красиво отформатированную версию документа. *indent* задаёт строку отступа; по умолчанию это табуляция. *newl* задаёт строку, добавляемую в конце каждой строки; по умолчанию это `\n`.

Аргумент *encoding* ведёт себя так же, как соответствующий аргумент функции [`toxml()`](https://python-all.ru/3.2/library/xml.dom.minidom.html#xml.dom.minidom.Node.toxml).

## 19.8.2. Пример DOM

Эта примерная программа – довольно реалистичный пример простой программы. В данном конкретном случае мы не используем гибкость DOM в полной мере.

```python
import xml.dom.minidom

document = """\
<slideshow>
<title>Demo slideshow</title>
<slide><title>Slide title</title>
<point>This is a demo</point>
<point>Of a program for processing slides</point>
</slide>

<slide><title>Another demo slide</title>
<point>It is important</point>
<point>To have more than</point>
<point>one slide</point>
</slide>
</slideshow>
"""

dom = xml.dom.minidom.parseString(document)

def getText(nodelist):
    rc = []
    for node in nodelist:
        if node.nodeType == node.TEXT_NODE:
            rc.append(node.data)
    return ''.join(rc)

def handleSlideshow(slideshow):
    print("<html>")
    handleSlideshowTitle(slideshow.getElementsByTagName("title")[0])
    slides = slideshow.getElementsByTagName("slide")
    handleToc(slides)
    handleSlides(slides)
    print("</html>")

def handleSlides(slides):
    for slide in slides:
        handleSlide(slide)

def handleSlide(slide):
    handleSlideTitle(slide.getElementsByTagName("title")[0])
    handlePoints(slide.getElementsByTagName("point"))

def handleSlideshowTitle(title):
    print("<title>%s</title>" % getText(title.childNodes))

def handleSlideTitle(title):
    print("<h2>%s</h2>" % getText(title.childNodes))

def handlePoints(points):
    print("<ul>")
    for point in points:
        handlePoint(point)
    print("</ul>")

def handlePoint(point):
    print("<li>%s</li>" % getText(point.childNodes))

def handleToc(slides):
    for slide in slides:
        title = slide.getElementsByTagName("title")[0]
        print("<p>%s</p>" % getText(title.childNodes))

handleSlideshow(dom)
```

## 19.8.3. minidom и стандарт DOM

Модуль [`xml.dom.minidom`](https://python-all.ru/3.2/library/xml.dom.minidom.html#module-xml.dom.minidom), по сути, является DOM, совместимым с DOM 1.0, с некоторыми функциями DOM 2 (в основном связанными с пространствами имён).

Использование интерфейса DOM в Python интуитивно понятно. Применяются следующие правила отображения:

- Интерфейсы доступны через объекты экземпляров. Приложения не должны создавать экземпляры классов напрямую; вместо этого следует использовать функции-создатели, доступные на объекте `Document`. Производные интерфейсы поддерживают все операции (и атрибуты) базовых интерфейсов, а также любые новые операции.
- Операции используются как методы. Поскольку DOM использует только параметры [`in`](https://python-all.ru/3.2/reference/expressions.html#in), аргументы передаются в обычном порядке (слева направо). Необязательных аргументов нет. Операции `void` возвращают `None`.
- Атрибуты IDL отображаются на атрибуты экземпляров. Для совместимости с отображением языка OMG IDL для Python атрибут `foo` можно также получать через методы доступа `_get_foo()` и `_set_foo()`. Атрибуты `readonly` нельзя изменять; это не контролируется во время выполнения.
- Типы `short int`, `unsigned int`, `unsigned long long` и `boolean` отображаются на целочисленные объекты Python.
- Тип `DOMString` отображается на строки Python. [`xml.dom.minidom`](https://python-all.ru/3.2/library/xml.dom.minidom.html#module-xml.dom.minidom) поддерживает как байтовые строки, так и обычные строки, но обычно возвращает строки. Значения типа `DOMString` также могут быть `None`, если спецификация DOM от W3C допускает значение IDL `null`.
- Объявления `const` отображаются на переменные в соответствующей области видимости (например, `xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE`); их нельзя изменять.
- `DOMException` в настоящее время не поддерживается в [`xml.dom.minidom`](https://python-all.ru/3.2/library/xml.dom.minidom.html#module-xml.dom.minidom). Вместо этого [`xml.dom.minidom`](https://python-all.ru/3.2/library/xml.dom.minidom.html#module-xml.dom.minidom) использует стандартные исключения Python, такие как [`TypeError`](https://python-all.ru/3.2/library/exceptions.html#TypeError) и [`AttributeError`](https://python-all.ru/3.2/library/exceptions.html#AttributeError).
- Объекты `NodeList` реализованы с использованием встроенного типа списка Python. Эти объекты предоставляют интерфейс, определённый в спецификации DOM, но в более ранних версиях Python они не поддерживают официальный API. Однако они гораздо более «питоновские», чем интерфейс, определённый в рекомендациях W3C.

Следующие интерфейсы не имеют реализации в [`xml.dom.minidom`](https://python-all.ru/3.2/library/xml.dom.minidom.html#module-xml.dom.minidom):

- `DOMTimeStamp`
- `DocumentType`
- `DOMImplementation`
- `CharacterData`
- `CDATASection`
- `Notation`
- `Entity`
- `EntityReference`
- `DocumentFragment`

Большинство из них отражают информацию в XML-документе, которая не представляет общей ценности для большинства пользователей DOM.

Сноски

| \[1\] | Имя кодировки, указываемое в XML-выводе, должно соответствовать соответствующим стандартам. Например, «UTF-8» допустимо, но «UTF8» недопустимо в объявлении XML-документа, хотя Python принимает его как имя кодировки. См. [http://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl](https://python-all.ru/3.2/library/xml.dom.minidom.html) и [http://www.iana.org/assignments/character-sets](https://python-all.ru/3.2/library/xml.dom.minidom.html). |
| --- | --- |
