Spec-Zone.ru › Python 3.12

xml.etree.ElementTree — API XML ElementTree

Исходный код: Lib/xml/etree/ElementTree.py

Модуль xml.etree.ElementTree реализует простой и эффективный API для разбора и создания XML-данных.

Изменено в версии 3.3: Этот модуль будет использовать быструю реализацию, когда она доступна.

Устаревшее с версии 3.3: Модуль xml.etree.cElementTree устарел.

Предупреждение

Модуль xml.etree.ElementTree не защищён от данных, злонамеренно сконструированных. Если вам нужно проанализировать недоверенные или неавторизованные данные, см. Уязвимости XML.

Учебник

Это краткий учебник по использованию xml.etree.ElementTree (ET коротко). Цель – продемонстрировать некоторые строительные блоки и основные концепции модуля.

Дерево XML и элементы

XML – это по своей природе иерархический формат данных, и самый естественный способ его представления – дерево. ET имеет два класса для этой цели – ElementTree представляет весь документ XML как дерево, а Element представляет собой отдельный узел в этом дереве. Взаимодействие с целым документом (чтение и запись в/из файлов) обычно выполняется на уровне ElementTree. Взаимодействие с отдельным элементом XML и его дочерними элементами выполняется на уровне Element.

Парсинг XML

Мы будем использовать вымышленный country_data.xml документ XML в качестве образца данных для этого раздела:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank>1</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank>4</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank>68</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

Мы можем импортировать эти данные, читая из файла:

import xml.etree.ElementTree as ET
tree = ET.parse('country_data.xml')
root = tree.getroot()

Или напрямую из строки:

root = ET.fromstring(country_data_as_string)

fromstring() парсит XML из строки напрямую в Element, который является корневым элементом проанализированного дерева. Другие функции парсинга могут создать ElementTree. Убедитесь в этом по документации.

Как Element, root имеет тег и словарь атрибутов:

>>> root.tag
'data'
>>> root.attrib
{}

Он также имеет дочерние узлы, по которым мы можем перебирать:

>>> for child in root:
...     print(child.tag, child.attrib)
...
country {'name': 'Liechtenstein'}
country {'name': 'Singapore'}
country {'name': 'Panama'}

Дочерние элементы вложены, и мы можем получить доступ к определённым дочерним элементам по индексу:

>>> root[0][1].text
'2008'

Примечание

Не все элементы входного XML окажутся элементами проанализированного дерева. В настоящее время этот модуль пропускает все XML-комментарии, инструкции обработки и объявления типов документов во входных данных. Тем не менее, деревья, построенные с помощью API этого модуля, а не парсинга из текста XML, могут содержать комментарии и инструкции обработки; они будут включены при генерации XML-вывода. Объявление типа документа можно получить, передав экземпляр пользовательского TreeBuilder конструктору XMLParser.

Pull-API для неблокирующего парсинга

Большинство функций парсинга, предоставляемых этим модулем, требуют, чтобы весь документ был прочитан сразу перед возвратом любого результата. Можно использовать XMLParser и по частям подавать данные в него, но это API "push", который вызывает методы целевого обратного вызова, что слишком низкоуровнево и неудобно для большинства нужд. Иногда пользователь на самом деле хочет иметь возможность по частям анализировать XML без блокирующих операций, при этом наслаждаясь удобством полностью сконструированных Element объектов.

Самый мощный инструмент для этого – XMLPullParser. Он не требует блокирующего чтения для получения данных XML и вместо этого получает данные по частям с помощью вызовов XMLPullParser.feed(). Чтобы получить проанализированные XML-элементы, вызовите XMLPullParser.read_events(). Вот пример:

>>> parser = ET.XMLPullParser(['start', 'end'])
>>> parser.feed('<mytag>sometext')
>>> list(parser.read_events())
[('start', <Element 'mytag' at 0x7fa66db2be58>)]
>>> parser.feed(' more text</mytag>')
>>> for event, elem in parser.read_events():
...     print(event)
...     print(elem.tag, 'text=', elem.text)
...
end
mytag text= sometext more text

Очевидным случаем использования является приложения, работающие в режиме, не требующем блокировки, где данные XML поступают из сокета или читаются по частям с какого-либо устройства хранения. В таких случаях блокирующие чтения неприемлемы.

Поскольку он настолько гибкий, XMLPullParser может быть неудобным для использования в простых случаях. Если вам не мешает блокировка вашего приложения при чтении данных XML, но вы всё ещё хотите иметь возможность по частям анализировать данные, взгляните на iterparse(). Это может быть полезно при чтении большого XML-документа, не желая загружать весь его в память.

Там, где требуется немедленная обратная связь через события, вызов метода XMLPullParser.flush() может помочь уменьшить задержку; убедитесь, что вы изучили соответствующие заметки по безопасности.

Поиск интересных элементов

Element имеет несколько полезных методов, которые помогают рекурсивно перебирать все поддеревья под ним (его потомки, их потомки и так далее). Например, Element.iter():

>>> for neighbor in root.iter('neighbor'):
...     print(neighbor.attrib)
...
{'name': 'Austria', 'direction': 'E'}
{'name': 'Switzerland', 'direction': 'W'}
{'name': 'Malaysia', 'direction': 'N'}
{'name': 'Costa Rica', 'direction': 'W'}
{'name': 'Colombia', 'direction': 'E'}

Element.findall() находит только элементы с тегом, которые являются непосредственными потомками текущего элемента. Element.find() находит первый элемент с определённым тегом, а Element.text получает текстовое содержимое элемента. Element.get() получает атрибуты элемента:

>>> for country in root.findall('country'):
...     rank = country.find('rank').text
...     name = country.get('name')
...     print(name, rank)
...
Liechtenstein 1
Singapore 4
Panama 68

Более сложные правила выбора элементов можно задать с помощью XPath.

Изменение XML-файла

ElementTree предоставляет простой способ построения XML-документов и записи их в файлы. Метод ElementTree.write() служит для этой цели.

