Spec-Zone.ru › Python 3.8

xml.etree.ElementTree — API XML ElementTree

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

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

Изменено в версии 3.3: Этот модуль будет использовать быструю реализацию, когда она доступна. Модуль xml.etree.cElementTree устарел.

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

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

Учебник

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

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

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

Разбор XML

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

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

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

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

Или напрямую из строки:

root = ET.fromstring(country_data_as_string)

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

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

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

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

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

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

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

Примечание

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

API извлечения для неблокирующего разбора

Большинство функций разбора, предоставляемых этим модулем, требуют, чтобы весь документ был прочитан сразу же, прежде чем возвращать любой результат. Можно использовать XMLParser и поставлять данные в него постепенно, но это API "нажатия", который вызывает методы на целевом обработчике событий, что слишком низкоуровнево и неудобно для большинства потребностей. Иногда пользователю действительно нужно, чтобы он мог анализировать XML постепенно, не блокируя операции, при этом пользуясь удобством полностью построенных объектов Element.

Самым мощным инструментом для этого является XMLPullParser. Он не требует блокирующего чтения для получения данных XML и вместо этого получает данные постепенно с помощью вызовов XMLPullParser.feed(). Чтобы получить проанализированные XML-элементы, вызовите XMLPullParser.read_events(). Вот пример:

>>> parser = ET.XMLPullParser(['start', 'end'])
>>> parser.feed('<mytag>sometext')
>>> list(parser.read_events())
[('start', <Element 'mytag' at 0x7fa66db2be58>)]
>>> parser.feed(' more text</mytag>')
>>> for event, elem in parser.read_events():
...     print(event)
...     print(elem.tag, 'text=', elem.text)
...
end

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

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

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

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

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

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

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

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

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

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

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

Предположим, что мы хотим добавить единицу к рангу каждой страны и добавить атрибут updated к элементу ранга:

>>> for rank in root.iter('rank'):
...     new_rank = int(rank.text) + 1
...     rank.text = str(new_rank)
...     rank.set('updated', 'yes')
...
>>> tree.write('output.xml')

Наш XML теперь выглядит так:

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

Мы можем удалить элементы с помощью Element.remove(). Предположим, что мы хотим удалить все страны с рейтингом выше 50:

>>> for country in root.findall('country'):
...     # using root.findall() to avoid removal during traversal
...     rank = int(country.find('rank').text)
...     if rank > 50:
...         root.remove(country)
...
>>> tree.write('output.xml')

Обратите внимание, что одновременное изменение во время итерации может привести к проблемам, как и при итерации и изменении списков или словарей Python. Поэтому в примере сначала собираются все соответствующие элементы с помощью root.findall(), а затем выполняется итерация по списку совпадений.

Наш XML теперь выглядит так:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
</data>

Создание XML-документов

Функция SubElement() также предоставляет удобный способ создания новых подэлементов для данного элемента:

>>> a = ET.Element('a')
>>> b = ET.SubElement(a, 'b')
>>> c = ET.SubElement(a, 'c')
>>> d = ET.SubElement(c, 'd')
>>> ET.dump(a)
<a><b /><c><d /></c></a>

Анализ XML с именованными пространствами

Если входной XML содержит пространства имен, теги и атрибуты с префиксами в форме prefix:sometag расширяются до {uri}sometag где префикс заменяется полным URI. Кроме того, если существует пространство имен по умолчанию, этот полный URI добавляется ко всем тегам без префикса.

Вот пример XML, который включает два пространства имен, одно с префиксом «fictional», а другое — в качестве пространства имен по умолчанию:

<?xml version="1.0"?>
<actors xmlns:fictional="http://characters.example.com"
        xmlns="http://people.example.com">
    <actor>
        <name>John Cleese</name>
        <fictional:character>Lancelot</fictional:character>
        <fictional:character>Archie Leach</fictional:character>
    </actor>
    <actor>
        <name>Eric Idle</name>
        <fictional:character>Sir Robin</fictional:character>
        <fictional:character>Gunther</fictional:character>
        <fictional:character>Commander Clement</fictional:character>
    </actor>
