Spec-Zone.ru › Python 3.12

xml.dom.minidom — Минимальная реализация DOM

Исходный код: Lib/xml/dom/minidom.py

xml.dom.minidom — это минимальная реализация интерфейса объектной модели документа, API которой похож на API в других языках. Она задумана как более простая и значительно более компактная альтернатива полной DOM. Тем, кто ещё не знаком с DOM, для обработки XML рекомендуется использовать модуль xml.etree.ElementTree.

Предупреждение

Модуль xml.dom.minidom не защищён от вредоносно сформированных данных. Если вам нужно анализировать недоверенные данные или данные, подлинность которых не подтверждена, см. раздел Уязвимости XML.

Обычно работа с DOM начинается с разбора XML в DOM. В xml.dom.minidom для этого используются функции разбора:

from xml.dom.minidom import parse, parseString

dom1 = parse('c:\\temp\\mydata.xml')  # parse an XML file by name

datasource = open('c:\\temp\\mydata.xml')
dom2 = parse(datasource)  # parse an open file

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

Функция parse() принимает имя файла или открытый файловый объект.

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

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

Если XML представлен строкой, вместо этого можно использовать функцию parseString():

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

Возвращает Document, представляющий string. Этот метод создаёт для строки объект io.StringIO и передаёт его в parse().

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

Функции parse() и parseString() соединяют XML-парсер с «построителем DOM», который принимает события разбора от любого парсера SAX и преобразует их в дерево DOM. Названия функций могут вводить в заблуждение, однако при изучении интерфейсов их легко понять. Разбор документа завершается до возврата из этих функций; просто сами функции не предоставляют реализацию парсера.

Можно также создать Document, вызвав метод объекта «реализации DOM». Получить этот объект можно, вызвав функцию getDOMImplementation() из пакета xml.dom или модуля xml.dom.minidom. Получив Document, можно добавить к нему дочерние узлы, чтобы заполнить DOM:

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-документа — тому, который содержит все остальные элементы. Пример программы:

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

Закончив работу с деревом DOM, можно по желанию вызвать метод unlink(), чтобы ускорить очистку ставших ненужными объектов. unlink() — специфичное для xml.dom.minidom расширение API DOM, которое фактически делает узел и его потомков непригодными для использования. В противном случае сборщик мусора Python в конечном итоге освободит объекты дерева.

См. также

Спецификация объектной модели документа (DOM) уровня 1

Рекомендация W3C для DOM, поддерживаемого xml.dom.minidom.

Объекты DOM

Определение API DOM для Python приведено в документации модуля xml.dom. В этом разделе перечислены различия между API и xml.dom.minidom.

Node.unlink()

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

Чтобы не вызывать этот метод явно, можно воспользоваться инструкцией with. Следующий код автоматически выполнит unlink для dom при выходе из блока with:

with xml.dom.minidom.parse(datasource) as dom:
    ... # Work with dom.
Node.writexml(writer, indent='', addindent='', newl='', encoding=None, standalone=None)

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

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

Аналогично, явное указание аргумента standalone добавляет объявление standalone-документа в пролог XML-документа. Если значение равно True, добавляется standalone="yes", в противном случае устанавливается "no". Если аргумент не указан, объявление не включается в документ.

Изменено в версии 3.8: Метод writexml() теперь сохраняет заданный пользователем порядок атрибутов.

Изменено в версии 3.9: Добавлен параметр standalone.

Node.toxml(encoding=None, standalone=None)

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

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

Аргумент standalone работает точно так же, как в методе writexml().

Изменено в версии 3.8: Метод toxml() теперь сохраняет заданный пользователем порядок атрибутов.

Изменено в версии 3.9: Добавлен параметр standalone.

Node.toprettyxml(indent='\t', newl='\n', encoding=None, standalone=None)

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

Аргумент encoding работает так же, как соответствующий аргумент toxml().

Аргумент standalone работает точно так же, как в методе writexml().

Изменено в версии 3.8: Метод toprettyxml() теперь сохраняет заданный пользователем порядок атрибутов.

Изменено в версии 3.9: Добавлен параметр standalone.

Пример DOM

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

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(f"<title>{getText(title.childNodes)}</title>")

def handleSlideTitle(title):
    print(f"<h2>{getText(title.childNodes)}</h2>")

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

def handlePoint(point):
    print(f"<li>{getText(point.childNodes)}</li>")

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

handleSlideshow(dom)

minidom и стандарт DOM

Модуль xml.dom.minidom по сути представляет собой совместимую с DOM 1.0 DOM-реализацию с некоторыми возможностями DOM 2 (главным образом, возможностями работы с пространствами имён).

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

  • Доступ к интерфейсам осуществляется через объекты экземпляров. Приложениям не следует создавать экземпляры классов самостоятельно; вместо этого следует использовать функции создания, доступные в объекте Document. Производные интерфейсы поддерживают все операции (и атрибуты) базовых интерфейсов, а также новые операции.
  • Операции используются как методы. Поскольку DOM использует только параметры 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 поддерживает байты и строки, но обычно создаёт строки. Значения типа DOMString также могут быть None, если спецификация DOM W3C допускает для них значение IDL null.
  • Объявления const соответствуют переменным в соответствующей области видимости (например, xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE); изменять их нельзя.
  • В настоящее время DOMException не поддерживается в xml.dom.minidom. Вместо этого xml.dom.minidom использует стандартные исключения Python, например TypeError и AttributeError.
  • Объекты NodeList реализованы с использованием встроенного типа list в Python. Эти объекты предоставляют интерфейс, определённый спецификацией DOM, но в более ранних версиях Python они не поддерживают официальный API. При этом они гораздо более «питоничны», чем интерфейс, определённый в рекомендациях W3C.

Следующие интерфейсы не реализованы в xml.dom.minidom:

  • DOMTimeStamp
  • EntityReference

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

Сноски

[1]

Название кодировки, включаемое в вывод XML, должно соответствовать применимым стандартам. Например, «UTF-8» — допустимое название, а «UTF8» недопустимо в объявлении XML-документа, хотя Python принимает его как название кодировки. См. https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl и https://www.iana.org/assignments/character-sets/character-sets.xhtml.

© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/xml.dom.minidom.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API