После создания объект Element можно изменить, непосредственно изменив его поля (например, Element.text), добавив и изменив атрибуты (метод Element.set()), а также добавив новые дочерние элементы (например, с помощью Element.append()).

Предположим, что мы хотим добавить по одному к рейтингу каждой страны и добавить атрибут updated к элементу рейтинга:

>>> for rank in root.iter('rank'):
...     new_rank = int(rank.text) + 1
...     rank.text = str(new_rank)
...     rank.set('updated', 'yes')
...
>>> tree.write('output.xml')

Наш XML теперь выглядит так:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

Мы можем удалить элементы с помощью Element.remove(). Предположим, что мы хотим удалить все страны с рейтингом выше 50:

>>> for country in root.findall('country'):
...     # using root.findall() to avoid removal during traversal
...     rank = int(country.find('rank').text)
...     if rank > 50:
...         root.remove(country)
...
>>> tree.write('output.xml')

Обратите внимание, что одновременное изменение во время итерирования может привести к проблемам, как и при итерировании и изменении списков или словарей Python. Поэтому в примере сначала собираются все соответствующие элементы с root.findall(), а затем итерируется по списку совпадений.

Наш XML теперь выглядит так:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
</data>

Создание XML-документов

Функция SubElement() также предоставляет удобный способ создания новых дочерних элементов для данного элемента:

>>> a = ET.Element('a')
>>> b = ET.SubElement(a, 'b')
>>> c = ET.SubElement(a, 'c')
>>> d = ET.SubElement(c, 'd')
>>> ET.dump(a)
<a><b /><c><d /></c></a>

Парсинг XML с именованными пространствами

Если входной XML имеет именованные пространства, теги и атрибуты с префиксами в форме prefix:sometag расширяются до {uri}sometag где префикс заменяется полным URI. Кроме того, если существует пространство имён по умолчанию, это полное URI добавляется в начало всех тегов без префиксов.

Вот пример XML, который включает два именованных пространства, одно с префиксом «fictional», а другое служит пространством имён по умолчанию:

<?xml version="1.0"?>
<actors xmlns:fictional="http://characters.example.com"
        xmlns="http://people.example.com">
    <actor>
        <name>John Cleese</name>
        <fictional:character>Lancelot</fictional:character>
        <fictional:character>Archie Leach</fictional:character>
    </actor>
    <actor>
        <name>Eric Idle</name>
        <fictional:character>Sir Robin</fictional:character>
        <fictional:character>Gunther</fictional:character>
        <fictional:character>Commander Clement</fictional:character>
    </actor>
</actors>

Один из способов поиска и просмотра этого примера XML – вручную добавить URI к каждому тегу или атрибуту в xpath функции find() или findall():

root = fromstring(xml_text)
for actor in root.findall('{http://people.example.com}actor'):
    name = actor.find('{http://people.example.com}name')
    print(name.text)
    for char in actor.findall('{http://characters.example.com}character'):
        print(' |-->', char.text)

Лучший способ поиска в именованном пространстве XML-примера – создать словарь со своими префиксами и использовать их в функциях поиска:

ns = {'real_person': 'http://people.example.com',
      'role': 'http://characters.example.com'}

for actor in root.findall('real_person:actor', ns):
    name = actor.find('real_person:name', ns)
    print(name.text)
    for char in actor.findall('role:character', ns):
        print(' |-->', char.text)

Эти два подхода оба выводят:

John Cleese
 |--> Lancelot
 |--> Archie Leach
Eric Idle
 |--> Sir Robin
 |--> Gunther
 |--> Commander Clement

Поддержка XPath

Этот модуль предоставляет ограниченную поддержку выражений XPath для поиска элементов в дереве. Цель — поддержать небольшой подмножество сокращённой синтаксической конструкции; полный движок XPath выходит за рамки возможностей модуля.

Пример

Вот пример, демонстрирующий некоторые возможности XPath модуля. Мы будем использовать countrydata XML-документ из раздела Разбор XML:

import xml.etree.ElementTree as ET

root = ET.fromstring(countrydata)

# Top-level elements
root.findall(".")

# All 'neighbor' grand-children of 'country' children of the top-level
# elements
root.findall("./country/neighbor")

# Nodes with name='Singapore' that have a 'year' child
root.findall(".//year/..[@name='Singapore']")

# 'year' nodes that are children of nodes with name='Singapore'
root.findall(".//*[@name='Singapore']/year")

# All 'neighbor' nodes that are the second child of their parent
root.findall(".//neighbor[2]")

Для XML с именованными пространствами используйте обычную нотацию {namespace}tag:

# All dublin-core "title" tags in the document
root.findall(".//{http://purl.org/dc/elements/1.1/}title")

Поддерживаемый синтаксис XPath

Синтаксис

Значение

tag

Выбирает все дочерние элементы с заданным тэгом. Например, spam выбирает все дочерние элементы с именем spam, а spam/egg выбирает всех внуков с именем egg среди всех детей с именем spam. {namespace}* выбирает все тэги в данном именованном пространстве, {*}spam выбирает тэги с именем spam в любом (или отсутствующем) именованном пространстве, а {}* выбирает только тэги, не находящиеся в именованном пространстве.

Изменено в версии 3.8: Добавлена поддержка звёздчатых подстановочных знаков.

*

Выбирает все дочерние элементы, включая комментарии и инструкции обработки. Например, */egg выбирает всех внуков с именем egg.

.

Выбирает текущий узел. Это в основном полезно в начале пути, чтобы указать, что это относительный путь.

//

Выбирает все подэлементы на всех уровнях под текущим элементом. Например, .//egg выбирает все элементы egg во всём дереве.

..

Выбирает родительский элемент. Возвращает None если путь пытается достичь предков начального элемента (элемента, на котором был вызван метод find).

[@attrib]

Выбирает все элементы, которые имеют заданный атрибут.

[@attrib='value']

Выбирает все элементы, для которых заданный атрибут имеет заданное значение. Значение не может содержать кавычки.

[@attrib!='value']

