Самый быстрый/лучший способ просмотра XML с помощью lxml в Python

У меня есть файл XML, который выглядит так:

xml = '''<?xml version="1.0"?>
        <root>
            <item>text</item>
            <item2>more text</item2>
            <targetroot>
                <targetcontainer>
                    <target>text i want to get</target>
                </targetcontainer>
                <targetcontainer>
                    <target>text i want to get</target>
                </targetcontainer>
            </targetroot>
            ...more items
        </root>
'''

С помощью lxml я пытаюсь получить доступ к тексту в элементе ‹ target >. Я нашел решение, но я уверен, что есть лучший и более эффективный способ сделать это. Мое решение:

target = etree.XML(xml)

for x in target.getiterator('root'):
    item1 = x.findtext('item')
    for target in x.iterchildren('targetroot'):
        for t in target.iterchildren('targetcontainer'):
            targetText = t.findtext('target')

Хотя это работает, поскольку дает мне доступ ко всем элементам в корне, а также к целевому элементу, мне трудно поверить, что это наиболее эффективное решение.

Итак, мой вопрос таков: есть ли более эффективный способ доступа к текстам ‹ target >, оставаясь в цикле root, потому что мне также нужен доступ к другим элементам.


person Roland    schedule 17.12.2011    source источник


Ответы (1)


Вы можете использовать XPath:

for x in target.xpath('/root/targetroot/targetcontainer/target'):
    print x.text

Мы запрашиваем все элементы, соответствующие пути. В данном случае путь /root/targetroot/targetcontainer/target, что означает

все элементы <target>, которые находятся внутри элемента <targetcontainer>, внутри элемента <targetroot>, внутри элемента <root>. Кроме того, элемент <root> должен быть корнем документа, поскольку ему предшествует /, что означает начало документа.

Кроме того, ваш XML-документ имел две проблемы. Во-первых, объявление <?xml version="1.0"?> должно быть самым первым в документе — и в этом примере ему предшествует новая строка и пробел. Кроме того, это не тег, и его не следует закрывать, поэтому </xml> в конце вашей строки следует удалить. Я уже отредактировал ваш вопрос в любом случае.

EDIT: это решение еще можно улучшить. Вам не нужно передавать все пути — вы можете просто задать все элементы <target> внутри документа. Для этого перед именем тега ставится две косые черты. Поскольку вам нужны все <target> текстов, независимо от того, где они находятся, это может быть лучшим решением. Таким образом, приведенный выше цикл можно записать так:

for x in target.xpath('//target'):
    print x.text

Я попробовал это сначала, но это не сработало. Проблема, однако, заключалась в проблемах синтаксиса в XML, а не в XPath, но я попробовал другой, более длинный путь и забыл повторить этот. Извиняюсь! В любом случае, я надеюсь, что все же пролил свет на XPath :)

person brandizzi    schedule 17.12.2011
comment
Теги ‹xml› — это моя ошибка, настоящий XML имеет правильный синтаксис. xpath отлично работает, спасибо! Чистый код = чище. - person Roland; 18.12.2011
comment
@ Роланд, на самом деле, его можно сделать еще чище. Я отредактировал ответ, посмотрите! - person brandizzi; 18.12.2011
comment
Спасибо, я понял это, когда читал о xpath. Хорошая редакция однако! - person Roland; 18.12.2011