Создание, Редактирование и Парсинг XML файла

Python содержит встроенные XML инструменты для парсинга, к которым вы можете получить доступ при помощи модуля xml. В данной статье мы рассмотрим два подмодуля xml:

  • minidom
  • ElementTree

Мы начнем с minidom по той причине, что де-факто он используется в качестве метода парсинга XML. После этого, мы взглянем на то, как использовать ElementTree для этих целей.

Работаем с minidom

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

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

Давайте уделим больше времени на то, чтобы поближе познакомиться с парсингом данного файла в Python при помощи модуля minidom. Это достаточно длинный кусок кода, так что подготовьтесь:

Этот код основан на примере из документации Python и стоит отметить, что, на мой взгляд, он немного уродливый. Давайте его разберем по кусочкам. Параметр url, который мы видим в классе ApptParser, может быть как url так и файлом. В методе getXml, мы используем обработчик исключений для того, чтобы попробовать открыть url. Если это привело к ошибке, значит url – это путь к файлу. Далее мы используем метод парсинга для парсинга XML. Далее мы изымаем node из XML. Мы опустим все условия, так как в данной статье это не принципиально. Наконец, мы возвращаем объект node. Технически, node является объектом XML, и мы передаем его методу handleXml. Чтобы получить все назначения в XML, мы делаем следующее:

После этого, мы передаем эту информацию методу handleAppts. Это большой объем информации. Хорошей идеей будет небольшой рефакторинг этого кода для этой цели, вместо передачи всей этой информации целиком, таким образом мы просто настраиваем переменные класса, после чего вызываем следующий метод без каких-либо аргументов. Я оставлю это в качестве упражнения для читателей. В любом случае, метод handleAppts только создает цикл в каждом назначении и вызывает метод handleAppt, чтобы вытянуть кое-какую дополнительную информации, добавляет данные в список и добавляет этот список в другой список. Идея в том, чтобы закончить со списком списков, которые содержат все соответствующие данные о встречах.

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!

Обратите внимание на то, что метод handleAppt вызывает метод getElement, который, в свою очередь вызывает метод getText. Технически, вы можете пропустить вызов getElement и вызвать getText напрямую. С другой стороны, вам может понадобиться добавить дополнительную обработку в getElement для конвертации текста, или чего-то другого перед возвратом. Например, вам может понадобиться конвертировать целые числа, числа с запятыми или объекты decimal.Decimal. Давайте попробуем еще один пример с minidom, перед тем как двигаться дальше. Мы используем пример XML с сайта MSDN Майкрософт: http://msdn.microsoft.com/en-us/library/ms762271%28VS.85%29.aspx . Сохраните следующий код под названием example.xml

В этом примере мы выполнили парсинг XML, извлекли заголовки книги и вывели их в stdout. Давайте взглянем на код:

Данный код – это только одна короткая функция, которая принимает один аргумент, который является файлом XML. Мы импортируем модуль minidom и даем ему такое же название, чтобы упростить отсылки к нему. Далее мы выполняем парсинг XML. Первые две строки функции очень похожи на те, что были в предыдущем примере. Мы используем метод getElementsByTagName чтобы собрать нужные нам части XML, после чего выполнить итерацию над результатом и извлечь заголовки книги. Так, мы извлекаем объекты заголовков, так что нужно выполнить итерацию этих данных в том числе, а также вытащить обычный текст, по этой причине мы используем вложенные данные цикла. Давайте уделим немного времени на унаследованный модуль xml под названием ElementTree.

Парсинг с ElementTree

В данном разделе, мы научимся создавать XML файлы, редактировать и выполнять парсинг при помощи ElementTree. Для сравнения, мы используем тот же XML, который мы использовали в предыдущем разделе для того, чтобы продемонстрировать разницу в использовании minidom и ElementTree. Вот наш код:

Давайте начнем с изучения того, как создавать такую XML структуру при помощи Python

Как создавать XML при помощи ElementTree

