xml.etree.ElementTree — ElementTree XML API

Источник: Lib/xml/etree/ElementTree.py


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

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

Не рекомендуется, начиная с версии 3.3: Модуль xml.etree.cElementTree устарел.

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

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

Учебное пособие

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

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

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

Разбор XML

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

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

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

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

Или непосредственно из строки:

root = ET.fromstring(country_data_as_string)

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

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

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

У него также есть дочерние узлы, над которыми мы можем выполнять итерации:

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

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

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

Примечание

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

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 к элементу rank:

>>> 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 содержит namespaces, теги и атрибуты с префиксами в виде prefix:sometag расширяются до {uri}sometag, где префикс заменяется полным URI. Также, если есть default namespace, этот полный 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 expressions для поиска элементов в дереве. Целью является поддержка небольшого подмножества сокращенного синтаксиса; полный механизм XPath выходит за рамки модуля.

Пример

Вот пример, демонстрирующий некоторые возможности модуля XPath. Мы будем использовать countrydata XML-документ из раздела Parsing 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']

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

Added in version 3.10.

[tag]

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

[.='text']

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

Added in version 3.7.

[.!='text']

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

Added in version 3.10.

[tag='text']

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

[tag!='text']

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

Added in version 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 file(-like), если он предоставлен, или возвращает его в виде текстовой строки, если нет. В выходной файл поступает текст, а не байты. Поэтому его следует открывать в текстовом режиме с кодировкой 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)

Конфигурационные опции следующие:

  • 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: набор имен тегов, которые не должны быть сериализованы

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

Added in version 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-документ из последовательности фрагментов строк. последовательность - список или другая последовательность, содержащая фрагменты XML-данных. parser - необязательный экземпляр парсера. Если он не указан, используется стандартный XMLParser парсер. Возвращает экземпляр Element.

Added in version 3.2.

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

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

Added in version 3.9.

xml.etree.ElementTree.iselement(element)

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

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

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

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

Примечание

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

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

Не рекомендуется, начиная с версии 3.4: Аргумент парсер.

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

Изменено в версии 3.13: Добавлен метод close().

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 пространства имен. Теги и атрибуты в этом пространстве имен будут сериализованы с данным префиксом, если это вообще возможно.

Added in version 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. 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. 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).

Added in version 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:s элементов с элементами. text - строка, содержащая XML-данные. parser - необязательный экземпляр парсера. Если он не указан, используется стандартный XMLParser парсер. Возвращает кортеж, содержащий экземпляр Element и словарь.

Поддержка XInclude

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

Пример

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

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

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

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

from xml.etree import ElementTree, ElementInclude

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

ElementInclude.include(root)

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

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

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

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

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

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

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

Ссылка

Функции

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

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

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

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

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

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

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

Класс 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)

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

Added in version 3.2.

find(match, namespaces=None)

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

findall(match, namespaces=None)

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

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

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

insert(index, subelement)

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

iter(tag=None)

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

Added in version 3.2.

iterfind(match, namespaces=None)

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

Added in version 3.2.

itertext()

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

Added in version 3.2.

makeelement(tag, attrib)

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

remove(subelement)

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

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

Внимание: Элементы без подэлементов будут проверяться как False. Проверка истинности значения элемента устарела и вызовет исключение в Python 3.14. Вместо этого используйте специальный тест 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")

Изменено в версии 3.12: Проверка истинности значения Элемента выдает DeprecationWarning.

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

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

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

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

Объекты ElementTree

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

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

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

_setroot(element)

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

find(match, namespaces=None)

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

findall(match, namespaces=None)

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

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

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

getroot()

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

iter(tag=None)

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

iterfind(match, namespaces=None)

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

Added in version 3.2.

parse(source, parser=None)

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

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

Записывает дерево элементов в файл в формате XML. file - имя файла или file object, открытый для записи. 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 object; убедитесь, что вы не пытаетесь записать строку в двоичный поток и наоборот.

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

Функции 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)

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

Added in version 3.8.

pi(target, text)

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

Added in version 3.8.

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

doctype(name, pubid, system)

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

Added in version 3.2.

start_ns(prefix, uri)

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

Added in version 3.8.

end_ns(prefix)

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

Added in version 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.

Added in version 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: Параметрами теперь являются keyword-only. Аргумент html больше не поддерживается.

close()

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

feed(data)

Передает данные парсеру. data - это закодированные данные.

flush()

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

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

Added in version 3.13.

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)

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

feed(data)

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

flush()

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

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

Added in version 3.13.

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».

Added in version 3.4.

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

Исключения

class xml.etree.ElementTree.ParseError

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

code

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

position

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

Сноски