поиск элементов по атрибуту с помощью lxml - PullRequest
43 голосов
/ 23 февраля 2011

Мне нужно проанализировать XML-файл, чтобы извлечь некоторые данные.Мне нужны только некоторые элементы с определенными атрибутами, вот пример документа:

<root>
    <articles>
        <article type="news">
             <content>some text</content>
        </article>
        <article type="info">
             <content>some text</content>
        </article>
        <article type="news">
             <content>some text</content>
        </article>
    </articles>
</root>

Здесь я хотел бы получить только статью с типом «новости».Какой самый эффективный и элегантный способ сделать это с помощью lxml?

Я пробовал с помощью метода find, но он не очень хорош:

from lxml import etree
f = etree.parse("myfile")
root = f.getroot()
articles = root.getchildren()[0]
article_list = articles.findall('article')
for article in article_list:
    if "type" in article.keys():
        if article.attrib['type'] == 'news':
            content = article.find('content')
            content = content.text

Ответы [ 2 ]

71 голосов
/ 23 февраля 2011

Вы можете использовать xpath, например, root.xpath("//article[@type='news']")

Это выражение xpath вернет список всех <article/> элементов с атрибутами "type" со значением "news".Затем вы можете перебрать его, чтобы сделать то, что вы хотите, или передать его куда угодно.

Чтобы получить только текстовое содержимое, вы можете расширить xpath следующим образом:

root = etree.fromstring("""
<root>
    <articles>
        <article type="news">
             <content>some text</content>
        </article>
        <article type="info">
             <content>some text</content>
        </article>
        <article type="news">
             <content>some text</content>
        </article>
    </articles>
</root>
""")

print root.xpath("//article[@type='news']/content/text()")

, и это будетвывод ['some text', 'some text'].Или, если вы просто хотите элементы содержимого, это будет "//article[@type='news']/content" - и т. Д.

9 голосов
/ 02 февраля 2015

Только для справки, вы можете достичь того же результата с findall:

root = etree.fromstring("""
<root>
    <articles>
        <article type="news">
             <content>some text</content>
        </article>
        <article type="info">
             <content>some text</content>
        </article>
        <article type="news">
             <content>some text</content>
        </article>
    </articles>
</root>
""")

articles = root.find("articles")
article_list = articles.findall("article[@type='news']/content")
for a in article_list:
    print a.text
...