Содержание
Краткая памятка по работе с XML в Python
- Выберите библиотеку: ElementTree для простых задач, lxml для продвинутых.
- Для чтения файла используйте ET.parse() или ET.fromstring().
- Получите корневой элемент через.getroot().
- Ищите элементы с помощью find(), findall() или iter().
- Читайте текст элемента через.text, атрибуты — через.attrib или.get().
- Изменяйте текст и атрибуты прямым присваиванием.
- Создавайте новые элементы через Element() и SubElement().
- Записывайте XML в файл через tree.write().
- Для больших файлов используйте iterparse() для потоковой обработки.
- Не забывайте про пространства имен при работе со сложными XML.
- Тестируйте код на небольших примерах перед запуском на реальных данных.
- Используйте XPath в lxml для сложных запросов к дереву.
Основы XML и его роль в обмене данными
XML (eXtensible Markup Language) — это язык разметки, который позволяет структурировать данные в формате, понятном как человеку, так и машине. Благодаря своей самоописательной природе, XML остаётся одним из ключевых форматов для хранения и обмена информацией между различными системами. 📄
- Элементов — основных блоков XML с открывающим и закрывающим тегами
- Атрибутов — дополнительных свойств элементов
- Текстового содержимого — данных внутри элементов
- Комментариев — пояснений, не влияющих на обработку
<?xml version=»1.0″ encoding=»UTF-8″?> <book> <title>Мастер и Маргарита</title> <author>Михаил Булгаков</author> <year published=»true»>1967</year> <!— Это комментарий —> </book>
Таблица №1
| Характеристика | Преимущество | Практическое значение |
|---|---|---|
| Платформонезависимость | Работает на любых ОС и устройствах | Упрощает интеграцию между разнородными системами |
| Самоописательность | Структура данных очевидна из разметки | Снижает необходимость в отдельной документации |
| Расширяемость | Возможность добавления новых элементов без нарушения совместимости | Позволяет развивать API без поломки клиентских приложений |
| Строгая валидация | Поддержка DTD/XSD схем для проверки структуры | Гарантирует корректность передаваемых данных |
Несмотря на рост популярности JSON, XML продолжает доминировать в корпоративных системах, SOAP API, конфигурационных файлах, документах Office и многих устоявшихся протоколах обмена данными.
Однажды мне пришлось интегрировать нашу систему с ERP-платформой крупного промышленного клиента. Система поддерживала только обмен данными через XML, причём со сложной и строго валидируемой схемой. Первая неделя ушла на попытки ручной генерации XML-файлов, что привело к бесконечным ошибкам валидации. Всё изменилось, когда я применил ElementTree для автоматического создания документов. Мы написали класс-маппер между нашими объектами и XML-структурой, и буквально за день разрешили проблему, которая мучила команду неделями. С тех пор работа с XML в Python стала для меня одним из базовых и необходимых навыков.
Встроенные библиотеки Python для обработки XML
Python предоставляет несколько встроенных библиотек для работы с XML, каждая из которых имеет свои сильные стороны и особенности применения. Выбор правильного инструмента существенно влияет на эффективность вашего кода. 🛠️
- — легковесный и удобный API для большинства задач
- — реализация DOM API для XML
- — реализация SAX (Simple API for XML) для потоковой обработки
Кроме того, существует популярная сторонняя библиотека lxml, которая предлагает расширенную функциональность и высокую производительность.
Таблица №2
| Библиотека | Парадигма | Производительность | Удобство API | Безопасность |
|---|---|---|---|---|
| ElementTree | Древовидная модель | Средняя | Высокая | Базовая |
| minidom | DOM | Низкая | Средняя | Базовая |
| SAX | Событийная | Высокая | Низкая | Базовая |
| lxml | Древовидная/DOM | Очень высокая | Высокая | Расширенная |
Выбор подходящей библиотеки зависит от конкретных требований вашей задачи:
- ElementTree — оптимальный выбор для большинства повседневных задач парсинга и создания XML
- minidom — удобен, если вам уже знаком DOM API или требуется точный контроль над структурой документа
- SAX — незаменим при обработке очень больших XML-файлов, когда загрузка всего документа в память нецелесообразна
- lxml — рекомендуется для сложных задач с высокими требованиями к производительности и поддержкой XPath, XSLT
Как правило, ElementTree является наиболее сбалансированным решением для большинства Python-разработчиков благодаря интуитивному API и достаточной производительности.
Как парсить XML с помощью minidom
Шаг 1) Внутри файла мы видим имя, фамилию, дом и навыки (SQL, Python, Testing и Business)
Шаг 2) После того, как мы спарсим документ, мы выведем «имя узла» корня документа и «первый дочерний тэг». Tagname и nodename являются стандартными свойствами файла XML.
Мы используем функцию parse в minidom XML для загрузки и парсинга файла XML
Мы хотим вывести имя файла и дочерний тэг, поэтому объявляем это в функции print
Запустите код. Он выведет имя узла (#document) из файла XML и первый дочерний тэг (employee) из файла XML.
Примечание: Nodename и tagname являются стандартными именами или свойствами XML dom. В случае, если вы не знакомы с этим типом именования.
Шаг 3) Мы также можем вызвать список тегов XML из документа XML и вывести его. Здесь мы вывели набор навыков, таких как SQL, Python, Testing и Business.
Объявление переменной expertise, из которой мы будем извлекать всю информацию сотрудника
Как парсить XML с помощью ElementTree
ElementTree — это API для управления XML. ElementTree — это простой способ обработки файлов XML. В качестве примера данных мы используем следующий XML-документ:
<data> <items> <item name=»expertise1″>SQL</item> <item name=»expertise2″>Python</item> </items> </data>
Таблица №3
|
1
2
3
4
5
6
|
<data>
<items>
<item name=«expertise1»>SQL</item>
<item name=«expertise2»>Python</item>
</items>
</data>
|
Чтение XML с использованием ElementTree
Таблица №4
|
1
|
import as ET
|
Таблица №5
|
1
|
root = tree.getroot()
|
import as ET tree = (») root = () # все данные print(‘Expertise Data:’) for elem in root: for subelem in elem: print() #Вывод: #Expertise Data: #SQL #Python
Таблица №6
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
import as ET
tree = ET.parse(»)
root = tree.getroot()
# все данные
print(‘Expertise Data:’)
for elem in root:
for subelem in elem:
print(subelem.text)
#Вывод:
#Expertise Data:
#SQL
#Python
|
Пример XML-парсера
import def main(): # используем функцию parse() для загрузки и парсинга XML файла doc = («»); # выводим узел документа и имя первого дочернего тега print print # получаем список тегов XML из документа и выводим каждый expertise = («expertise») print «%d expertise:» % for skill in expertise: print («name») # создаем новый тег XML и вставляем его в документ newexpertise = («expertise») («name», «BigData») (newexpertise) print » » expertise = («expertise») print «%d expertise:» % for skill in expertise: print («name») if name == «__main__»: main();
Таблица №7
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
import
def main():
# используем функцию parse() для загрузки и парсинга XML файла
doc = .parse(«»);
# выводим узел документа и имя первого дочернего тега
print doc.nodeName
print doc.firstChild.tagName
# получаем список тегов XML из документа и выводим каждый
expertise = doc.getElementsByTagName(«expertise»)
print «%d expertise:» % expertise.length
for skill in expertise:
print skill.getAttribute(«name»)
# создаем новый тег XML и вставляем его в документ
newexpertise = doc.createElement(«expertise»)
newexpertise.setAttribute(«name», «BigData»)
doc.firstChild.appendChild(newexpertise)
print » «
expertise = doc.getElementsByTagName(«expertise»)
print «%d expertise:» % expertise.length
for skill in expertise:
print skill.getAttribute(«name»)
if name == «__main__»:
main();
|
import def main(): # используем функцию parse() для загрузки и парсинга XML файла doc = («»); # выводим узел документа и имя первого дочернего тега print () print () # получаем список тегов XML из документа и выводим каждый expertise = («expertise») print («%d expertise:» %) for skill in expertise: print ((«name»)) # создаем новый тег XML и вставляем его в документ newexpertise = («expertise») («name», «BigData») (newexpertise) print (» «) expertise = («expertise») print («%d expertise:» %) for skill in expertise: print ((«name»)) if __name__ == «__main__»: main();
Таблица №8
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
import
def main():
# используем функцию parse() для загрузки и парсинга XML файла
doc = .parse(«»);
# выводим узел документа и имя первого дочернего тега
print (doc.nodeName)
print (doc.firstChild.tagName)
# получаем список тегов XML из документа и выводим каждый
expertise = doc.getElementsByTagName(«expertise»)
print («%d expertise:» % expertise.length)
for skill in expertise:
print (skill.getAttribute(«name»))
# создаем новый тег XML и вставляем его в документ
newexpertise = doc.createElement(«expertise»)
newexpertise.setAttribute(«name», «BigData»)
doc.firstChild.appendChild(newexpertise)
print (» «)
expertise = doc.getElementsByTagName(«expertise»)
print («%d expertise:» % expertise.length)
for skill in expertise:
print (skill.getAttribute(«name»))
if __name__ == «__main__»:
main();
|
Парсинг XML с ElementTree: чтение и навигация
ElementTree — это мощный и элегантный инструмент для парсинга XML-документов. Его концепция представления элементов в виде объектов Python делает навигацию по дереву XML интуитивно понятной. 🌳
import as ET # Создаем объект ElementTree из файла tree = (») # Получаем корневой элемент root = () # Вывод имени корневого элемента print(f»Корневой элемент: {}») # Вывод всех атрибутов корневого элемента print(f»Атрибуты: {}»)
Для навигации по элементам ElementTree предлагает несколько удобных методов:
- Итерация по дочерним элементам — перебор прямых потомков элемента
- Доступ по индексу — обращение к дочерним элементам как к элементам списка
- Методы find() и findall() — поиск элементов с использованием XPath-подобных выражений
<!— Предположим, у нас есть XML с книгами: —> <library> <book id=»1″> <title>Война и мир</title> <author>Лев Толстой</author> <genre>Роман</genre> <price>750</price> </book> <book id=»2″> <title>Преступление и наказание</title> <author>Фёдор Достоевский</author> <genre>Роман</genre> <price>550</price> </book> </library>
# Итерация по всем книгам for book in (‘./book’): title = (‘title’).text author = (‘author’).text price = float((‘price’).text) book_id = (‘id’) # Получение атрибута print(f»Книга {book_id}: {title} – {author}, Цена: {price} руб.») # Поиск всех романов romance_books = («.//book[genre=’Роман’]») print(f»Найдено романов: {len(romance_books)}») # Поиск книг с ценой выше 600 expensive_books = [(‘title’).text for book in («.//book») if float((‘price’).text) > 600] print(f»Дорогие книги: {‘, ‘.join(expensive_books)}»)
ElementTree поддерживает упрощенную версию XPath для поиска элементов. Вот наиболее полезные XPath-выражения:
- tag — выбирает все дочерние элементы с именем tag
- * — выбирает все дочерние элементы
- //tag — выбирает все элементы с именем tag во всем документе
- ./tag — выбирает дочерние элементы с именем tag относительно текущего элемента
- ../tag — выбирает элементы с именем tag на уровень выше
- tag[@attr=’value’] — выбирает элементы с атрибутом attr, равным ‘value’
При работе с большими XML-файлами важно помнить о производительности. В таких случаях можно использовать итеративный парсинг:
# Итеративный парсинг для больших файлов for event, elem in (‘huge_file.xml’, events=(‘start’, ‘end’)): if event == ‘end’ and == ‘book’: # Обработка элемента book print(f»Найдена книга: {(‘title’).text}») # Очищаем элемент для освобождения памяти ()
Однажды мне пришлось обрабатывать XML-файл размером 12 ГБ с данными медицинских исследований. Первая попытка загрузить весь файл в память с помощью стандартного parse() привела к OutOfMemoryError. Ситуацию спас iterparse(). Мы настроили потоковую обработку, которая обрабатывала каждую запись и сразу же очищала память. Процесс занял около часа, но успешно завершился без сбоев. Главный вывод: при работе с XML всегда оценивайте размер входных данных и выбирайте соответствующий подход к парсингу. ElementTree с его iterparse() — настоящее спасение для анализа гигантских XML-документов, когда память ограничена.
Создание и модификация XML-документов в Python
ElementTree не только отлично справляется с чтением XML, но и предоставляет удобный API для создания новых документов и модификации существующих. Эта функциональность особенно полезна при генерации отчетов, конфигурационных файлов или при подготовке данных для API. 🔄
import as ET # Создаем корневой элемент root = («library») # Добавляем первую книгу book1 = (root, «book») («id», «1») # Устанавливаем атрибут # Добавляем элементы книги title1 = (book1, «title») = «Идиот» author1 = (book1, «author») = «Фёдор Достоевский» # Добавляем вторую книгу аналогичным образом book2 = (root, «book») («id», «2») title2 = (book2, «title») = «Евгений Онегин» author2 = (book2, «author») = «Александр Пушкин» # Создаем объект ElementTree tree = (root) # Записываем в файл с правильной кодировкой и отступами («new_library.xml», encoding=»utf-8″, xml_declaration=True)
К сожалению, стандартный ElementTree не имеет встроенной поддержки форматирования (pretty printing). Для создания читаемого XML с отступами можно использовать такую функцию:
def indent_xml(elem, level=0): «»»Функция для добавления отступов в XML-документ.»»» i = «\n» + level * » » if len(elem): if not or not (): = i + » » if not or not (): = i for elem in elem: indent_xml(elem, level + 1) if not or not (): = i else: if level and (not or not ()): = i # Применение функции indent_xml(root) («formatted_library.xml», encoding=»utf-8″, xml_declaration=True)
Для модификации существующего XML-документа сначала нужно его загрузить:
# Загружаем существующий XML tree = («») root = () # Модификация существующих элементов for book in («./book»): # Увеличиваем цену на 10% price_elem = («price») if price_elem is not None: current_price = float(price_elem.text) price_elem.text = str(round(current_price * 1.1, 2)) # Добавляем новый элемент к каждой книге pub_date = (book, «publication_date») pub_date.text = «2026» # Добавляем новую книгу new_book = (root, «book») new_book.set(«id», «3») title = (new_book, «title») = «Мастер и Маргарита» author = (new_book, «author») = «Михаил Булгаков» # Сохраняем изменения («updated_library.xml», encoding=»utf-8″, xml_declaration=True)
# Удаление элементов for book in («./book»): # Удаляем элемент genre, если он существует genre = («genre») if genre is not None: (genre) # Удаляем книги с ценой ниже 500 price = («price») if price is not None and float() < 500: (book) # Сохраняем результат («filtered_library.xml», encoding=»utf-8″, xml_declaration=True)
При работе с XML-документами полезно понимать различные операции над элементами:
- (subelement) — добавляет дочерний элемент
- (subelements) — добавляет несколько дочерних элементов
- (index, subelement) — вставляет элемент по указанному индексу
- (subelement) — удаляет дочерний элемент
- (key, value) — устанавливает атрибут
- (key, default) — получает значение атрибута
- — словарь атрибутов элемента
При работе с XML важно помнить о безопасности, особенно при чтении XML из ненадежных источников. ElementTree имеет некоторые уязвимости, связанные с атаками XML Entity Expansion. Для безопасной обработки можно использовать defusedxml — библиотеку, которая защищает от таких атак:
Как создать XML-узел
Мы можем создать новый атрибут с помощью функции «createElement», а затем добавить этот новый атрибут или тег к существующим тегам XML. Мы добавили новый тег «BigData» в XML-файл.
Вам нужно написать код, чтобы добавить новый атрибут (BigData) в существующий тег XML
Затем вам нужно вывести тег XML с новыми атрибутами, добавленными к существующему тегу XML.
Чтобы добавить новый XML и вставить его в документ, мы используем код «elements»
Этот код создаст новый тег skill для нашего нового атрибута «Big-data»
Запустите код — появится новый тег «big data» с другим списком навыков.
Продвинутые техники работы с XML через lxml
Библиотека lxml — это мощная альтернатива встроенным XML-парсерам Python. Она базируется на быстрых библиотеках libxml2 и libxslt, написанных на C, что обеспечивает высокую производительность и расширенную функциональность. Для сложных задач обработки XML lxml часто становится незаменимым инструментом. 🚀
Базовый парсинг с lxml похож на ElementTree, но с дополнительными возможностями:
from lxml import etree # Парсинг из файла tree = («») root = () # Парсинг из строки xml_string = »’ <library> <book id=»1″> <title>Преступление и наказание</title> </book> </library> »’ root = (xml_string)
Одним из главных преимуществ lxml является полноценная поддержка XPath, включая все функции и оси стандарта XPath 1.0:
# Использование полного XPath # Найти все книги, у которых цена больше 500 и жанр «Роман» expensive_novels = («//book[price > 500 and genre=’Роман’]») # Найти книги по автору, используя функции XPath tolstoy_books = («//book[contains(author, ‘Толстой’)]») # Использование осей XPath # Найти всех «братьев» элемента (на том же уровне) first_book = («//book[1]») siblings = first_book.xpath(«following-sibling::book») # Поиск по атрибутам books_with_id = («//book[@id]») book_id_1 = («//book[@id=’1′]»)
# Валидация по XSD схеме schema_root = («library_schema.xsd») schema = (schema_root) # Проверка валидности документа is_valid = (tree) if not is_valid: # Вывод ошибок валидации for error in schema.error_log: print(f»Ошибка: {}»)
# Загрузка XSLT шаблона xslt_root = («transform_template.xslt») transform = (xslt_root) # Применение трансформации result_tree = transform(tree) # Сохранение результата result_tree.write(«transformed_output.xml», encoding=»utf-8″, pretty_print=True)
lxml предоставляет удобные возможности для форматированного вывода XML:
# Создание XML с отступами (pretty printing) print((root, encoding=»utf-8″, pretty_print=True).decode(«utf-8»)) # Запись в файл с отступами («», encoding=»utf-8″, xml_declaration=True, pretty_print=True)
Таблица №9
| Функциональность | ElementTree | lxml |
|---|---|---|
| Базовый парсинг | ✓ | ✓ |
| Простые XPath выражения | ✓ (ограниченно) | ✓ |
| Полная поддержка XPath 1.0 | ✗ | ✓ |
| Валидация по схемам | ✗ | ✓ |
| XSLT трансформации | ✗ | ✓ |
| Встроенный pretty print | ✗ | ✓ |
| Производительность | Средняя | Высокая |
| Защита от XXE атак | ✗ (требуется defusedxml) | ✓ (через параметры) |
lxml особенно полезна при работе с XML-пространствами имён, которые часто встречаются в сложных XML-форматах, таких как SOAP, SVG или XHTML:
<!— XML с пространствами имён —> <soap:Envelope xmlns:soap=»/» xmlns:m=»; <soap:Body> <m:GetStockPrice> <m:StockName>IBM</m:StockName> </m:GetStockPrice> </soap:Body> </soap:Envelope>
root = (xml_with_ns) # Определение пространств имён для XPath namespaces = { ‘soap’: ‘/’, ‘m’: » } # Поиск с учётом пространств имён stock_name = (‘//m:StockName’, namespaces=namespaces).text print(f»Название акции: {stock_name}»)
При работе с большими XML-файлами lxml также предлагает итеративный парсинг, аналогичный iterparse() в ElementTree, но с расширенными возможностями:
# Итеративный парсинг больших файлов с lxml for event, elem in («huge_file.xml», events=(‘end’,), tag=»book»): # Обрабатываем только завершающие события для тегов ‘book’ title = («title») author = («author») print(f»Книга: {title} – {author}») # Очищаем память () # Также удаляем ссылки на элемент из родителя while () is not None: del ()
lxml — мощный инструмент, который значительно расширяет возможности работы с XML в Python. Она особенно полезна для проектов, где требуется производительность, валидация схем, трансформации XSLT или продвинутые XPath-запросы.
XML — неизбежная часть современной инфраструктуры разработки, и Python предоставляет исчерпывающий набор инструментов для эффективной работы с этим форматом. От простого парсинга с ElementTree до сложных трансформаций с lxml — выбор правильной библиотеки и подхода зависит от конкретной задачи. Освоив различные техники работы с XML, вы сможете справиться с любыми задачами интеграции, анализа и генерации данных, повысив свою эффективность как разработчика и обеспечив надежность ваших решений.
Часто задаваемые вопросы по работе с XML в Python
Вопрос: Какая библиотека Python лучше всего подходит для начинающих при работе с XML?
Ответ: Для начинающих рекомендуется использовать встроенную библиотеку ElementTree, так как она проста в освоении и не требует установки дополнительных пакетов.
Вопрос: В чем разница между библиотеками xml.etree.ElementTree и lxml?
Ответ: ElementTree встроена в Python и проще, но lxml быстрее, поддерживает XPath, XSLT и более удобна для сложных задач.
Вопрос: Как прочитать XML-файл в Python с помощью ElementTree?
Ответ: Используйте функцию ET.parse(‘file.xml’), которая возвращает объект ElementTree, или ET.fromstring(xml_string) для строки.
Вопрос: Как найти все элементы с определенным тегом в XML?
Ответ: Используйте метод findall(‘tag’) на корневом элементе или iter(‘tag’) для рекурсивного поиска.
Вопрос: Как получить текст внутри XML-элемента?
Ответ: Обратитесь к атрибуту.text элемента, например: element.text.
Вопрос: Как изменить значение атрибута XML-элемента в Python?
Ответ: Присвойте новое значение элементу по ключу: element.set(‘attr_name’, ‘new_value’).
Вопрос: Как создать новый XML-документ с нуля?
Ответ: Создайте корневой элемент с помощью Element(‘root’), затем добавляйте дочерние элементы через SubElement() и запишите в файл через ElementTree().write().
Вопрос: Что такое пространства имен (namespaces) в XML и как с ними работать в Python?
Ответ: Пространства имен предотвращают конфликты имен. В lxml их можно обрабатывать через префиксы в XPath, а в ElementTree — через полные URI.
Вопрос: Как обработать очень большой XML-файл, не загружая его целиком в память?
Ответ: Используйте итеративный парсинг с ET.iterparse() или lxml.etree.iterparse(), который обрабатывает файл по частям.
Вопрос: Как преобразовать XML в словарь Python?
Ответ: Напишите рекурсивную функцию, которая обходит дерево элементов и собирает теги и текст в словарь, или используйте сторонние библиотеки типа xmltodict.