Создание XML при помощи ElementTree – это очень просто. В данном разделе, мы попытаемся создать написанный выше XML в Python. Давайте посмотрим на код:

Если вы запустите этот код, вы должны получить что-то вроде нижеизложенного (возможно в одной строке):

Это очень похоже на исходный код и это, безусловно, действенный XML. Само собой, наши коды отличаются, но весьма похожи. Давайте уделим время для разбора кода и убедиться в том, что мы его хорошо понимаем. Для начала мы создаем корневой элемент при помощи функции Element модуля ElementTree. Далее, мы создаем элемент назначения и добавляем его к root. Далее, мы создаем SubElements, выполнив парсинг назначения объекта Element (appt) в SubElement наряду с именем, например, begin. Далее, для каждого SubElement, мы назначаем их текстовые свойства, для передачи значения. В конце скрипта мы создаем ElementTree и используем его для написания XML в файле. Теперь мы готовы к тому, чтобы научиться редактировать файл!

Как редактировать XML при помощи ElementTree

Редактирование XML при помощи ElementTree это также очень просто. Чтобы все было немного интереснее, мы добавим другой блок назначения в XML:

Теперь мы напишем код для того, чтобы изменить каждое значение тега begin от секунд, начиная с эпохи на что-нибудь более читабельное. Мы используем модуль time python, чтобы облегчить себе жизнь:

Здесь мы создаем объект ElementTree под названием tree и извлечем из него root. Далее мы используем метод iter() чтобы найти все теги, помеченные “begin”. Обратите внимание на то, что метод iter() был добавлен в Python 2.7. В наем цикле for, мы указываем текстовое содержимое каждого объекта, чтобы получить более читабельный временной формат при помощи метода time.ctime(). Вы также можете обратить внимание на то, что нам нужно конвертировать строку для целых чисел, при передаче их к ctime. Результат будет выглядеть примерно следующим образом:

Вы также можете использовать методы ElementTree, такие как find() или findall() для поиска конкретных тегов в вашем XML. Метод find() найдет только первый пример, в то время как findall() найдет каждый тег с указанной отметкой. Это очень полезно при решении задач, возникших при редактировании или при парсинге, что является темой нашего следующего раздела!

Парсинг и ElementTree

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

Вы уже должны понять, что и как работает, но в этом примере и предыдущем мы импортируем cElementTree вместо обычного ElementTree. Разница между этими двумя в том, что cElementTree основан на С, а не на Python, так что он намного быстрее. В любом случае, мы снова создаем объект ElementTree и извлекаем root из него. Обратите внимание на то, что мы выводим root, его тег и атрибуты. Далее мы покажем несколько способов итерации тегов. Первый цикл просто итерирует XML, дочку за дочкой. Таким образом выведется только дочерний код (назначение) с наивысшим уровнем , так что мы добавили оператор if, чтобы проверить дочерний код и выполнить его итерацию. Далее мы берем итератор из объекта tree и также итерируем его. В итоге мы получим ту же информацию, но без дополнительных ступеней, как в первом примере. Третий метод использует корневую функцию getchildren(). Так что нам снова понадобится применить внутренний цикл, чтобы получить все теги дочернего кода и назначения. В последнем примере используется корневой метод iter() для цикла всех тегов, соответствующих строке “begin”.

Как было отмечено в последнем разделе, вы также можете использовать методы find() или findall(), чтобы облегчить поиск конкретных тегов, или набор тегов соответственно. Также обратите внимание на то, что каждый объект Element имеет свой тег и текстовое значение, этим можно воспользоваться для получения необходимой точной информации.

Подведем Итоги

Теперь вы знаете, как использовать minidom для парсинга XML. Вы также освоили ElementTree для создания, редактирования и парсинга XML. Существуют и другие библиотеки вне Python, которые предлагают дополнительные методы для работы с XML. Убедитесь в том, что вы пользуетесь понятным вам инструментом, так как данный вопрос может быть очень сложным и непонятным, если пытаться решить его неправильным инструментом.