Как разобрать XML и получить значения определенного атрибута узла?
У меня есть много строк в XML, и я пытаюсь получить значения конкретного атрибута узла. Вот пример XML:
<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>
Как мне получить доступ к значениям атрибута foobar
? В этом примере я хочу получить "1"
и "2"
.
5 ответ(ов)
xml.etree.ElementTree vs. lxml
Вот некоторые преимущества двух самых популярных библиотек, которые было бы полезно знать перед выбором между ними.
xml.etree.ElementTree:
- Из стандартной библиотеки: не требуется установка дополнительных модулей.
lxml:
- Легко писать XML-декларации: например, нужно ли добавить
standalone="no"
? - Красивый вывод: вы можете получить хорошо отформатированный XML без лишнего кода.
- Функциональность Objectify: позволяет работать с XML так, как если бы это была обычная иерархия объектов Python.
sourceline
позволяет легко получить номер строки элемента XML, который вы используете.- Также доступен встроенный проверщик схем XSD.
В приведенном вами коде происходит парсинг XML-строки с использованием модуля xml.etree.ElementTree
. В этом коде создается XML-дерево, после чего выполняется поиск всех элементов <type>
внутри тега <bar>
. Далее, для каждого найденного элемента выводится значение атрибута foobar
.
Вот код с небольшими исправлениями для корректного вывода (с использованием функции print
в Python 3):
import xml.etree.ElementTree as ET
data = '''<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>'''
tree = ET.fromstring(data)
lst = tree.findall('bar/type')
for item in lst:
print(item.get('foobar'))
Этот код напечатает значения атрибута foobar
для каждого элемента <type>
, что в данном случае будет:
1
2
Таким образом, скрипт успешно извлекает и выводит значения атрибута foobar
из XML-структуры.
Используйте библиотеку pandas. В pandas есть функция read_xml()
, которая отлично подходит для работы с такими плоскими структурами XML.
Вот пример кода:
import pandas as pd
xml = """<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>"""
df = pd.read_xml(xml, xpath=".//type")
print(df)
Вывод будет следующим:
foobar
0 1
1 2
Таким образом, вы сможете легко извлечь данные из вашего XML в удобный формат DataFrame для дальнейшей работы.
В Python есть интерфейс к парсеру XML expat:
xml.parsers.expat
Это парсер, не проводящий валидацию, поэтому ошибки в XML не будут выявлены. Но если вы уверены, что ваш файл корректен, то это вполне приемлемо, и вы, вероятно, сможете получить нужную информацию, отбрасывая лишнее на лету.
В качестве примера, вот как можно использовать этот парсер:
stringofxml = """<foo>
<bar>
<type arg="value" />
<type arg="value" />
<type arg="value" />
</bar>
<bar>
<type arg="value" />
</bar>
</foo>"""
count = 0
def start(name, attr):
global count
if name == 'type':
count += 1
p = expat.ParserCreate()
p.StartElementHandler = start
p.Parse(stringofxml)
print(count) # выводит 4
В этом примере мы создаем строку с XML, устанавливаем обработчик для начала элемента и подсчитываем, сколько раз встречается элемент <type>
. В результате мы получаем количество этих элементов в XML, которое равно 4.
Ваш код на Python правильно разбирает XML-файл и выводит ожидаемые результаты. Давайте разберем его по частям.
Первоначально вы импортируете модуль xml.etree.cElementTree
и загружаете XML-дерево из файла foo.xml
. После этого вы получаете корневой элемент и выводите его тег.
import xml.etree.cElementTree as ET
tree = ET.parse("foo.xml")
root = tree.getroot()
root_tag = root.tag
print(root_tag) # Выводит 'foo'
Следующий блок кода находит все дочерние элементы <type>
, которые находятся внутри <bar>
. Используя метод findall
, вы получаете список этих элементов и перебираете их.
for form in root.findall("./bar/type"):
x = (form.attrib) # Получаем атрибуты элемента <type>
z = list(x) # Преобразуем словарь атрибутов в список
for i in z:
print(x[i]) # Выводим значение каждого атрибута
В этом блоке x
представляет собой словарь атрибутов, который содержит foobar
как ключ. Поскольку в вашем XML два элемента <type>
с разными значениями атрибута foobar
, ваш код корректно выводит их значения в порядке их появления.
Таким образом, вывод программы будет:
foo
1
2
Если у вас есть какие-либо конкретные вопросы по коду или XML, пожалуйста, уточните, и я с радостью помогу!
Почему используется string.join(list), а не list.join(string)?
Создание словаря с помощью генератора словарей
Как получить полный путь к директории текущего файла?
UnicodeDecodeError: Кодек 'charmap' не может декодировать байт X в позиции Y: символ отображается как <неопределённый>
Найти все файлы с расширением .txt в директории на Python