xml.etree.ElementTree — API ElementTree XML

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


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

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

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

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

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

Учебник

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

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

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

Разбор XML

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

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

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

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

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

root = ET.fromstring(country_data_as_string)

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

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

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

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

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

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

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

Примечание

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

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

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

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

Нахождение интересных элементов

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

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

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

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

Более сложная спецификация того, какие элементы следует искать, возможна при использовании XPath.

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

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

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

Допустим, мы хотим добавить единицу к рангу каждой страны, и добавляем атрибут updated к элементу 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. Мы будем использовать XML-документ countrydata из раздела 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']

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

Добавлено в версии 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 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{число}».

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

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

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

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

Добавлено в версии 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).

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

Примечание

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

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

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

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

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

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

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

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

Элементы-объекты

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.

Добавлено в версии 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. Если структура дерева изменена во время итерации, результат не определен.

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

iterfind(match, namespaces=None)

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

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

itertext()

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

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

makeelement(tag, attrib)

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

remove(subelement)

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

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

Внимание: Элементы без подэлементов будут проверяться как False. Это поведение будет изменено в будущих версиях. Вместо этого используйте специальный тест len(elem) или elem is None.

element = root.find('foo')

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

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

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

В целом, пользовательский код должен стараться не зависеть от конкретного упорядочивания атрибутов, учитывая, что XML 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)

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

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

Функции 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, то комментарий также будет добавлен в дерево.

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

pi(target, text)

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

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

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

doctype(name, pubid, system)

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

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

start_ns(prefix, uri)

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

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

end_ns(prefix)

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

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

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

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

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

Объекты XMLParser

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

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

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

close()

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

feed(data)

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

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

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

Объекты XMLPullParser

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

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

feed(data)

Подать заданные байты данных в синтаксический анализатор.

close()

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

read_events()

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

  • start, end: текущий Элемент.

  • comment, pi: текущий комментарий / инструкция по обработке

  • start-ns: кортеж (prefix, uri), называющий объявленное отображение пространства имен.

  • end-ns: None (это может измениться в будущей версии)

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

Примечание

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

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

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

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

Исключения

class xml.etree.ElementTree.ParseError

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

code

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

position

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

Сноски

1(1,2,3,4)

Строка кодировки, включенная в вывод XML, должна соответствовать соответствующим стандартам. Например, «UTF-8» является допустимым, а «UTF8» - нет. См. https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl и https://www.iana.org/assignments/character-sets/character-sets.xhtml.

Вернуться на верх