Содержание страницы
19.8. xml.dom.minidom – минимальная реализация DOM¶xml.dom.minidom – Minimal DOM implementation
Исходный код: Lib/xml/dom/minidom.py
xml.dom.minidom – это минимальная реализация интерфейса Document Object Model с API, похожим на API в других языках. Он задуман как более простой, чем полный DOM, и значительно меньше. Пользователям, которые ещё не знакомы с DOM, следует рассмотреть использование модуля xml.etree.ElementTree для обработки XML вместо этого.
Предупреждение
Модуль xml.dom.minidom не является безопасным для злонамеренно сконструированных данных. Если требуется обрабатывать ненадёжные или неаутентифицированные данные, см. XML vulnerabilities.
Приложения 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=None, bufsize=None)¶
Возвращает Document из переданных данных. filename_or_file может быть как именем файла, так и объектом, похожим на файл. parser, если задан, должен быть объектом парсера SAX2. Эта функция изменит обработчик документа парсера и активирует поддержку пространств имён; другие настройки парсера (например, установка резолвера сущностей) должны быть выполнены заранее.
Если XML находится в строке, можно использовать функцию parseString() вместо этого:
- xml.dom.minidom.parseString(string, parser=None)¶
Возвращает объект Document, представляющий строку. Этот метод создаёт объект 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() является расширением DOM API, специфичным для xml.dom.minidom, которое делает узел и его потомков по сути бесполезными. В противном случае сборщик мусора Python в конечном итоге позаботится об объектах в дереве.
См. также
- Спецификация объектной модели документа (DOM) уровня 1
- Рекомендация W3C для DOM, поддерживаемая xml.dom.minidom.
19.8.1. Объекты DOM¶DOM Objects
Определение DOM API для Python приведено в документации модуля xml.dom. В этом разделе перечислены различия между этим API и xml.dom.minidom.
- Node.unlink()¶
Разрывает внутренние ссылки в DOM, чтобы дерево могло быть собрано сборщиком мусора в версиях Python без циклического GC. Даже когда циклический GC доступен, его использование может освободить большие объёмы памяти раньше, поэтому вызов этого метода на DOM-объектах, как только они больше не нужны, является хорошей практикой. Этот метод нужно вызывать только на объекте Document, но можно вызывать и на дочерних узлах, чтобы удалить их потомков.
Можно избежать явного вызова этого метода, используя оператор with. Следующий код автоматически вызовет unlink для dom при выходе из блока with:
with xml.dom.minidom.parse(datasource) as dom: ... # Работать с DOM.
- Node.writexml(writer, indent="", addindent="", newl="")¶
Записывает XML в объект writer. Writer должен иметь метод write(), соответствующий интерфейсу файлового объекта. Параметр indent задаёт отступ текущего узла. Параметр addindent задаёт дополнительный отступ для подузлов текущего узла. Параметр newl задаёт строку, используемую для завершения строк.
Для узла Document можно использовать дополнительный именованный аргумент encoding для указания поля кодировки в заголовке XML.
- Node.toxml(encoding=None)¶
Возвращает строку или байтовую строку, содержащую XML, представленный узлом DOM.
При явном указании аргумента encoding [1] результатом будет байтовая строка в указанной кодировке. Рекомендуется всегда указывать кодировку; можно использовать любую, но аргумент «utf-8» – самый распространённый выбор, позволяющий избежать исключений UnicodeError при наличии непредставимых текстовых данных.
Без аргумента encoding результатом будет строка Unicode, и XML-объявление в результирующей строке не указывает кодировку. Кодирование этой строки в кодировке, отличной от UTF-8, скорее всего, некорректно, так как UTF-8 является кодировкой XML по умолчанию.
- Node.toprettyxml(indent="", newl="", encoding="")¶
Возвращает красиво отформатированную версию документа. indent задаёт строку отступа; по умолчанию это табуляция. newl задаёт строку, добавляемую в конце каждой строки; по умолчанию это \n.
Аргумент encoding ведёт себя так же, как соответствующий аргумент функции toxml().
19.8.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.8.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 поддерживает как байтовые строки, так и обычные строки, но обычно возвращает строки. Значения типа 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 реализованы с использованием встроенного типа списка Python. Эти объекты предоставляют интерфейс, определённый в спецификации DOM, но в более ранних версиях Python они не поддерживают официальный API. Однако они гораздо более «питоновские», чем интерфейс, определённый в рекомендациях W3C.
Следующие интерфейсы не имеют реализации в xml.dom.minidom:
- DOMTimeStamp
- DocumentType
- DOMImplementation
- CharacterData
- CDATASection
- Notation
- Entity
- EntityReference
- DocumentFragment
Большинство из них отражают информацию в XML-документе, которая не представляет общей ценности для большинства пользователей DOM.
Сноски
| [1] | Имя кодировки, указываемое в XML-выводе, должно соответствовать соответствующим стандартам. Например, «UTF-8» допустимо, но «UTF8» недопустимо в объявлении XML-документа, хотя Python принимает его как имя кодировки. См. http://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl и http://www.iana.org/assignments/character-sets. |