Xml.etree.ElementTree.parse: примеры (PYTHON)

Работа с XML через функцию parse в Python
Раздел: XML, Парсинг
xml.etree.ElementTree.parse(source, parser): xml.etree.ElementTree.ElementTree

Функция xml.etree.ElementTree.parse

Функция parse() из модуля xml.etree.ElementTree предназначена для чтения и разбора XML-документов из файла или файлоподобного объекта. Она создает дерево элементов, с которым можно работать в памяти.

Область применения

Функция используется при необходимости обработать XML-данные из файловой системы или потока. Это распространенная задача при работе с конфигурационными файлами, веб-сервисами (SOAP, REST с XML), данными обмена между приложениями.

Аргументы

  • source (строка, путь или файловый объект): Обязательный аргумент. Может быть строкой с путем к файлу, файловым объеком, уже открытым для чтения в бинарном режиме ('rb'), или объектом с методом read (например, io.BytesIO).
  • parser (объект парсера, опционально): Экземпляр класса парсера, например XMLParser. По умолчанию используется стандартный парсер. Позволяет настроить обработку, например, указать кодировку.

Возвращаемое значение

Функция возвращает объект ElementTree, который представляет весь XML-документ как дерево. Корневой элемент этого дерева доступен через метод .getroot().

Примеры использования

Чтение из файла по пути

Базовый сценарий чтения XML из файла.

import xml.etree.ElementTree as ET
tree = ET.parse('config.xml')
root = tree.getroot()
print(root.tag)
<Element 'config' at 0x7f8c0a1e3d40>

Чтение из файлового объекта

Использование уже открытого файла.

import xml.etree.ElementTree as ET
with open('data.xml', 'rb') as f:
    tree = ET.parse(f)
    print(tree.find('item').text)
Пример данных

Чтение из строки в памяти (BytesIO)

Парсинг XML, который хранится в виде строки байтов.

import xml.etree.ElementTree as ET
from io import BytesIO
xml_data = b'<root><child>Content</child></root>'
tree = ET.parse(BytesIO(xml_data))
print(tree.getroot()[0].text)
Content

Использование пользовательского парсера

Указание кодировки через парсер.

import xml.etree.ElementTree as ET
parser = ET.XMLParser(encoding='utf-8')
tree = ET.parse('data_utf8.xml', parser=parser)
# Объект ElementTree создан

Похожие функции в Python

xml.etree.ElementTree.fromstring()

Функция fromstring() разбирает XML непосредственно из строки (тип str или bytes) и возвращает корневой Element, а не все дерево ElementTree. Предпочтительнее для небольших XML-данных, уже находящихся в памяти.

xml.dom.minidom.parse()

Функция из модуля xml.dom.minidom, реализующая Document Object Model (DOM). Возвращает более тяжеловесный объект документа, соответствующий стандарту DOM. Используется при необходимости DOM-интерфейса или XPath 1.0.

xml.sax.parse()

Функция для событийного (SAX) парсинга. Не создает дерево в памяти, а генерирует события при чтении документа. Эффективна для очень больших файлов или когда нужно только извлечь часть данных.

Выбор зависит от задачи: ElementTree.parse - сбалансированный вариант для большинства случаев работы с файлами; fromstring - для строк; minidom - для работы через DOM; sax - для потоковой обработки.

Аналоги в других языках программирования

JavaScript (в среде Node.js)

Модуль xml2js предоставляет асинхронный и синхронный парсинг в объект JavaScript.

const xml2js = require('xml2js');
const fs = require('fs');
const parser = new xml2js.Parser();
const xml = fs.readFileSync('file.xml');
parser.parseString(xml, (err, result) => {
    console.log(result.root.element[0]);
});

Java

Классы DocumentBuilderFactory и DocumentBuilder для DOM-парсинга.

import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
File file = new File("file.xml");
Document doc = DocumentBuilderFactory.newInstance()
                    .newDocumentBuilder().parse(file);

PHP

Функция simplexml_load_file() загружает XML-файл в объект SimpleXML.

$xml = simplexml_load_file('file.xml');
echo $xml->child;

C#

Класс XDocument из пространства имен System.Xml.Linq для загрузки через LINQ to XML.

XDocument doc = XDocument.Load("file.xml");
var element = doc.Root.Element("child");

Основное отличие Python-функции - простота и возвращение собственного объекта ElementTree, а не стандартизированного DOM или специализированного объекта. В других языках чаще реализуется DOM или предоставляется доступ через запросы (LINQ).

Типичные ошибки