Выбирает все элементы, для которых заданный атрибут не имеет заданного значения. Значение не может содержать кавычки.

Добавлена в версии 3.10.

[tag]

Выбирает все элементы, которые имеют дочерний элемент с именем tag. Поддерживаются только непосредственные дочерние элементы.

[.='text']

Выбирает все элементы, полное текстовое содержимое которых, включая потомков, равно указанному text.

Добавлена в версии 3.7.

[.!='text']

Выбирает все элементы, полное текстовое содержимое которых, включая потомков, не равно указанному text.

Добавлена в версии 3.10.

[tag='text']

Выбирает все элементы, которые имеют дочерний элемент с именем tag , полное текстовое содержимое которого, включая потомков, равно указанному text.

[tag!='text']

Выбирает все элементы, которые имеют дочерний элемент с именем tag , полное текстовое содержимое которого, включая потомков, не равно указанному text.

Добавлена в версии 3.10.

[position]

Выбирает все элементы, находящиеся на заданной позиции. Позиция может быть целым числом (1 — первая позиция), выражением last() (для последней позиции) или позицией, относящейся к последней позиции (например, last()-1).

Предикаты (выражения в квадратных скобках) должны предшествовать имени тэга, звездочке или другому предикату. position предикаты должны предшествовать имени тэга.

Справочник

Функции

xml.etree.ElementTree.canonicalize(xml_data=None, *, out=None, from_file=None, **options)

Функция преобразования C14N 2.0.

Канонизация — это способ нормализации XML-вывода, который позволяет сравнивать байты по байтам и подписывать данные цифровой подписью. Она ограничивает свободу XML-сериализаторов, вместо этого генерируя более ограниченное представление XML. Основные ограничения касаются размещения объявлений пространства имён, порядка атрибутов и игнорируемого пробела.

Эта функция принимает на вход строку XML-данных (xml_data) или путь к файлу или файлоподобный объект (from_file), преобразует его в каноническую форму и записывает его в объект файла (out), если он предоставлен, или возвращает его как текстовую строку, если нет. Выходной файл получает текст, а не байты. Поэтому его следует открыть в текстовом режиме с кодировкой utf-8.

Типичные применения:

xml_data = "<root>...</root>"
print(canonicalize(xml_data))

with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file:
    canonicalize(xml_data, out=out_file)

with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file:
    canonicalize(from_file="inputfile.xml", out=out_file)

Настройки options следующие:

  • with_comments: устанавливается в значение true для включения комментариев (по умолчанию: false)
  • strip_text: устанавливается в значение true для удаления пробелов перед и после текстового содержимого

    (по умолчанию: false)

  • rewrite_prefixes: устанавливается в значение true для замены префиксов пространства имен на «n{number}»

    (по умолчанию: false)

  • qname_aware_tags: набор имен тэгов, в которых следует заменить префиксы в текстовом содержимом

    (по умолчанию: пустое)

  • qname_aware_attrs: набор имен атрибутов, в которых следует заменить префиксы в текстовом содержимом

    (по умолчанию: пустое)

  • exclude_attrs: набор имен атрибутов, которые не следует сериализовать
  • exclude_tags: набор имен тэгов, которые не следует сериализовать

В списке параметров выше «набор» относится к любой коллекции или итерируемому объекту строк, порядок не ожидается.

Добавлен в версии 3.8.

xml.etree.ElementTree.Comment(text=None)

Фабрика элементов комментариев. Эта фабричная функция создаёт специальный элемент, который стандартный сериализатор сериализует как XML-комментарий. Строка комментария может быть либо строкой байтов, либо строкой Юникода. text — строка, содержащая строку комментария. Возвращает экземпляр элемента, представляющий комментарий.

Обратите внимание, что XMLParser пропускает комментарии во входных данных вместо создания для них объектов комментариев. ElementTree будет содержать узлы комментариев только в том случае, если они были вставлены в дерево с помощью одного из методов Element.

xml.etree.ElementTree.dump(elem)

Записывает дерево элементов или структуру элементов в sys.stdout. Эту функцию следует использовать только для отладки.

Точный формат вывода зависит от реализации. В этой версии он записывается как обычный XML-файл.

elem — это дерево элементов или отдельный элемент.

Изменено в версии 3.8: Функция dump() теперь сохраняет порядок атрибутов, заданный пользователем.

xml.etree.ElementTree.fromstring(text, parser=None)

Парсит XML-раздел из строковой константы. То же самое, что и XML(). text — строка, содержащая XML-данные. parser — необязательный экземпляр парсера. Если он не задан, используется стандартный парсер XMLParser. Возвращает экземпляр Element.

xml.etree.ElementTree.fromstringlist(sequence, parser=None)

Парсит XML-документ из последовательности фрагментов строк. sequence — список или другая последовательность, содержащая фрагменты XML-данных. parser — необязательный экземпляр парсера. Если он не задан, используется стандартный парсер XMLParser. Возвращает экземпляр Element.

Добавлен в версии 3.2.

xml.etree.ElementTree.indent(tree, space=' ', level=0)

Добавляет пробелы к поддереву для визуального отступа дерева. Это можно использовать для создания красивого отформатированного XML-вывода. tree может быть элементом или деревом элементов. space — строка пробелов, которая будет вставляться для каждого уровня отступа, по умолчанию две пробельные символы. Для отступа частичных поддеревьев внутри уже отступающего дерева передайте начальный уровень отступа как level.

Добавлен в версии 3.9.

xml.etree.ElementTree.iselement(element)

Проверяет, является ли объект допустимым объектом элемента. element — экземпляр элемента. Возвращает True если это объект элемента.

xml.etree.ElementTree.iterparse(source, events=None, parser=None)

