Spec-Zone.ru › Python 3.12

xml.etree.ElementTree — XML API 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", это экземпляр 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.

Объекты 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. В будущей версии Python проверка истинности всех элементов будет давать True независимо от наличия подэлементов. Вместо этого предпочтительно использовать явные проверки len(elem) или elem is not None:

element = root.find('foo')

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

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

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

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

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

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

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

Объекты ElementTree

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

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

element — корневой элемент. Если указан 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.12.3.

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

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

Объекты XMLPullParser

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

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

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

close()

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

read_events()

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

  • start, end: текущий элемент Element.
  • 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.12/library/xml.etree.elementtree.html

Spec-Zone.ru

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