xml.dom.minidom
— Минимальная реализация DOM¶
Источник: Lib/xml/dom/minidom.py
xml.dom.minidom
- это минимальная реализация интерфейса Document Object Model, с 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') # 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_или_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 Implementation». Этот объект можно получить, вызвав функцию 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 в конце концов позаботится об объектах в дереве.
См.также
- Document Object Model (DOM) Level 1 Specification
Рекомендация W3C для DOM, поддерживаемая
xml.dom.minidom
.
Объекты DOM¶
Определение DOM API для Python дано в документации к модулю xml.dom
. В этом разделе перечислены различия между API и xml.dom.minidom
.
- Node.unlink()¶
Разбивает внутренние ссылки внутри 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='', encoding=None, standalone=None)¶
Запись XML в объект writer. Объект writer принимает на вход тексты, но не байты, у него должен быть метод
write()
, соответствующий методу интерфейса объекта file. Параметр indent - это отступ текущего узла. Параметр addindent - это дополнительный отступ, который следует использовать для подузлов текущего узла. Параметр newl задает строку для завершения новых строк.Для узла
Document
можно использовать дополнительный ключевой аргумент encoding, чтобы указать поле кодировки в заголовке XML.Аналогично, явное указание аргумента standalone приводит к тому, что объявления отдельного документа добавляются в пролог 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¶
Этот пример программы представляет собой достаточно реалистичный пример простой программы. В данном конкретном случае мы не используем все преимущества гибкости 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 разрешает им иметь значение IDLnull
.Объявления
const
отображаются на переменные в соответствующей области видимости (например,xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE
); их нельзя изменять.В настоящее время
DOMException
не поддерживается вxml.dom.minidom
. Вместо этого вxml.dom.minidom
используются стандартные исключения Python, такие какTypeError
иAttributeError
.Объекты
NodeList
реализуются с помощью встроенного в Python типа списка. Эти объекты предоставляют интерфейс, определенный в спецификации DOM, но в ранних версиях Python они не поддерживают официальный API. Тем не менее, они гораздо более «питоновские», чем интерфейс, определенный в рекомендациях W3C.
Следующие интерфейсы не имеют реализации в xml.dom.minidom
:
DOMTimeStamp
EntityReference
Большинство из них отражают информацию в XML-документе, которая не является общеполезной для большинства пользователей DOM.
Сноски