Инкрементально парсит XML-раздел в дерево элементов и сообщает пользователю о происходящем. source — имя файла или объект файла, содержащий XML-данные. events — последовательность событий, которые нужно сообщить обратно. Поддерживаемые события — это строки "start", "end", "comment", "pi", "start-ns" и "end-ns" (события «ns» используются для получения подробной информации о пространстве имён). Если events опущено, сообщаются только события "end". parser — необязательный экземпляр парсера. Если он не задан, используется стандартный парсер XMLParser. parser должен быть подклассом XMLParser и может использовать только целевой по умолчанию TreeBuilder. Возвращает итератор, предоставляющий пары (event, elem); у него есть атрибут root, который ссылается на корневой элемент результирующего XML-дерева после полного чтения source.

Обратите внимание, что, хотя iterparse() строит дерево инкрементально, он выполняет блокирующие чтения в source (или файле, который он называет). Таким образом, он не подходит для приложений, где блокирующие чтения не могут быть выполнены. Для полностью неблокирующего парсинга см. XMLPullParser.

Примечание

iterparse() гарантирует, что он видел символ «>» начального тэга, когда он излучает событие «start», поэтому атрибуты определены, но содержимое атрибутов text и tail в этот момент не определено. То же самое относится к дочерним элементам; они могут или могут не присутствовать.

Если вам нужен полностью заполненный элемент, ищите события «end».

Устарело начиная с версии 3.4: Аргумент parser.

Изменено в версии 3.8: Были добавлены события comment и pi.

xml.etree.ElementTree.parse(source, parser=None)

Парсит XML-раздел в дерево элементов. source — имя файла или объект файла, содержащий XML-данные. parser — необязательный экземпляр парсера. Если он не задан, используется стандартный парсер XMLParser. Возвращает экземпляр ElementTree.

xml.etree.ElementTree.ProcessingInstruction(target, text=None)

Фабрика элементов PI. Эта фабричная функция создаёт специальный элемент, который стандартный сериализатор сериализует как XML-обработку команд. target — строка, содержащая цель PI. text — строка, содержащая содержимое PI, если задано. Возвращает экземпляр элемента, представляющий инструкцию по обработке.

Обратите внимание, что XMLParser пропускает инструкции по обработке во входных данных вместо создания объектов PI для них. ElementTree будет содержать узлы инструкций по обработке только в том случае, если они были вставлены в дерево с помощью одного из методов Element.

xml.etree.ElementTree.register_namespace(prefix, uri)

Регистрирует префикс пространства имен. Регистр глобальный, и любое существующее отображение для данного префикса или URI пространства имен будет удалено. prefix — префикс пространства имен. uri — URI пространства имен. Теги и атрибуты в этом пространстве имен будут сериализованы с данным префиксом, если это возможно.

Добавлена в версии 3.2.

xml.etree.ElementTree.SubElement(parent, tag, attrib={}, **extra)

Фабрика подэлементов. Эта функция создаёт экземпляр элемента и добавляет его в существующий элемент.

Имя элемента, имена атрибутов и значения атрибутов могут быть либо байтовыми строками, либо строками Юникода. parent — родительский элемент. tag — имя подэлемента. attrib — необязательный словарь, содержащий атрибуты элемента. extra содержит дополнительные атрибуты, заданные в качестве ключевых аргументов. Возвращает экземпляр элемента.

xml.etree.ElementTree.tostring(element, encoding='us-ascii', method='xml', *, xml_declaration=None, default_namespace=None, short_empty_elements=True)

Генерирует строковое представление XML-элемента, включая все подэлементы. element — экземпляр Element. encoding [1] — кодировка вывода (по умолчанию US-ASCII). Используйте encoding="unicode" для генерации строки Юникода (в противном случае генерируется байтовая строка). method — либо "xml", "html" или "text" (по умолчанию "xml"). xml_declaration, default_namespace и short_empty_elements имеют то же значение, что и в ElementTree.write(). Возвращает (при необходимости) закодированную строку, содержащую XML-данные.

Изменено в версии 3.4: Добавлен параметр short_empty_elements.

Изменено в версии 3.8: Добавлены параметры xml_declaration и default_namespace.

Изменено в версии 3.8: Функция tostring() теперь сохраняет порядок атрибутов, указанный пользователем.

xml.etree.ElementTree.tostringlist(element, encoding='us-ascii', method='xml', *, xml_declaration=None, default_namespace=None, short_empty_elements=True)

Генерирует строковое представление XML-элемента, включая все подэлементы. element — экземпляр Element. encoding [1] — кодировка вывода (по умолчанию US-ASCII). Используйте encoding="unicode" для генерации строки Юникода (в противном случае генерируется байтовая строка). method — либо "xml", "html" или "text" (по умолчанию "xml"). xml_declaration, default_namespace и short_empty_elements имеют то же значение, что и в ElementTree.write(). Возвращает список (при необходимости) закодированных строк, содержащих XML-данные. Он не гарантирует никакого определенного порядка, за исключением того, что b"".join(tostringlist(element)) == tostring(element).

Добавлена в версии 3.2.

Изменено в версии 3.4: Добавлен параметр short_empty_elements.

Изменено в версии 3.8: Добавлены параметры xml_declaration и default_namespace.

Изменено в версии 3.8: Функция tostringlist() теперь сохраняет порядок атрибутов, указанный пользователем.

xml.etree.ElementTree.XML(text, parser=None)

Парсит XML-раздел из константы строки. Эта функция может использоваться для встраивания «XML-литералов» в код Python. text — строка, содержащая XML-данные. parser — необязательный экземпляр парсера. Если не указано, используется стандартный парсер XMLParser. Возвращает экземпляр Element.

xml.etree.ElementTree.XMLID(text, parser=None)

Парсит XML-раздел из константы строки, а также возвращает словарь, который сопоставляет id элемента с элементами. text — строка, содержащая XML-данные. parser — необязательный экземпляр парсера. Если не указано, используется стандартный парсер XMLParser. Возвращает кортеж, содержащий экземпляр Element и словарь.

Поддержка XInclude

Этот модуль предоставляет ограниченную поддержку директив XInclude через вспомогательный модуль xml.etree.ElementInclude. Этот модуль может использоваться для вставки поддеревьев и текстовых строк в деревья элементов на основе информации в дереве.