</actors>

Один из способов поиска и изучения этого примера XML — вручную добавить URI к каждому тегу или атрибуту в xpath функции find() или findall():

root = fromstring(xml_text)
for actor in root.findall('{http://people.example.com}actor'):
    name = actor.find('{http://people.example.com}name')
    print(name.text)
    for char in actor.findall('{http://characters.example.com}character'):
        print(' |-->', char.text)

Лучший способ поиска в примере XML с именованными пространствами — создать словарь со своими префиксами и использовать их в функциях поиска:

ns = {'real_person': 'http://people.example.com',
      'role': 'http://characters.example.com'}

for actor in root.findall('real_person:actor', ns):
    name = actor.find('real_person:name', ns)
    print(name.text)
    for char in actor.findall('role:character', ns):
        print(' |-->', char.text)

Эти два подхода оба выдают:

John Cleese
 |--> Lancelot
 |--> Archie Leach
Eric Idle
 |--> Sir Robin
 |--> Gunther
 |--> Commander Clement

Дополнительные ресурсы

См. http://effbot.org/zone/element-index.htm для учебников и ссылок на другие документы.

Поддержка XPath

Этот модуль предоставляет ограниченную поддержку выражений XPath для поиска элементов в дереве. Цель состоит в поддержке небольшого подмножества сокращенной синтаксической конструкции; полный движок XPath выходит за рамки данного модуля.

Пример

Вот пример, демонстрирующий некоторые возможности XPath модуля. Мы будем использовать countrydata XML-документ из раздела Разбор XML:

import xml.etree.ElementTree as ET

root = ET.fromstring(countrydata)

# Top-level elements
root.findall(".")

# All 'neighbor' grand-children of 'country' children of the top-level
# elements
root.findall("./country/neighbor")

# Nodes with name='Singapore' that have a 'year' child
root.findall(".//year/..[@name='Singapore']")

# 'year' nodes that are children of nodes with name='Singapore'
root.findall(".//*[@name='Singapore']/year")

# All 'neighbor' nodes that are the second child of their parent
root.findall(".//neighbor[2]")

Для XML с именованными пространствами используйте обычную квалифицированную {namespace}tag запись:

# All dublin-core "title" tags in the document
root.findall(".//{http://purl.org/dc/elements/1.1/}title")

Поддерживаемый синтаксис XPath

Синтаксис

Значение

tag

Выбирает все дочерние элементы с заданным тегом. Например, spam выбирает все дочерние элементы с именем spam, а spam/egg выбирает всех внуков с именем egg во всех дочерних элементах с именем spam. {namespace}* выбирает все теги в заданном пространстве имен, {*}spam выбирает теги с именем spam в любом (или отсутствующем) пространстве имен, и {}* выбирает только теги, которые не находятся в пространстве имен.

Изменено в версии 3.8: Добавлена поддержка звездочных шаблонов.

*

Выбирает все дочерние элементы, включая комментарии и инструкции обработки. Например, */egg выбирает всех внуков с именем egg.

.

Выбирает текущий узел. Это в основном полезно в начале пути, чтобы указать, что это относительный путь.

//

Выбирает все подэлементы на всех уровнях ниже текущего элемента. Например, .//egg выбирает все egg элементы во всем дереве.

..

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

[@attrib]

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

[@attrib='value']

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

[tag]

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

[.='text']

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

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

[tag='text']

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

[position]

Выбирает все элементы, расположенные в заданной позиции. Позиция может быть целым числом (1 — первая позиция), выражением last() (для последней позиции) или позицией, относительной к последней позиции (например, last()-1).

Предикаты (выражения в квадратных скобках) должны предшествовать имени тега, звездочке или другому предикату. position предикаты должны предшествовать имени тега.

Ссылка

Функции

xml.etree.ElementTree.canonicalize(xml_data=None, *, out=None, from_file=None, **options)

Функция преобразования C14N 2.0.

