#python #xml #lxml
#python #xml #lxml
Вопрос:
У меня есть следующий XML-файл:
<root>
<scene name="scene1">
<view ath="0" atv="10"/>
<image url="img1.jgp"/>
<hotspot name="hot1"/>
</scene>
<scene name="scene2">
<view ath="20" atv="10"/>
<image url="img2.jgp"/>
<hotspot name="hot2"/>
</scene>
</root>
Я пишу скрипт на Python с использованием пакета lxml, чтобы получить весь view
тег внутри scene1
. Это:
<view ath="0" atv="10" />
Я прочитал документацию по lxml, но все, что я могу найти, это как получить тег, его атрибуты или содержимое, но не весь тег.
Может ли кто-нибудь хотя бы указать мне правильное направление? Есть ли в lxml функция или метод для достижения этой цели?
Спасибо,
Рафаэль
Комментарии:
1. Проанализируйте файл с
lxml.etree;parse
помощью , используйте выражение XPath для поиска ваших элементов, см.: XPath и XSLT с помощью lxml . Сериализуйте результат с помощью lxml.etree.tostring .2. Обратите внимание: я отредактировал ваш образец XML, потому что он недействителен. Ожидание рецензирования…
Ответ №1:
Содержимое XML представляет собой строку, подобную этой:
content = u"""
<root>
<scene name="scene1">
<view ath="0" atv="10"/>
<image url="img1.jgp"/>
<hotspot name="hot1"/>
</scene>
<scene name="scene2">
<view ath="20" atv="10"/>
<image url="img2.jgp"/>
<hotspot name="hot2"/>
</scene>
</root>
"""
Вы можете проанализировать файл; Но здесь я анализирую StringIO:
tree = etree.parse(io.StringIO(content))
Все загружается в ElementTree
.
Чтобы найти представления, я использую выражение XPath:
views = tree.xpath("//scene/view")
Результатом всегда является список:
for view in views:
print(etree.tostring(view, with_tail=False))
Вы получите:
<view ath="0" atv="10"/>
<view ath="20" atv="10"/>
Ответ №2:
Ваш данный XML-источник содержит некоторые ошибки; Я исправил их, см. Мой источник ниже:
from lxml import etree
source = """
<root>
<scene name="scene1">
<view ath="0" atv="10" />
<image url="img1.jgp" />
<hotspot name="hot1" />
</scene>
<scene name="scene2">
<view ath="20" atv="10" />
<image url="img2.jgp" />
<hotspot name="hot2" />
</scene>
</root>
"""
Для анализа этого источника вы создадите etree:
tree = etree.fromstring(source)
(Для источника, поступающего из файла, используйте etree.parse()
вместо этого.)
Теперь вы можете просматривать проанализированный XML tree
, получив правильный доступ. Мой любимый способ сделать это — перейти с помощью XPaths (освоение их выходит за рамки вашего вопроса):
allViews = tree.xpath('//root/scene/view')
for view in allViews:
print view.attrib
При этом будут напечатаны все атрибуты XML для каждого тега представления, найденного XPath:
{'atv': '10', 'ath': '0'}
{'atv': '10', 'ath': '20'}
Конечно, вы также можете получить доступ к другим атрибутам элементов представления, таким как их встроенный текст (который здесь, конечно, пустой) или их подэлементы (дочерние элементы) (конечно, в вашем примере у них также нет дочерних элементов).
Формулировка вашего вопроса предполагает, что вы, возможно, не поняли того факта, что этот view
объект действительно является «тегом всего представления». Вы можете запросить у view
объекта тег, из которого он состоит ( view
), его атрибуты (см. Выше), его содержимое ( view.text
) и даже его подэлементы ( view.getchildren()
, но их нет).
Вы можете преобразовать проанализированную структуру XML обратно в представление ASCII с помощью вызова etree.tostring(view)
; это вернет строку like '<view ath="20" atv="10"/>n '
. В большинстве случаев вы этого не сделаете.
Вы также можете получить доступ к элементам, просмотреть дочерние элементы элементов:
print tree.getchildren()[1].getchildren()[0].attrib
Это выведет XML-атрибуты 0-го дочернего элемента (a view
) первого дочернего элемента (a scene
) tree
элемента:
{'atv': '10', 'ath': '20'}