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

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


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

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

Модуль xml.dom.minidom не защищен от вредоносных данных. Если вам нужно проанализировать данные, которым нельзя доверять или которые не прошли проверку подлинности, обратитесь к Важно отметить, что для модулей в пакете требуется, чтобы был доступен хотя бы один синтаксический анализатор XML, совместимый с SAX. Синтаксический анализатор Expat включен в состав Python, поэтому модуль всегда будет доступен..

Приложения 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, представляющее строку *. Этот метод создает объект 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 document, вы можете получить доступ к частям вашего XML-документа через его свойства и методы. Эти свойства определены в спецификации DOM. Основным свойством объекта document является свойство documentElement. Это дает вам основной элемент в XML-документе: тот, который содержит все остальные. Вот пример программы:

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

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

См.также

Document Object Model (DOM) Level 1 Specification

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

Объекты DOM

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

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

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

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

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

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

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

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

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

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

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

При явном аргументе encoding [1] результатом будет строка байтов в указанной кодировке. При отсутствии аргумента encoding результатом будет строка в Юникоде, а 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

Этот пример программы является довольно реалистичным примером простой программы. В данном конкретном случае мы не слишком пользуемся гибкостью ПРЕДМЕТНОЙ области.

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, совместимым с DOM 1.0, с некоторыми функциями 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, где разрешено иметь значение IDL null в соответствии со спецификацией DOM из W3C.

  • const объявления соответствуют переменным в их соответствующей области видимости (например, xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE); их нельзя изменять.

  • DOMException в настоящее время не поддерживается в xml.dom.minidom. Вместо этого в xml.dom.minidom используются стандартные исключения Python, такие как TypeError и AttributeError.

  • NodeList объекты реализованы с использованием встроенного в Python типа list. Эти объекты предоставляют интерфейс, определенный в спецификации DOM, но в более ранних версиях Python они не поддерживают официальный API. Однако они гораздо более «питонические», чем интерфейс, определенный в рекомендациях W3C.

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

  • DOMTimeStamp

  • EntityReference

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

Сноски

Вернуться на верх