2011-02-23 4 views
34

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

<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?

Я попытался с помощью метода найти, но это не очень приятно:

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 

ответ

55

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

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

Чтобы получить только текстовое содержимое, вы можете расширить 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" - и так далее.

7

Просто для справки, вы можете достичь того же результата с 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 
Смежные вопросы