Spec-Zone.ru › Python 3.11

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

Мы будем использовать следующий 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.

API вытягивания для неблокирующего парсинга

Большинство функций парсинга, предоставляемых этим модулем, требуют, чтобы весь документ был прочитан сразу перед возвратом любого результата. Можно использовать XMLParser и поставлять данные в него постепенно, но это API «нажатия», вызывающее методы целевого обработчика событий, что слишком низкоуровнево и неудобно для большинства потребностей. Иногда пользователю действительно нужно возможность парсить 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-документ и не хотите хранить его целиком в памяти.

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

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{номер}”

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

  • qname_aware_tags: множество имён тегов с поддержкой полных имён, в которых префиксы

    должны быть заменены в текстовом содержимом (по умолчанию: пустое множество)

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

    должны быть заменены в текстовом содержимом (по умолчанию: пустое множество)

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

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

Новая функция в версии 3.8.

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

Фабрика элементов комментариев. Эта фабричная функция создаёт специальный элемент, который стандартный сериализатор будет сериализовывать как XML-комментарий. Строка комментария может быть строкой байтов или строкой Unicode. 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)

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

Обратите внимание, что XMLParser пропускает инструкции обработки во входных данных, вместо того чтобы создавать для них объекты комментариев. 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", это экземпляр ElementTree. Если режим разбора — «text», это строка Юникода. Если загрузчик терпит неудачу, он может вернуть None или вызвать исключение.

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

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

Возвращает расширенный ресурс. Если режим разбора — "xml", это экземпляр ElementTree. Если режим разбора — «text», это строка Юникода. Если загрузчик терпит неудачу, он может вернуть None или вызвать исключение.

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

END_OF_DOCUMENT_MARKER ```

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

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

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

Имя элемента, имена атрибутов и значения атрибутов могут быть либо строками байтов, либо строками Unicode. 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. Это поведение изменится в будущих версиях. Используйте вместо этого конкретную проверку len(elem) или elem is 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")

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

END_OF_DOCUMENT_MARKER

В общем случае, код пользователя должен стараться не зависеть от конкретного порядка атрибутов, учитывая, что 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 push — путём вызова обратных вызовов в объекте target. Если target не указан, используется стандартный TreeBuilder. Если задан encoding 1, значение переопределяет кодировку, указанную в файле XML.

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

close()

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

feed(data)

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

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)

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

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

Кортеж из номеров строки и столбца, указывающий место возникновения ошибки.

Примечания

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–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/library/xml.etree.elementtree.html

Spec-Zone.ru

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