Python и XML: парсинг, чтение и обработка данных с примерами

0
14

Краткая памятка по работе с XML в Python

  1. Выберите библиотеку: ElementTree для простых задач, lxml для продвинутых.
  2. Для чтения файла используйте ET.parse() или ET.fromstring().
  3. Получите корневой элемент через.getroot().
  4. Ищите элементы с помощью find(), findall() или iter().
  5. Читайте текст элемента через.text, атрибуты — через.attrib или.get().
  6. Изменяйте текст и атрибуты прямым присваиванием.
  7. Создавайте новые элементы через Element() и SubElement().
  8. Записывайте XML в файл через tree.write().
  9. Для больших файлов используйте iterparse() для потоковой обработки.
  10. Не забывайте про пространства имен при работе со сложными XML.
  11. Тестируйте код на небольших примерах перед запуском на реальных данных.
  12. Используйте XPath в lxml для сложных запросов к дереву.

Основы XML и его роль в обмене данными

Python и парсинг - изображение номер один
Python и парсинг — изображение номер один

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 стала для меня одним из базовых и необходимых навыков.

Efficient - изображение номер два
Efficient — изображение номер два

Встроенные библиотеки Python для обработки XML

Python - изображение номер три
Python — изображение номер три

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

Reading - изображение номер четыре
Reading — изображение номер четыре

Шаг 1) Внутри файла мы видим имя, фамилию, дом и навыки (SQL, Python, Testing и Business)

XML - изображение номер пять
XML — изображение номер пять

Шаг 2) После того, как мы спарсим документ, мы выведем «имя узла» корня документа и «первый дочерний тэг». Tagname и nodename являются стандартными свойствами файла XML.

Как делать парсинг - изображение номер шесть
Как делать парсинг — изображение номер шесть

Мы используем функцию parse в minidom XML для загрузки и парсинга файла XML

Мы хотим вывести имя файла и дочерний тэг, поэтому объявляем это в функции print

Запустите код. Он выведет имя узла (#document) из файла XML и первый дочерний тэг (employee) из файла XML.

Примечание: Nodename и tagname являются стандартными именами или свойствами XML dom. В случае, если вы не знакомы с этим типом именования.

Шаг 3) Мы также можем вызвать список тегов XML из документа XML и вывести его. Здесь мы вывели набор навыков, таких как SQL, Python, Testing и Business.

Using - изображение номер семь
Using — изображение номер семь

Объявление переменной expertise, из которой мы будем извлекать всю информацию сотрудника

Как парсить XML с помощью ElementTree

Python parse xml - изображение номер восемь
Python parse xml — изображение номер восемь

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

XML parsing using - изображение номер девять
XML parsing using — изображение номер девять

Таблица №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();

ЧИТАТЬ ТАКЖЕ:  Python sort и sorted: в чем разница и как выбрать метод сортировки

Таблица №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: чтение и навигация

How to - изображение номер одиннадцать
How to — изображение номер одиннадцать

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

Create - изображение номер двенадцать
Create — изображение номер двенадцать

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)

ЧИТАТЬ ТАКЖЕ:  Правильное именование классов в Python: синтаксис, self и подклассы

Для модификации существующего 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-узел

Learn - изображение номер тринадцать
Learn — изображение номер тринадцать

Мы можем создать новый атрибут с помощью функции «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.