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-документ country_data.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 и постепенно передавать ему данные, но это push 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-документа, который не хочется целиком хранить в памяти.

Если требуется получать немедленную обратную связь через события, вызов метода 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 этого модуля. Мы будем использовать XML-документ countrydata из раздела Разбор 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, в которых префиксы

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

  • qname_aware_attrs: набор имён атрибутов, учитывающих QName, в которых префиксы

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

  • 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 может быть Element или ElementTree. 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)

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

Имя элемента, имена атрибутов и значения атрибутов могут быть байтовыми строками или строками Unicode. 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", чтобы создать строку 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", чтобы создать строку 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 из строковой константы и также возвращает словарь, сопоставляющий идентификаторы элементов с элементами. 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», это строка Unicode. Если загрузчику не удаётся выполнить загрузку, он может вернуть 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», это строка Unicode. Если загрузчику не удаётся выполнить загрузку, он может вернуть None или вызвать исключение.

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

Объекты Element

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

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

Имя элемента, имена атрибутов и значения атрибутов могут быть байтовыми строками или строками 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 это произвольное переупорядочивание было отменено, чтобы сохранять порядок, в котором атрибуты изначально разбирались или создавались пользовательским кодом.

В целом пользовательскому коду следует избегать зависимости от определённого порядка атрибутов, поскольку набор информационных элементов XML явно исключает порядок атрибутов как источник информации. Код должен быть готов к любому порядку атрибутов во входных данных. Если требуется детерминированный вывод 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-file, дерево инициализируется его содержимым.

_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 — строка. Это должна быть байтовая строка или строка Unicode.

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)

Обрабатывает объявление doctype. name — имя doctype. 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(), а события разбора преобразуются в push 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 в качестве исправления безопасности. Если код должен выполняться в разных версиях Python, проверьте наличие flush() с помощью hasattr().

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

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 в качестве исправления безопасности. Если код должен выполняться в разных версиях Python, проверьте наличие flush() с помощью hasattr().

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

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–2024 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