# `xml.dom.minidom` — Minimal DOM implementation

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

`xml.dom.minidom` is a minimal implementation of the Document Object Model interface, with an API similar to that in other languages. It is intended to be simpler than the full DOM and also significantly smaller. Users who are not already proficient with the DOM should consider using the `xml.etree.ElementTree` module for their XML processing instead.

Примітка

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

DOM applications typically start by parsing some XML into a DOM. With `xml.dom.minidom`, this is done through the parse functions:

    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`, що представляє вміст документа.

What the `parse()` and `parseString()` functions do is connect an XML parser with a «DOM builder» that can accept parse events from any SAX parser and convert them into a DOM tree. The names of the functions are perhaps misleading, but are easy to grasp when learning the interfaces. The parsing of the document will be completed before these functions return; it’s simply that these functions do not provide a parser implementation themselves.

You can also create a `Document` by calling a method on a «DOM Implementation» object. You can get this object either by calling the `getDOMImplementation()` function in the `xml.dom` package or the `xml.dom.minidom` module. Once you have a `Document`, you can add child nodes to it to populate the 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)

  The W3C recommendation for the DOM supported by `xml.dom.minidom`.

## Об’єкти DOM

The definition of the DOM API for Python is given as part of the `xml.dom` module documentation. This section lists the differences between the API and `xml.dom.minidom`.

Node.unlink()

  Розбийте внутрішні посилання в 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

The `xml.dom.minidom` module is essentially a DOM 1.0-compatible DOM with some DOM 2 features (primarily namespace features).

Використання інтерфейсу 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.

- The type `DOMString` maps to Python strings. `xml.dom.minidom` supports either bytes or strings, but will normally produce strings. Values of type `DOMString` may also be `None` where allowed to have the IDL `null` value by the DOM specification from the W3C.

- Оголошення `const` відображаються на змінні у відповідній області (наприклад, `xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE`); їх не можна змінювати.

- `DOMException` is currently not supported in `xml.dom.minidom`. Instead, `xml.dom.minidom` uses standard Python exceptions such as `TypeError` and `AttributeError`.

- Об’єкти `NodeList` реалізовані за допомогою вбудованого типу списку Python. Ці об’єкти забезпечують інтерфейс, визначений у специфікації DOM, але в попередніх версіях Python вони не підтримують офіційний API. Однак вони набагато більш «пітонічні», ніж інтерфейс, визначений у рекомендаціях W3C.

The following interfaces have no implementation in `xml.dom.minidom`:

- `DOMTimeStamp`

- `EntityReference`

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

Виноски

[1]

Ім’я кодування, включене у вивід XML, має відповідати відповідним стандартам. Наприклад, «UTF-8» є дійсним, але «UTF8» не є дійсним в декларації документа XML, навіть якщо Python приймає його як назву кодування. Див. https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl і https://www.iana.org/assignments/character-sets/character-sets.xhtml.