xml.dom.minidom — Minimal DOM implementation

Вихідний код: Lib/xml/dom/minidom.py


xml.dom.minidom — це мінімальна реалізація інтерфейсу об’єктної моделі документа з API, подібним до того, що є в інших мовах. Він має бути простішим, ніж повний DOM, а також значно меншим. Користувачам, які ще не володіють DOM, варто розглянути можливість використання модуля xml.etree.ElementTree для обробки XML.

Примітка

If you need to parse untrusted or unauthenticated data, see XML security.

Програми 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, ви можете отримати доступ до частин свого документа XML через його властивості та методи. Ці властивості визначені в специфікації DOM. Основною властивістю об’єкта документа є властивість documentElement. Це дає вам головний елемент у документі XML: той, який містить усі інші. Ось приклад програми:

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

When you are finished with a DOM tree, you may optionally call the unlink() method to encourage early cleanup of the now-unneeded objects. unlink() is an xml.dom.minidom-specific extension to the DOM API that renders the node and its descendants essentially useless. Otherwise, Python’s garbage collector will eventually take care of the objects in the tree.

Дивись також

Специфікація рівня 1 об’єктної моделі документа (DOM)

Рекомендація W3C щодо DOM, що підтримується xml.dom.minidom.

Об’єкти DOM

Визначення DOM API для Python надається як частина документації модуля xml.dom. У цьому розділі наведено відмінності між API та xml.dom.minidom.

Розбийте внутрішні посилання в DOM, щоб у версіях Python без циклічного збирання сміття було зібрано сміття. Навіть якщо циклічний 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 в об’єкт запису. Записувач отримує тексти, але не байти як вхідні дані, він повинен мати метод write(), який відповідає методу інтерфейсу файлового об’єкта. Параметр indent — це відступ поточного вузла. Параметр addindent є поступовим відступом для використання підвузлів поточного. Параметр newl визначає рядок, який використовуватиметься для завершення символів нового рядка.

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

Similarly, explicitly stating the standalone argument causes the standalone document declarations to be added to the prologue of the XML document. If the value is set to True, standalone="yes" is added, otherwise it is set to "no". Not stating the argument will omit the declaration from the document.

Змінено в версії 3.8: Метод writexml() тепер зберігає порядок атрибутів, указаний користувачем.

Змінено в версії 3.9: Додано параметр standalone.

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

Повертає рядок або рядок байтів, що містить XML, представлений вузлом DOM.

З явним аргументом encoding [1] результатом буде рядок байтів у вказаному кодуванні. Без аргументу encoding результатом є рядок Unicode, а оголошення 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-сумісним 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. Ці об’єкти забезпечують інтерфейс, визначений у специфікації DOM, але в попередніх версіях Python вони не підтримують офіційний API. Однак вони набагато більш «пітонічні», ніж інтерфейс, визначений у рекомендаціях W3C.

Наступні інтерфейси не мають реалізації в xml.dom.minidom:

  • DOMTimeStamp

  • EntityReference

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

Виноски