Файл не найден

При указании неверного пути возникает исключение FileNotFoundError.

import xml.etree.ElementTree as ET
try:
    tree = ET.parse('несуществующий_файл.xml')
except FileNotFoundError as e:
    print(f"Ошибка: {e}")
Ошибка: [Errno 2] No such file or directory: 'несуществующий_файл.xml'

Некорректный XML

При синтаксической ошибке в XML возникает ParseError.

import xml.etree.ElementTree as ET
from io import BytesIO
xml_data = b'<root><unclosed>' # Незакрытый тег
try:
    tree = ET.parse(BytesIO(xml_data))
except ET.ParseError as e:
    print(f"Ошибка разбора: {e}")
Ошибка разбора: not well-formed (invalid token): line 1, column 16

Передача строки вместо файлового объекта или пути

Функция ожидает путь или объект с методом read. Передача строки с XML-содержимым вызывает ошибку.

import xml.etree.ElementTree as ET
xml_string = '<root></root>'
tree = ET.parse(xml_string)  # Ошибка
FileNotFoundError: [Errno 2] No such file or directory: '<root></root>'

Попытка чтения из файла, открытого в текстовом режиме

Функция требует байтовый поток. Файл должен быть открыт в бинарном режиме ('rb').

import xml.etree.ElementTree as ET
with open('file.xml', 'r') as f:  # Текстовый режим
    tree = ET.parse(f)  # Может привести к ошибке
# TypeError: can't parse from 'TextIOWrapper'

Изменения в последних версиях

В Python 3.4 была добавлена поддержка протокола управления контекстом для объектов ElementTree, возвращаемых функцией parse(). Это позволяет использовать конструкцию with для автоматического закрытия открытого файлового потока.

import xml.etree.ElementTree as ET
# Начиная с Python 3.4
with ET.parse('file.xml') as tree:
    root = tree.getroot()
# Файл автоматически закрыт после выхода из блока with

В Python 3.8 в парсер по умолчанию было добавлено ограничение на обработку сущностей для повышения безопасности. Теперь по умолчанию сущности не разбираются, что предотвращает возможные атаки через XML (например, Billion Laughs).

Расширенные примеры

Парсинг с обработкой пространств имен

Извлечение данных из XML с объявленными пространствами имен.

Пример python
import xml.etree.ElementTree as ET
xml_ns = '''
<root xmlns:f="http://example.com/ns">
  <f:item>Значение1</f:item>
  <item>Значение2</item>
</root>
'''
from io import BytesIO
tree = ET.parse(BytesIO(xml_ns.encode()))
root = tree.getroot()
ns = {'f': 'http://example.com/ns'}
# Поиск с учетом пространства имен
item1 = root.find('f:item', ns)
print(item1.text)
# Поиск без учета пространства имен
for item in root.findall('.//item'):
    print(item.text)
Значение1
Значение2

Итеративная обработка большого файла

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

Пример python
import xml.etree.ElementTree as ET
tree = ET.parse('large_data.xml')
# Поиск всех элементов 'record' в любом месте документа
for record in tree.iterfind('.//record'):
    id = record.find('id').text
    # Обработка записи
    print(f"Обработана запись ID: {id}")
    # Очистка памяти от уже обработанных элементов внутри цикла
    record.clear()

Модификация дерева и сохранение в файл

Чтение, изменение и запись обратно в файл.

Пример python
import xml.etree.ElementTree as ET
tree = ET.parse('settings.xml')
root = tree.getroot()
# Добавление нового элемента
new_elem = ET.Element('newSetting', attrib={'enabled': 'true'})
new_elem.text = '100'
root.append(new_elem)
# Изменение существующего
for elem in root.iter('oldSetting'):
    elem.text = 'updated'
# Удаление элемента
for elem in root.findall('obsoleteSetting'):
    root.remove(elem)
# Сохранение в новый файл
tree.write('settings_modified.xml', encoding='utf-8', xml_declaration=True)

Обработка XML с помощью XPath

Использование метода findall с синтаксисом, похожим на XPath, для сложных запросов.

Пример python
import xml.etree.ElementTree as ET
tree = ET.parse('catalog.xml')
# Поиск всех элементов 'book', у которых цена больше 20
for book in tree.findall("./book[price>'20.00']"):
    title = book.find('title').text
    print(title)
# Поиск первого элемента 'author' в любой книге
author = tree.find('.//author')
if author is not None:
    print(author.text)

питон xml.etree.ElementTree.parse function comments

En
Xml.etree.ElementTree.parse Parse XML document