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

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


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

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

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

Приложения DOM обычно начинаются с парсинг некоторых XML в DOM. С помощью xml.dom.minidom это выполняется через функции парсинга:

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() может принимать либо имя файла, либо открытый файловый объект.

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 расширение DOM API, которое делает узел и его потомки по существу бесполезными. В противном случае сборщик мусора Python’а конечном итоге позаботится об объектах в дереве.

См.также

Спецификация объектной модели документа (DOM) уровня 1
Рекомендация W3C для поддержки DOM xml.dom.minidom.

Объекты DOM

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

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

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

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

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

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

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

Node.toxml(encoding=None)

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

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

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

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

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

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

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

Пример 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("<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)

minidom и стандарт DOM

Модуль xml.dom.minidom по существу является DOM 1.0-совместимым DOM с некоторыми функциями DOM 2 (в основном функциями пространства имен).

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

  • Доступ к интерфейсам осуществляется через сущность объекты. Приложения не должны создавать экземпляры самих классов; они должны использовать функции создателя, доступные на объекте Document. Производные интерфейсы поддерживают все операции (и атрибуты) из базовых интерфейсов, а также любые новые операции.
  • Операции используемый как методы. Поскольку DOM использует только in параметры, аргументы передаются в обычном порядке (слева направо). Необязательные аргументы отсутствуют. void операции возвращает None.
  • IDL атрибуты сопоставить с сущность атрибуты. Для совместимости с сопоставлением языка IDL OMG для Python доступ к атрибут foo также можно получить с помощью методов доступа _get_foo() и _set_foo(). readonly атрибуты не должны изменяться; это не применяется во время выполнения.
  • Типы short int, unsigned int, unsigned long long и boolean все отображения к целочисленным объектам Python.
  • Тип DOMString сопоставляется с Python строки. xml.dom.minidom поддерживает байты или строки, но обычно создает строки. Ценности типа DOMString могут также быть None, где позволено иметь IDL null значение спецификацией DOM от W3C.
  • const объявления соответствуют переменным в их соответствующих область видимости (например, xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE); они не должны быть изменены.
  • DOMException настоящее время не поддерживается в xml.dom.minidom. Вместо этого xml.dom.minidom использует стандартные исключения Python, такие как TypeError и AttributeError.
  • Объекты NodeList осуществлены, используя Python встроенный тип списка. Эти объекты обеспечивают интерфейс, определенный в спецификации DOM, но в более ранних версиях Python они не поддерживают официальный API. Они, однако, гораздо более «Pythonic», чем интерфейс, определенный в рекомендациях 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.