Пример

Вот пример, демонстрирующий использование модуля XInclude. Чтобы включить XML-документ в текущий документ, используйте элемент {http://www.w3.org/2001/XInclude}include и установите атрибут parse в значение "xml", а с помощью атрибута href укажите документ для включения.

<?xml version="1.0"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude">
  <xi:include href="source.xml" parse="xml" />
</document>

По умолчанию атрибут href обрабатывается как имя файла. Вы можете использовать пользовательские загрузчики для изменения этого поведения. Также обратите внимание, что стандартный вспомогательный модуль не поддерживает синтаксис XPointer.

Для обработки этого файла загрузите его обычным способом и передайте корневой элемент модулю xml.etree.ElementTree:

from xml.etree import ElementTree, ElementInclude

tree = ElementTree.parse("document.xml")
root = tree.getroot()

ElementInclude.include(root)

Модуль ElementInclude заменяет элемент {http://www.w3.org/2001/XInclude}include корневым элементом из документа source.xml. Результат может выглядеть примерно так:

<document xmlns:xi="http://www.w3.org/2001/XInclude">
  <para>This is a paragraph.</para>
</document>

Если атрибут parse опущен, он по умолчанию равен “xml”. Атрибут href обязателен.

Чтобы включить текстовый документ, используйте элемент {http://www.w3.org/2001/XInclude}include и установите атрибут parse в значение “text”:

<?xml version="1.0"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude">
  Copyright (c) <xi:include href="year.txt" parse="text" />.
</document>

Результат может выглядеть примерно так:

<document xmlns:xi="http://www.w3.org/2001/XInclude">
  Copyright (c) 2003.
</document>

Справочник

Функции

xml.etree.ElementInclude.default_loader(href, parse, encoding=None)

Загрузчик по умолчанию. Этот загрузчик по умолчанию считывает включённый ресурс с диска. href — URL. parse — режим парсинга, либо “xml”, либо “text”. encoding — необязательная кодировка текста. Если не указано, кодировка — utf-8. Возвращает расширенный ресурс. Если режим парсинга "xml", это экземпляр Element. Если режим парсинга "text", это строка. Если загрузчик завершается неудачно, он может вернуть None или выбросить исключение.

xml.etree.ElementInclude.include(elem, loader=None, base_url=None, max_depth=6)

Эта функция расширяет директивы XInclude на месте в дереве, указанном в elem. elem — либо корневой Element, либо экземпляр ElementTree для поиска такого элемента. loader — необязательный загрузчик ресурсов. Если опущен, по умолчанию используется default_loader(). Если задан, он должен быть вызываемым объектом, реализующим тот же интерфейс, что и default_loader(). base_url — базовый URL исходного файла для разрешения относительных ссылок на файлы включения. max_depth — максимальное количество рекурсивных включений. Ограничено для уменьшения риска взрыва вредоносного содержимого. Передайте None для отключения ограничения.

Изменено в версии 3.9: Добавлены параметры base_url и max_depth.

Объекты Элементов

class xml.etree.ElementTree.Element(tag, attrib={}, **extra)

Класс элемента. Этот класс определяет интерфейс элемента и предоставляет эталонную реализацию этого интерфейса.

Имя элемента, имена атрибутов и значения атрибутов могут быть строками байтов или строками Юникода. tag — это имя элемента. attrib — это необязательный словарь, содержащий атрибуты элемента. extra содержит дополнительные атрибуты, заданные в качестве ключевых аргументов.

tag

Строка, определяющая, какой тип данных представляет этот элемент (тип элемента, другими словами).

text
tail

Эти атрибуты могут использоваться для хранения дополнительных данных, связанных с элементом. Их значения обычно являются строками, но могут быть любыми объектами, специфичными для приложения. Если элемент создан из XML-файла, атрибут text содержит либо текст между открывающим тегом элемента и его первым дочерним элементом или закрывающим тегом, либо None, а атрибут tail содержит либо текст между закрывающим тегом элемента и следующим тегом, либо None. Для XML-данных

<a><b>1<c>2<d/>3</c></b>4</a>

элемент a имеет None для обоих атрибутов text и tail, элемент b имеет text "1" и tail "4", элемент c имеет text "2" и tail None, а элемент d имеет text None и tail "3".

Чтобы собрать внутренний текст элемента, см. itertext(), например "".join(element.itertext()).

Приложения могут хранить произвольные объекты в этих атрибутах.

attrib

Словарь, содержащий атрибуты элемента. Обратите внимание, что, хотя значение attrib всегда является реальным изменяемым словарем Python, реализация ElementTree может выбрать использование другого внутреннего представления и создать словарь только в том случае, если кто-то запросит его. Чтобы воспользоваться такими реализациями, используйте методы словаря по возможности.

Следующие методы, похожие на методы словаря, работают с атрибутами элемента.

clear()

Сбрасывает элемент. Эта функция удаляет все подэлементы, очищает все атрибуты и устанавливает атрибуты text и tail в None.

get(key, default=None)

Получает атрибут элемента с именем key.

Возвращает значение атрибута или default, если атрибут не был найден.

items()

Возвращает атрибуты элемента в виде последовательности пар (имя, значение). Атрибуты возвращаются в произвольном порядке.

keys()

Возвращает имена атрибутов элементов в виде списка. Имена возвращаются в произвольном порядке.

set(key, value)

Устанавливает атрибут key элемента в значение value.

Следующие методы работают с дочерними элементами (поделементами).

append(subelement)

Добавляет элемент subelement в конец внутреннего списка дочерних элементов этого элемента. Возбуждает TypeError, если subelement не является Element.

extend(subelements)

Добавляет subelements из последовательности объектов с нулем или более элементами. Возбуждает TypeError, если подэлемент не является Element.

Добавлен в версии 3.2.

find(match, namespaces=None)

Находит первый подэлемент, соответствующий match. match может быть именем тега или путем. Возвращает экземпляр элемента или None. namespaces — это необязательное отображение из префикса пространства имен в полное имя. Передайте '' в качестве префикса, чтобы перенести все имена тегов без префикса в указанное пространство имен.

findall(match, namespaces=None)

Находит все соответствующие подэлементы по имени тега или пути. Возвращает список, содержащий все соответствующие элементы в порядке документа. namespaces — это необязательное отображение из префикса пространства имен в полное имя. Передайте '' в качестве префикса, чтобы перенести все имена тегов без префикса в указанное пространство имен.

findtext(match, default=None, namespaces=None)

Находит текст для первого подэлемента, соответствующего match. match может быть именем тега или путем. Возвращает текстовое содержимое первого соответствующего элемента или default, если элемент не был найден. Обратите внимание, что если у соответствующего элемента нет текстового содержимого, возвращается пустая строка. namespaces — это необязательное отображение из префикса пространства имен в полное имя. Передайте '' в качестве префикса, чтобы перенести все имена тегов без префикса в указанное пространство имен.

insert(index, subelement)

Вставляет subelement в заданную позицию в этом элементе. Возбуждает TypeError, если subelement не является Element.

iter(tag=None)

Создает итератор дерева итератор с текущим элементом в качестве корня. Итератор перебирает этот элемент и все элементы ниже него в порядке документа (в глубину). Если tag не равно None или '*', из итератора возвращаются только элементы, чьи теги равны tag. Если структура дерева изменяется во время итерации, результат неопределен.

Добавлен в версии 3.2.

iterfind(match, namespaces=None)

Находит все соответствующие подэлементы по имени тега или пути. Возвращает итерируемый объект, возвращающий все соответствующие элементы в порядке документа. namespaces — это необязательное отображение из префикса пространства имен в полное имя.

Добавлен в версии 3.2.

itertext()

Создает итератор текста. Итератор перебирает этот элемент и все подэлементы в порядке документа и возвращает весь внутренний текст.

Добавлен в версии 3.2.

makeelement(tag, attrib)

Создает новый объект элемента того же типа, что и этот элемент. Не вызывайте этот метод, используйте функцию-фабрику SubElement() вместо этого.

remove(subelement)

Удаляет subelement из элемента. В отличие от методов find*, этот метод сравнивает элементы на основе идентификатора экземпляра, а не на основе значения тега или содержимого.

Element объекты также поддерживают следующие методы типа последовательности для работы с подэлементами: __delitem__(), __getitem__(), __setitem__(), __len__().

Внимание: элементы без подэлементов будут проверяться как False. В будущей версии Python все элементы будут проверяться как True независимо от того, существуют ли подэлементы. Вместо этого предпочитайте явные len(elem) или elem is not None проверки.:

element = root.find('foo')

if not element:  # careful!
    print("element not found, or element has no subelements")

if element is None:
    print("element not found")

Изменено в версии 3.12: Проверка истинности значения элемента генерирует DeprecationWarning.

Перед Python 3.8 порядок сериализации атрибутов XML-элементов искусственно делался предсказуемым путем сортировки атрибутов по их имени. Основываясь на теперь гарантированном порядке словарей, эта произвольная переупорядочивание была удалена в Python 3.8, чтобы сохранить порядок, в котором атрибуты изначально были распарсены или созданы кодом пользователя.

В целом, код пользователя должен стараться не зависеть от конкретного порядка атрибутов, поскольку XML Information Set явно исключает порядок атрибутов из информации. Код должен быть подготовлен к обработке любого порядка на входе. В тех случаях, когда требуется детерминированный вывод XML, например, для криптографического подписания или наборов тестовых данных, доступна каноническая сериализация с функцией canonicalize().

В тех случаях, когда канонический вывод неприменим, но определенный порядок атрибутов всё же желателен на выходе, код должен стремиться к созданию атрибутов непосредственно в нужном порядке, чтобы избежать искажений восприятия для читателей кода. В тех случаях, когда это сложно сделать, можно применить рецепт, подобный следующему, перед сериализацией, чтобы обеспечить порядок независимо от создания элемента:

def reorder_attributes(root):
    for el in root.iter():
        attrib = el.attrib
        if len(attrib) > 1:
            # adjust attribute order, e.g. by sorting
            attribs = sorted(attrib.items())
            attrib.clear()
            attrib.update(attribs)

Объекты ElementTree

class xml.etree.ElementTree.ElementTree(element=None, file=None)

Класс-обёртка ElementTree. Этот класс представляет всю иерархию элементов и добавляет некоторую дополнительную поддержку сериализации в стандартный XML и из него.

element — корневой элемент. Дерево инициализируется содержимым XML-файла, если он задан.

_setroot(element)

Заменяет корневой элемент для этого дерева. Это отбрасывает текущее содержимое дерева и заменяет его заданным элементом. Используйте с осторожностью. element — экземпляр элемента.

find(match, namespaces=None)

То же, что и Element.find(), начиная с корня дерева.

findall(match, namespaces=None)

То же, что и Element.findall(), начиная с корня дерева.

findtext(match, default=None, namespaces=None)

То же, что и Element.findtext(), начиная с корня дерева.

getroot()

Возвращает корневой элемент для этого дерева.

iter(tag=None)

Создаёт и возвращает итератор дерева для корневого элемента. Итератор перебирает все элементы в этом дереве в порядке раздела. tag — тег для поиска (по умолчанию возвращаются все элементы).

iterfind(match, namespaces=None)

То же, что и Element.iterfind(), начиная с корня дерева.

Добавлен в версии 3.2.

parse(source, parser=None)

Загружает внешний XML-раздел в это дерево элементов. source — имя файла или объект файла. parser — необъект парсера. Если не указан, используется стандартный парсер XMLParser. Возвращает корневой элемент раздела.

write(file, encoding='us-ascii', xml_declaration=None, default_namespace=None, method='xml', *, short_empty_elements=True)

Записывает дерево элементов в файл в формате XML. file — имя файла или объект файла, открытый для записи. encoding [1] — кодировка вывода (по умолчанию US-ASCII). xml_declaration управляет добавлением объявления XML в файл. Используйте False для никогда, True для всегда, None для только если не US-ASCII или UTF-8 или Unicode (по умолчанию None). default_namespace задаёт стандартное XML-пространство имён (для “xmlns”). method может быть "xml", "html" или "text" (по умолчанию "xml"). Параметр short_empty_elements (только ключевое слово) управляет форматированием элементов, не содержащих контента. Если True (по умолчанию), они выводятся как один самозакрывающийся тег, в противном случае — как пара открывающего и закрывающего тегов.

Выводом является строка (str) или двоичные данные (bytes). Это контролируется аргументом encoding. Если encoding — "unicode", вывод — строка; в противном случае — двоичные данные. Обратите внимание, что это может конфликтовать с типом file, если это открытый объект файла; убедитесь, что вы не пытаетесь записать строку в двоичный поток и наоборот.

Изменено в версии 3.4: Добавлен параметр short_empty_elements.

Изменено в версии 3.8: Метод write() теперь сохраняет порядок атрибутов, заданный пользователем.

Это XML-файл, который будет обрабатываться:

<html>
    <head>
        <title>Example page</title>
    </head>
    <body>
        <p>Moved to <a href="http://example.org/">example.org</a>
        or <a href="http://example.com/">example.com</a>.</p>
    </body>
</html>

Пример изменения атрибута «target» каждого ссылки в первом абзаце:

>>> from xml.etree.ElementTree import ElementTree
>>> tree = ElementTree()
>>> tree.parse("index.xhtml")
<Element 'html' at 0xb77e6fac>
>>> p = tree.find("body/p")     # Finds first occurrence of tag p in body
>>> p
<Element 'p' at 0xb77ec26c>
>>> links = list(p.iter("a"))   # Returns list of all links
>>> links
[<Element 'a' at 0xb77ec2ac>, <Element 'a' at 0xb77ec1cc>]
>>> for i in links:             # Iterates through all found links
...     i.attrib["target"] = "blank"
...
>>> tree.write("output.xhtml")

Объекты QName

class xml.etree.ElementTree.QName(text_or_uri, tag=None)

Обёртка QName. Это можно использовать для обертки значения атрибута QName, чтобы получить правильную обработку пространства имён при выводе. text_or_uri — строка, содержащая значение QName в форме {uri}local, или, если задан аргумент tag, часть URI QName. Если задан tag, первый аргумент интерпретируется как URI, а этот аргумент интерпретируется как локальное имя. Экземпляры QName непрозрачны.

Объекты TreeBuilder

class xml.etree.ElementTree.TreeBuilder(element_factory=None, *, comment_factory=None, pi_factory=None, insert_comments=False, insert_pis=False)

Универсальный конструктор структуры элементов. Этот конструктор преобразует последовательность вызовов методов start, data, end, comment и pi в хорошо сформированную структуру элементов. Вы можете использовать этот класс для построения структуры элементов с помощью пользовательского парсера XML или парсера для какого-либо другого формата, похожего на XML.

element_factory, если задан, должен быть вызываемым объектом, принимающим два позиционных аргумента: тег и словарь атрибутов. Ожидается, что он вернёт новую экземпляр элемента.

Функции comment_factory и pi_factory, если заданы, должны вести себя как функции Comment() и ProcessingInstruction() для создания комментариев и инструкций обработки. Если они не заданы, будут использованы значения по умолчанию. Если insert_comments и/или insert_pis установлены в true, комментарии/инструкции обработки будут вставлены в дерево, если они появляются внутри корневого элемента (но не вне его).

close()

Очищает буферы конструктора и возвращает корневой элемент документа. Возвращает экземпляр Element.

data(data)

Добавляет текст к текущему элементу. data — строка. Это должна быть строка байтов или строка Юникода.

end(tag)

Закрывает текущий элемент. tag — имя элемента. Возвращает закрытый элемент.

start(tag, attrs)

Открывает новый элемент. tag — имя элемента. attrs — словарь, содержащий атрибуты элемента. Возвращает открытый элемент.

comment(text)

Создаёт комментарий с заданным текстом text. Если insert_comments равно true, он также будет добавлен в дерево.

Добавлен в версии 3.8.

pi(target, text)

Создаёт инструкцию обработки с заданным именем target и текстом text. Если insert_pis равно true, она также будет добавлена в дерево.

Добавлен в версии 3.8.

Кроме того, пользовательский объект TreeBuilder может предоставлять следующие методы:

doctype(name, pubid, system)

Обрабатывает объявление типа документа. name — имя типа документа. pubid — идентификатор публикации. system — идентификатор системы. Этот метод не существует в стандартном классе TreeBuilder.

Добавлен в версии 3.2.

start_ns(prefix, uri)

Вызывается всякий раз, когда парсер сталкивается с новым объявлением пространства имён, перед вызовом start() для открывающего элемента, который его определяет. prefix — '' для пространства имён по умолчанию и имя префикса объявленного пространства имён в противном случае. uri — URI пространства имён.

Добавлен в версии 3.8.

end_ns(prefix)

Вызывается после вызова end() элемента, который объявил сопоставление префикса пространства имён, с именем prefix, которое вышло из области видимости.

Добавлен в версии 3.8.

class xml.etree.ElementTree.C14NWriterTarget(write, *, with_comments=False, strip_text=False, rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None, exclude_attrs=None, exclude_tags=None)

Писатель C14N 2.0. Аргументы такие же, как и для функции canonicalize(). Этот класс не строит дерево, но напрямую преобразует события обратного вызова в сериализованную форму с помощью функции write.

Добавлен в версии 3.8.

Объекты XMLParser

class xml.etree.ElementTree.XMLParser(*, target=None, encoding=None)

Этот класс является базовым строительным блоком модуля. Он использует xml.parsers.expat для эффективного событийного парсинга XML. Его можно по частям подкармливать данными XML с помощью метода feed(), и события парсинга переводятся в API «нажатия» — путём вызова обратных вызовов на объекте target. Если target опущен, используется стандартный TreeBuilder. Если задан encoding [1], это значение переопределяет кодировку, указанную в файле XML.

Изменено в версии 3.8: Параметры теперь являются только ключевыми. Аргумент html больше не поддерживается.

close()

Завершает подкармливание данных парсеру. Возвращает результат вызова метода close() объекта target, переданного во время создания; по умолчанию это корневой элемент документа.

feed(data)

Подкармливает парсер данными. data — закодированные данные.

flush()

Вызывает парсинг любых ранее переданных необработанных данных, что может быть использовано для обеспечения более оперативной обратной связи, особенно с Expat >=2.6.0. Реализация flush() временно отключает отложенный повторный парсинг с Expat (если он в данный момент включён) и вызывает повторный парсинг. Отключение отложенного повторного парсинга влечёт за собой последствия для безопасности; см. xml.parsers.expat.xmlparser.SetReparseDeferralEnabled() для получения более подробной информации.

Обратите внимание, что flush() был обратной совместимостью перенесён в некоторые предыдущие версии CPython в качестве исправления уязвимости безопасности. Проверьте наличие flush() с помощью hasattr(), если используется код, работающий в разных версиях Python.

Добавлен в версии 3.12.3.

XMLParser.feed() вызывает метод start(tag, attrs_dict) объекта target для каждого открывающего тега, метод end(tag) для каждого закрывающего тега, а данные обрабатываются методом data(data). Для других поддерживаемых методов обратного вызова см. класс TreeBuilder. XMLParser.close() вызывает метод close() объекта target. XMLParser может использоваться не только для построения структуры дерева. Пример подсчёта максимальной глубины файла XML:

>>> from xml.etree.ElementTree import XMLParser
>>> class MaxDepth:                     # The target object of the parser
...     maxDepth = 0
...     depth = 0
...     def start(self, tag, attrib):   # Called for each opening tag.
...         self.depth += 1
...         if self.depth > self.maxDepth:
...             self.maxDepth = self.depth
...     def end(self, tag):             # Called for each closing tag.
...         self.depth -= 1
...     def data(self, data):
...         pass            # We do not need to do anything with data.
...     def close(self):    # Called when all data has been parsed.
...         return self.maxDepth
...
>>> target = MaxDepth()
>>> parser = XMLParser(target=target)
>>> exampleXml = """
... <a>
...   <b>
...   </b>
...   <b>
...     <c>
...       <d>
...       </d>
...     </c>
...   </b>
... </a>"""
>>> parser.feed(exampleXml)
>>> parser.close()
4

Объекты XMLPullParser

class xml.etree.ElementTree.XMLPullParser(events=None)

Парсер выдергивания, подходящий для неблокирующих приложений. Его API со стороны ввода аналогичен API XMLParser, но вместо отправки вызовов целевому обработчику, XMLPullParser собирает внутренний список событий разбора и позволяет пользователю читать из него. events — последовательность событий для отчёта обратно. Поддерживаемые события — строки "start", "end", "comment", "pi", "start-ns" и "end-ns" (события «ns» используются для получения подробной информации о пространствах имён). Если events опущено, сообщаются только события "end".

feed(data)

Передать заданные байтовые данные парсеру.

flush()

Вызывает разбор любых ранее переданных необработанных данных, что может быть использовано для обеспечения более оперативной обратной связи, особенно с Expat >=2.6.0. Реализация flush() временно отключает отложенный повторный разбор с Expat (если он включён в данный момент) и инициирует повторный разбор. Отключение отложенного повторного разбора имеет последствия для безопасности; см. xml.parsers.expat.xmlparser.SetReparseDeferralEnabled() для получения подробностей.

Обратите внимание, что flush() был обратнопортирован в некоторые предыдущие релизы CPython в качестве исправления безопасности. Проверьте доступность flush() с помощью hasattr(), если код используется на различных версиях Python.

Добавлен в версии 3.12.3.

close()

Сигнализирует парсеру о завершении потока данных. В отличие от XMLParser.close(), этот метод всегда возвращает None. Любые события, которые ещё не были получены, когда парсер закрыт, по-прежнему могут быть прочитаны с помощью read_events().

read_events()

Возвращает итератор по событиям, которые были встречены в данных, переданных парсеру. Итератор возвращает пары (event, elem), где event — строка, представляющая тип события (например, "end"), а elem — встреченный объект Element, или другое значение контекста следующим образом.

  • start, end: текущий элемент.
  • comment, pi: текущий комментарий/инструкция обработки.
  • start-ns: кортеж (prefix, uri), обозначающий сопоставление объявленных пространств имён.
  • end-ns: None (это может измениться в будущей версии).

События, предоставленные в предыдущем вызове read_events(), не будут возвращены повторно. События потребляются из внутренней очереди только тогда, когда они извлекаются из итератора, поэтому несколько читателей, итерирующих параллельно по итераторам, полученным из read_events(), будут иметь непредсказуемые результаты.

Примечание

XMLPullParser гарантирует только, что он видел символ «>» начального тега, когда он испускает событие «start», поэтому атрибуты определены, но содержимое атрибутов text и tail в этот момент неопределено. То же самое относится к дочерним элементам; они могут или не могут быть присутствовать.

Если вам нужен полностью заполненный элемент, ищите события «end».

Добавлен в версии 3.4.

Изменено в версии 3.8: Были добавлены события comment и pi.

Исключения

class xml.etree.ElementTree.ParseError

Ошибка разбора XML, генерируемая различными методами разбора в этом модуле при неудачном разборе. Строковое представление экземпляра этого исключения будет содержать понятное сообщение об ошибке. Кроме того, у него будут доступны следующие атрибуты:

code

Числовой код ошибки от парсера expat. См. документацию по xml.parsers.expat для списка кодов ошибок и их значений.

position

Кортеж из line и column, указывающих, где произошла ошибка.

Примечания

[1] (1,2,3,4)

Строка кодировки, включённая в выходной 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.

© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/xml.etree.elementtree.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API