2011-02-23 32 views
34

Tôi cần phải phân tích cú pháp tệp xml để trích xuất một số dữ liệu. tôi chỉ cần một số yếu tố với các thuộc tính nhất định, đây là một ví dụ của tài liệu:tìm các phần tử theo thuộc tính với 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> 

Ở đây tôi muốn để có được chỉ là bài viết với các loại "tin tức". Cách hiệu quả nhất và thanh lịch để làm điều đó với lxml là gì?

Tôi đã thử với phương pháp tìm nhưng nó không phải là rất tốt đẹp:

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 

Trả lời

55

Bạn có thể dùng xpath, ví dụ root.xpath("//article[@type='news']")

Biểu thức xpath này sẽ trả về danh sách tất cả các thuộc tính "loại" có giá trị "tin tức". Sau đó, bạn có thể lặp lại nó để thực hiện những gì bạn muốn hoặc chuyển nó ở bất kỳ đâu.

Để có được chỉ là nội dung văn bản, bạn có thể kéo dài tuổi xpath như vậy:

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()") 

và điều này sẽ ra ['some text', 'some text']. Hoặc nếu bạn chỉ muốn các yếu tố nội dung, nó sẽ là "//article[@type='news']/content" - v.v.

7

Chỉ cần để tham khảo, bạn có thể đạt được kết quả tương tự với 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 
Các vấn đề liên quan