Канонизация — это способ нормализации XML-вывода, который позволяет сравнивать байт за байтом и создавать цифровые подписи. Она ограничивает свободу XML-сериализаторов и вместо этого генерирует более ограниченное XML-представление. Основные ограничения касаются размещения деклараций пространства имён, порядка атрибутов и игнорируемых пробелов.

Эта функция принимает на вход строку XML-данных (xml_data) или путь к файлу или объект-подобный файлу (from_file), преобразует её в каноническую форму и записывает её в объект-подобный файл out, если он предоставлен, или возвращает её в виде текстовой строки, если нет. Выходной файл получает текст, а не байты. Поэтому он должен быть открыт в текстовом режиме с кодировкой utf-8.

Типичные применения:

xml_data = "<root>...</root>"
print(canonicalize(xml_data))

with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file:
    canonicalize(xml_data, out=out_file)

with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file:
    canonicalize(from_file="inputfile.xml", out=out_file)

Настройка options выглядит следующим образом:

  • with_comments: устанавливается в значение true для включения комментариев (по умолчанию: false)
  • strip_text: устанавливается в значение true для удаления пробелов перед и после текстового содержимого

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

  • rewrite_prefixes: устанавливается в значение true для замены префиксов пространства имён на «n{число}»

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

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

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

  • 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.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).

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

xml.etree.ElementTree.register_namespace(prefix, uri)

Регистрация префикса пространства имён. Регистр глобальный, и любое существующее соответствие для заданного префикса или URI пространства имён будет удалено. prefix — префикс пространства имён. uri — URI пространства имён. Тэги и атрибуты в этом пространстве имён будут сериализованы с заданным префиксом, если это возможно.

Новое в версии 3.2.

xml.etree.ElementTree.SubElement(parent, tag, attrib={}, **extra)

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

Имя элемента, имена атрибутов и значения атрибутов могут быть либо строками байтов, либо строками Unicode. parent — родительский элемент. tag — имя дочернего элемента. attrib — необязательный словарь, содержащий атрибуты элемента. extra содержит дополнительные атрибуты, заданные в качестве ключевых аргументов. Возвращает экземпляр элемента.

xml.etree.ElementTree.tostring(element, encoding="us-ascii", method="xml", *, xml_declaration=None, default_namespace=None, short_empty_elements=True)

Генерирует строковое представление XML-элемента, включая все дочерние элементы. element — экземпляр Element. encoding 1 — кодировка вывода (по умолчанию US-ASCII). Используйте encoding="unicode" для генерации строки Unicode (в противном случае генерируется байтовая строка). method — либо "xml", "html" или "text" (по умолчанию "xml"). xml_declaration, default_namespace и short_empty_elements имеют то же значение, что и в ElementTree.write(). Возвращает (при необходимости) закодированную строку, содержащую XML-данные.

Новое в версии 3.4: Параметр short_empty_elements.

Новое в версии 3.8: Параметры xml_declaration и default_namespace.

Изменено в версии 3.8: Функция tostring() теперь сохраняет порядок атрибутов, указанный пользователем.

xml.etree.ElementTree.tostringlist(element, encoding="us-ascii", method="xml", *, xml_declaration=None, default_namespace=None, short_empty_elements=True)

Генерирует строковое представление XML-элемента, включая все дочерние элементы. element — экземпляр Element. encoding 1 — кодировка вывода (по умолчанию US-ASCII). Используйте encoding="unicode" для генерации строки Unicode (в противном случае генерируется байтовая строка). method — либо "xml", "html" или "text" (по умолчанию "xml"). xml_declaration, default_namespace и short_empty_elements имеют то же значение, что и в ElementTree.write(). Возвращает список (при необходимости) закодированных строк, содержащих XML-данные. Он не гарантирует никакого конкретного порядка, за исключением того, что b"".join(tostringlist(element)) == tostring(element).

Новое в версии 3.2.

Новое в версии 3.4: Параметр short_empty_elements.

Новое в версии 3.8: Параметры xml_declaration и default_namespace.

Изменено в версии 3.8: Функция tostringlist() теперь сохраняет порядок атрибутов, указанный пользователем.

