xml.etree.ElementTree
— ElementTree XML API
Модуль 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
.
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
к элементу ранга:
>>> 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'):
... # использование root.findall(), чтобы избежать удаления во время обхода
... 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
, где prefix
заменяется полным URI. Кроме того, если есть пространство имён по умолчанию, данный полный URI будет
добавлен ко всем тегам без префикса.
Вот пример XML, который включает два пространства имён, одно с префиксом «fictional», а другое служит пространством имён по умолчанию:
<?xml version="1.0"?>
<actors xmlns:fictional="http://characters.example.com"
xmlns="http://people.example.com">
<actor>
<name>John Cleese</name>
<fictional:character>Lancelot</fictional:character>
<fictional:character>Archie Leach</fictional:character>
</actor>
<actor>
<name>Eric Idle</name>
<fictional:character>Sir Robin</fictional:character>
<fictional:character>Gunther</fictional:character>
<fictional:character>Commander Clement</fictional:character>
</actor>
</actors>
Один из способов поиска и изучения этого примера XML — вручную добавить URI к
каждому тегу или атрибуту в xpath find()
или
findall()
:
root = fromstring(xml_text)
for actor in root.findall('{http://people.example.com}actor'):
name = actor.find('{http://people.example.com}name')
print(name.text)
for char in actor.findall('{http://characters.example.com}character'):
print(' |-->', char.text)
Лучший способ поиска в примере XML с пространством имён — создать словарь с вашими собственными префиксами и использовать их в функциях поиска:
ns = {'real_person': 'http://people.example.com',
'role': 'http://characters.example.com'}
for actor in root.findall('real_person:actor', ns):
name = actor.find('real_person:name', ns)
print(name.text)
for char in actor.findall('role:character', ns):
print(' |-->', char.text)
Оба подхода выходят:
John Cleese
|--> Lancelot
|--> Archie Leach
Eric Idle
|--> Sir Robin
|--> Gunther
|--> Commander Clement
Дополнительные ресурсы
См. дополнительный сайт для руководств и ссылок на другие документы.
Поддержка XPath
Модуль предоставляет ограниченную поддержку XPath выражений для поиска элементов в дереве. Цель состоит в том, чтобы поддерживать небольшое подмножество сокращенного синтаксиса; полный механизм XPath выходит за рамки модуля.
Пример
Далее пример, демонстрирующий некоторые возможности модуля XPath. Мы будем
использовать XML-документ countrydata
из раздела
Парсинг XML:
import xml.etree.ElementTree as ET
root = ET.fromstring(countrydata)
# Элементы верхнего уровня
root.findall(".")
# Все "neighbor" дети "country" детей элементов высшего уровня
root.findall("./country/neighbor")
# Узлы с name='Singapore', содержащий дочерний 'year'
root.findall(".//year/..[@name='Singapore']")
# 'year' узлы, которые являются дочерними узлами узлов с name='Singapore'
root.findall(".//*[@name='Singapore']/year")
# Все "соседние" узлы, которые являются вторым нижестоящим элементом их родителя
root.findall(".//neighbor[2]")
Для XML с пространствами имён использовать обычную квалифицированную нотацию
{namespace}tag
:
# Все дубликатные теги "title" в документе
root.findall(".//{http://purl.org/dc/elements/1.1/}title")
Поддерживаемый синтаксис XPath
Синтаксис | Значение |
---|---|
tag |
Выбирает все дочерние элементы с заданным тегом.
Например, Изменено в версии 3.8: Добавлена поддержка подстановочных знаков звездочки. |
* |
Выбирает все дочерние элементы, включая комментарии и
инструкции по обработке. Например, */egg выбирает
всех внуков с именем egg . |
. |
Выбор текущего узла. В основном полезно в начале пути, чтобы указать, что это относительный путь. |
// |
Выбор всех вложенных элементов на всех уровнях под
текущим элементом. Например, .//egg выбирает все
egg элементы во всем дереве. |
.. |
Выбор родительского элемента. Возвращает None ,
если путь пытается достичь предков начального элемента
(элемент find был вызван). |
[@attrib] |
Выбор всех элементов с заданным атрибут. |
[@attrib='value'] |
Выбирает все элементы, для которых данный атрибут содержит заданное значение. В значение не могут содержаться кавычки. |
[tag] |
Выбор всех элементов, имеющих дочерний элемент с
именем tag . Поддерживаются только непосредственные
дети. |
[.='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{number}» (по умолчанию: false)
- qname_aware_tags: множество имён тегов, поддерживающих qname,
- в которых префиксы должны заменяться текстовым содержимом (по умолчанию: пусто)
- qname_aware_attrs: множество имён атрибутов, поддерживающих qname,
- в которых префиксы должны заменяться текстовым содержимом (по умолчанию: пусто)
- exclude_attrs: множество имён атрибутов, которые не следует сериализовать
- exclude_tags: множество имён тегов, которые не следует сериализовать
В приведенном выше списке опций «набор» относится к любой коллекции или итерации строк, упорядочение не ожидается.
Добавлено в версии 3.8.
-
xml.etree.ElementTree.
Comment
(text=None) Фабрика элементов комментария. Функция фабрика создаёт специальный элемент, который будет сериализован как XML-комментарий стандартным сериализатором. Строка комментария может быть строкой байтов или Юникод строкой. 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 в этой точке не определено. То же самое относится к дочерним элементам; они могут присутствовать, а могут и не присутствовать.Если вам нужен полностью заполненный элемент, ищите вместо этого «конечные» события.
Не рекомендуется, начиная с версии 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) Фабрика субэлемента. Функция создаёт экземпляр элемента и добавляет его к существующему элементу.
Имя элемента, имена атрибутов и значения атрибутов могут быть строками байтов или Юникод строками. 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"
для создания строки Юникод (в противном случае создаётся строка байтов). 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"
для создания Юникод строки (в противном случае создаётся строка байтов). 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
через вспомогательный модуль
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. Если режим парсинга — «текст», это строка Юникод. Если загрузчик не работает, он может вернуть None или вызвать исключение.
-
xml.etree.ElementInclude.
include
(elem, loader=None) Функция расширяет директивы XInclude. elem — корневой элемент. loader — дополнительный загрузчик ресурсов. Если пропущен, по умолчанию используется
default_loader()
. Если задан, то должен быть вызываемый объект, реализующий тот же интерфейс, что иdefault_loader()
. Возвращает расширенный ресурс. Если режим парсинга —"xml"
, то экземпляр ElementTree. Если режим парсинга — «text», то Юникод строка. Если загрузчик не работает, он может вернуть None или вызвать исключение.
Элементные объекты
-
class
xml.etree.ElementTree.
Element
(tag, attrib={}, **extra) Элементный класс. Класс определяет интерфейс Element и предоставляет эталонную реализацию этого интерфейса.
Имя элемента, имена атрибутов и значения атрибутов могут быть строками байтов или строками Юникод. 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"
и tailNone
, и у элемента d есть textNone
и tail"3"
.Чтобы собрать внутренний текст элемента, см.
itertext()
, например"".join(element.itertext())
.Приложения могут хранить в этих атрибутах произвольные объекты.
-
attrib
Словарь, содержащий атрибуты элемента. Обратите внимание, что хотя значение attrib всегда является настоящим изменяемым словарём Python, реализация ElementTree может выбрать использование другого внутреннего представления и создать словарь, только если кто-то об этом попросит. Чтобы воспользоваться преимуществами таких реализаций, по возможности использовать приведенные ниже словарные методы.
Следующие методы, подобные словарю, работают с атрибутами элемента.
-
clear
() Сбрасывает элемент. Функция удаляет все подэлементы, очищает все атрибуты и устанавливает атрибуты текста и хвоста на
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: # осторожно! print("element not found, or element has no subelements") if element is None: print("element not found")
До Python 3.8 порядок сериализации XML-атрибутов элементов был искусственно предсказуем путём сортировки атрибутов по их имени. Основываясь теперь на гарантированном порядке словарей, данное произвольное переупорядочение было удалено в Python 3.8, чтобы сохранить порядок, в котором атрибуты были первоначально проанализированы или созданы пользовательским кодом.
В общем, код пользователя должен стараться не зависеть от определенного порядка атрибутов, учитывая, что Набор информации XML явно исключает порядок атрибутов из передачи информации. Код должен быть готов к работе с любым упорядочиванием при вводе. В случаях, когда требуется детерминированный вывод XML, например для криптографической подписи или наборов тестовых данных каноническая сериализация доступна с помощью функции
canonicalize()
.В случаях, когда канонический вывод неприменим, но определенный порядок атрибутов всё ещё желателен при выводе, код должен стремиться к созданию атрибутов непосредственно в желаемом порядке, чтобы избежать несоответствия восприятия для читателей кода. В случаях, когда этого трудно достичь, перед сериализацией можно применить следующий рецепт, чтобы обеспечить выполнение порядка независимо от создания Element:
def reorder_attributes(root): for el in root.iter(): attrib = el.attrib if len(attrib) > 1: # отрегулировать порядок атрибутов, например путём сортировки attribs = sorted(attrib.items()) attrib.clear() attrib.update(attribs)
-
Объекты ElementTree
-
class
xml.etree.ElementTree.
ElementTree
(element=None, file=None) Класс-оболочка ElementTree. Класс представляет всю иерархию элементов и добавляет некоторую дополнительную поддержку сериализации в стандартный XML и обратно.
element — корневой элемент. Дерево инициализируется содержимым XML file, если указан.
-
_setroot
(element) Заменяет корневой элемент данного дерева. Отбрасывает текущее содержимое дерева и заменяет его заданным элементом. Используйте с осторожностью. element — экземпляр элемента.
-
find
(match, namespaces=None) То же, что и
Element.find()
, начиная с корня дерева.
-
findall
(match, namespaces=None) То же, что и
Element.findall()
, начиная с корня дерева.
-
findtext
(match, default=None, namespaces=None) То же, что и
Element.findtext()
, начиная с корня дерева.
-
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 или Юникод (по умолчанию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") # Находит первое вхождение тега p в body
>>> p
<Element 'p' at 0xb77ec26c>
>>> links = list(p.iter("a")) # Возвращает список всех ссылок
>>> links
[<Element 'a' at 0xb77ec2ac>, <Element 'a' at 0xb77ec1cc>]
>>> for i in 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 или, если задан аргумент тега, часть 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 истинны, комментарии/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()
, а события парсинга транслируются в push API путём вызова обратных вызовов для объекта target. Если target пропущен, используется стандартныйTreeBuilder
. Если задано encoding [1], значение переопределяет кодировку, указанную в файле XML.Изменено в версии 3.8: Параметры теперь только ключевые. Аргумент html больше не поддерживается.
-
close
() Завершает подачу данных в парсер. Возвращает результат вызова метода
close()
из target, переданного во время построения; по умолчанию это элемент документа верхнего уровня.
-
feed
(data) Отдаёт данные парсеру. data — закодированные данные.
XMLParser.feed()
вызывает метод targetstart(tag, attrs_dict)
для каждого открывающего тега, свой методend(tag)
для каждого закрывающего тега, а данные обрабатываются методомdata(data)
. Дополнительные поддерживаемые методы обратного вызова см. в классеTreeBuilder
.XMLParser.close()
вызывает метод targetclose()
.XMLParser
можно использовать не только для построения древовидной структуры. Далее пример подсчёта максимальной глубины XML-файла:>>> from xml.etree.ElementTree import XMLParser >>> class MaxDepth: # Целевой объект парсера ... maxDepth = 0 ... depth = 0 ... def start(self, tag, attrib): # Вызывается для каждого открывающего тега. ... self.depth += 1 ... if self.depth > self.maxDepth: ... self.maxDepth = self.depth ... def end(self, tag): # Вызывается для каждого закрывающего тега. ... self.depth -= 1 ... def data(self, data): ... pass # Нам не нужно ничего делать с данными. ... def close(self): # Вызывается после анализа всех данных. ... 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» нет. См. официальный сайт w3c и iana. |