Содержание страницы
19.9. xml.dom.minidom – Минимальная реализация DOM¶xml.dom.minidom – Minimal DOM implementation
Новое в версии 2.0.
Исходный код: Lib/xml/dom/minidom.py
xml.dom.minidom – это минимальная реализация интерфейса Document Object
Model с API, похожим на API в других языках. Она призвана быть проще, чем полный DOM, и значительно меньше. Пользователям, которые ещё недостаточно знакомы с DOM, стоит рассмотреть использование модуля
xml.etree.ElementTree для обработки XML.
Предупреждение
Модуль xml.dom.minidom не защищён от вредоносных данных. Если нужно разобрать непроверенные или неаутентифицированные данные, см. уязвимости XML.
Приложения, работающие с DOM, обычно начинают с разбора XML в DOM. С
xml.dom.minidom это делается с помощью функций parse:
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[, bufsize]])¶ Возвращает
Documentиз переданных входных данных. filename_or_file может быть либо именем файла, либо объектом, похожим на файл. parser, если указан, должен быть объектом парсера SAX2. Эта функция изменит обработчик документа парсера и включит поддержку пространств имён; остальные настройки парсера (например, установка обработчика сущностей) должны быть выполнены заранее.
Если XML находится в строке, можно использовать функцию parseString()
вместо этого:
-
xml.dom.minidom.parseString(string[, parser])¶ Возвращает объект
Document, представляющий строку. Этот метод создаёт объектStringIOдля строки и передаёт его вparse().
Обе функции возвращают объект Document, представляющий содержимое документа.
Функции parse() и parseString() связывают XML
парсер с «DOM-построителем», который может принимать события разбора от любого SAX-парсера и
преобразовывать их в DOM-дерево. Названия функций, возможно, вводят в заблуждение,
но их легко понять при изучении интерфейсов. Разбор документа
завершится до того, как эти функции вернут управление; просто эти
функции сами не предоставляют реализацию парсера.
Также можно создать объект Document, вызвав метод у объекта «DOM Implementation». Этот объект можно получить, вызвав функцию getDOMImplementation() в пакете xml.dom или модуле xml.dom.minidom. Использование реализации из модуля xml.dom.minidom всегда возвращает экземпляр Document из реализации minidom, тогда как версия из xml.dom может предоставить альтернативную реализацию (это вероятно, если установлен пакет PyXML). Получив объект 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.
19.9.1. Объекты DOM¶DOM Objects
Определение DOM API для Python даётся как часть документации модуля xml.dom.
В этом разделе перечислены отличия между API и xml.dom.minidom.
-
Node.unlink()¶ Разрывает внутренние ссылки внутри DOM, чтобы он мог быть собран сборщиком мусора на версиях Python без циклического GC. Даже если циклический GC доступен, использование этого метода может освободить большие объёмы памяти раньше, поэтому вызов его для DOM-объектов, как только они больше не нужны, является хорошей практикой. Этот метод нужно вызывать только для объекта
Document, но его можно вызывать и для дочерних узлов, чтобы удалить потомков этого узла.
-
Node.writexml(writer, indent="", addindent="", newl="")¶ Записывает XML в объект writer. Объект writer должен иметь метод
write(), который соответствует интерфейсу файлового объекта. Параметр indent задаёт отступ текущего узла. Параметр addindent – дополнительный отступ для дочерних узлов текущего. Параметр newl определяет строку, используемую для завершения строк.Для узла
Documentможно использовать дополнительный именованный аргумент encoding для указания поля кодировки в заголовке XML.Изменено в версии 2.1: Были добавлены необязательные именованные параметры indent, addindent и newl для поддержки форматированного вывода.
Изменено в версии 2.3: Для узла
Documentможно использовать дополнительный именованный аргумент encoding, чтобы указать поле кодировки в заголовке XML.
-
Node.toxml([encoding])¶ Возвращает XML-представление DOM в виде строки.
Если аргументы не переданы, заголовок XML не указывает кодировку, и результатом будет строка Unicode, если кодировка по умолчанию не может представить все символы документа. Кодирование этой строки в кодировке, отличной от UTF-8, скорее всего, некорректно, поскольку UTF-8 – это кодировка XML по умолчанию.
При явном указании encoding 1 аргумента результатом является байтовая строка в указанной кодировке. Рекомендуется всегда указывать этот аргумент. Чтобы избежать исключений
UnicodeErrorв случае непредставимых текстовых данных, аргумент encoding следует указывать как «utf-8».Изменено в версии 2.3: добавлен аргумент encoding; см.
writexml().
-
Node.toprettyxml(indent="\t", newl="\n", encoding=None)¶ Возвращает версию документа с красивым форматированием. indent задаёт строку отступа, по умолчанию – символ табуляции; newl задаёт строку, добавляемую в конце каждой строки, по умолчанию
\n.Новое в версии 2.1.
Изменено в версии 2.3: добавлен аргумент encoding; см.
writexml().
Следующие стандартные методы DOM имеют особенности при работе с xml.dom.minidom:
-
Node.cloneNode(deep)¶ Хотя этот метод присутствовал в версии
xml.dom.minidom, поставляемой с Python 2.0, он был серьёзно сломан. Это было исправлено в последующих выпусках.
19.9.2. Пример DOM¶DOM Example
Эта примерная программа – довольно реалистичный пример простой программы. В данном конкретном случае мы не используем гибкость 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)
19.9.3. minidom и стандарт DOM¶minidom and the DOM standard
Модуль 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поддерживает как байтовые, так и строки Unicode, но обычно создаёт строки Unicode. Значения типаDOMStringтакже могут бытьNone, если это допускается спецификацией DOM от W3C для значений IDLnull.Объявления
constотображаются на переменные в соответствующей области видимости (например,xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE); они не должны изменяться.DOMExceptionв настоящее время не поддерживается вxml.dom.minidom. Вместо этогоxml.dom.minidomиспользует стандартные исключения Python, такие какTypeErrorиAttributeError.Объекты
NodeListреализованы с использованием встроенного типа list Python. Начиная с Python 2.2, эти объекты предоставляют интерфейс, определённый в спецификации DOM, но в более ранних версиях Python они не поддерживают официальный API. Однако они гораздо более «Pythonic», чем интерфейс, определённый в рекомендациях W3C.
Следующие интерфейсы не имеют реализации в xml.dom.minidom:
DOMTimeStampDocumentType(добавлено в Python 2.1)DOMImplementation(добавлено в Python 2.1)CharacterDataCDATASectionNotationEntityEntityReferenceDocumentFragment
Большинство из них отражают информацию в XML-документе, которая не представляет общей ценности для большинства пользователей DOM.
Сноски
- 1
Строка кодировки, указанная в XML-выводе, должна соответствовать соответствующим стандартам. Например, «UTF-8» допустимо, а «UTF8» – нет. См. https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl и https://www.iana.org/assignments/character-sets/character-sets.xhtml.