xml.etree.ElementTree.XML(text, parser=None)

Парсит XML-раздел из константы строки. Эта функция может использоваться для встраивания «XML-литералов» в код Python. text — строка, содержащая XML-данные. parser — необязательный экземпляр парсера. Если не указан, используется стандартный парсер XMLParser. Возвращает экземпляр Element.

xml.etree.ElementTree.XMLID(text, parser=None)

Парсит XML-раздел из константы строки и также возвращает словарь, который отображает идентификаторы элементов на элементы. text — строка, содержащая XML-данные. parser — необязательный экземпляр парсера. Если не указан, используется стандартный парсер XMLParser. Возвращает кортеж, содержащий экземпляр Element и словарь.

Поддержка XInclude

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

Пример

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

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

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

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

from xml.etree import ElementTree, ElementInclude

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

ElementInclude.include(root)

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

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

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

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

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

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

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

Справочник

Функции

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

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

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

Эта функция расширяет директивы XInclude. elem — корневой элемент. loader — необязательный загрузчик ресурсов. Если опущен, по умолчанию используется default_loader(). Если задан, он должен быть вызываемым объектом, реализующим тот же интерфейс, что и default_loader(). Возвращает расширенный ресурс. Если режим парсинга — "xml", это экземпляр ElementTree. Если режим парсинга — «text», это строка Unicode. Если загрузчик завершается ошибкой, он может вернуть None или вызвать исключение.

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

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

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

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

getchildren()

Устаревшее начиная с версии 3.2, будет удалено в версии 3.9: Используйте list(elem) или итерацию.

getiterator(tag=None)

Устаревшее начиная с версии 3.2, будет удалено в версии 3.9: Используйте метод Element.iter() вместо этого.

insert(index, subelement)

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

iter(tag=None)

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

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

iterfind(match, namespaces=None)

Ищет все соответствующие дочерние элементы по имени тега или пути. Возвращает итерируемый объект, возвращающий все соответствующие элементы в порядке документа. namespaces — необязательное отображение префикса пространства имен на полное имя.

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

itertext()

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

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

makeelement(tag, attrib)

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

remove(subelement)

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

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

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

element = root.find('foo')

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

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

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

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

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

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

Объекты ElementTree

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

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

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

_setroot(element)

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

find(match, namespaces=None)

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

findall(match, namespaces=None)

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

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

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

getiterator(tag=None)

Устарело начиная с версии 3.2, будет удалено в версии 3.9: Используйте метод ElementTree.iter() вместо него.

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 истинны, комментарии/инструкции обработки будут вставлены в дерево, если они встречаются внутри корневого элемента (но не вне его).

close()

Очищает буферы конструктора и возвращает элемент документа верхнего уровня. Возвращает экземпляр Element.

data(data)

Добавляет текст к текущему элементу. data — строка. Это должна быть либо строка байтов, либо строка Юникода.

end(tag)

Закрывает текущий элемент. tag — имя элемента. Возвращает закрытый элемент.

start(tag, attrs)

Открывает новый элемент. tag — имя элемента. attrs — словарь, содержащий атрибуты элемента. Возвращает открытый элемент.

comment(text)

Создаёт комментарий с заданным текстом text. Если insert_comments истинно, это также добавит его в дерево.

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

pi(target, text)

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

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

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

doctype(name, pubid, system)

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

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

start_ns(prefix, uri)

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

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

end_ns(prefix)

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

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

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

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

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

Объекты XMLParser

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

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

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

close()

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

feed(data)

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

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

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

Объекты XMLPullParser

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

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

feed(data)

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

close()

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

read_events()

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

  • start, end: текущий элемент.
  • comment, pi: текущий комментарий/инструкция обработки.
  • start-ns: кортеж (prefix, uri), определяющий сопоставление объявленных пространств имен.
  • end-ns: None (это может измениться в будущей версии)

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

Примечание

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

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

Введено в версии 3.4.

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

Исключения

class xml.etree.ElementTree.ParseError

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

code

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

position

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

Примечания

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

Spec-Zone.ru

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