2011-01-13 37 views
17

Vấn đề là thế này: Tôi có một mảnh XML như sau:Trong lxml, làm cách nào để xóa thẻ nhưng giữ lại tất cả nội dung?

<fragment>text1 <a>inner1 </a>text2 <b>inner2</b> <c>t</c>ext3</fragment> 

Đối với kết quả này, tôi muốn xoá tất cả <a> - và <c> -Tags, nhưng giữ lại (văn bản) -contents của họ, và childNodes chỉ như họ. Ngoài ra, các <b> -Element nên được bỏ hoang. Kết quả sau đó sẽ giống như vậy

<fragment>text1 inner<d>1</d> text2 <b>inner2</b> text3</fragment> 

Đối với thời điểm hiện tại, tôi sẽ trở lại với một thủ thuật rất bẩn: Tôi sẽ etree.tostring đoạn, loại bỏ các thẻ vi phạm qua regex, và thay thế các đoạn ban đầu với các etree.fromstring kết quả của việc này (không phải là mã thực, nhưng nên đi một cái gì đó như thế này):

from lxml import etree 
fragment = etree.fromstring("<fragment>text1 <a>inner1 </a>text2 <b>inner2</b> <c>t</c>ext3</fragment>") 
fstring = etree.tostring(fragment) 
fstring = fstring.replace("<a>","") 
fstring = fstring.replace("</a>","") 
fstring = fstring.replace("<c>","") 
fstring = fstring.replace("</c>","") 
fragment = etree.fromstring(fstring) 

tôi biết rằng tôi có lẽ có thể sử dụng XSLT để đạt được điều này, và tôi biết rằng lxml có thể tận dụng XSLT , nhưng phải có cách tiếp cận bản địa lxml nhiều hơn?

Để tham khảo: Tôi đã cố gắng đến đó với phần tử lxml.replace, nhưng vì tôi muốn chèn văn bản có nút phần tử trước đây, tôi không nghĩ mình có thể làm điều đó.

Trả lời

31

Hãy thử điều này: http://lxml.de/api/lxml.etree-module.html#strip_tags

>>> etree.strip_tags(fragment,'a','c') 
>>> etree.tostring(fragment) 
'<fragment>text1 inner1 text2 <b>inner2</b> text3</fragment>' 
+0

Cảm ơn, công trình này hoàn hảo. Thuật ngữ "dải" không xảy ra với tôi, hoặc tôi có thể tự tìm ra câu trả lời :) – Thor

+0

Nghiêm túc. Bạn sẽ đến PyCon 2011? Nếu vậy, hãy để tôi mua cho bạn một ly bia, hoặc bất cứ thứ gì bạn thích. Bạn chỉ cần làm đêm của tôi :) – mkelley33

+0

Cũng tuyệt vời: '' etree.strip_elements (đoạn, * ['tag1', 'tag2']) '' – mkelley33

1

Sử dụng chức năng Cleaner của lxml để loại bỏ thẻ từ nội dung html. Dưới đây là một ví dụ để làm những gì bạn muốn. Đối với một tài liệu HTML, Cleaner là một giải pháp chung tốt hơn cho vấn đề hơn là sử dụng strip_elements, bởi vì trong các trường hợp như thế này bạn muốn loại bỏ nhiều hơn chỉ là thẻ; bạn cũng muốn loại bỏ những thứ như thuộc tính onclick = function() trên các thẻ khác.

import lxml 
from lxml.html.clean import Cleaner 
cleaner = Cleaner() 
cleaner.remove_tags = ['p'] 
remove_tags: 

Danh sách thẻ cần xóa. Chỉ các thẻ sẽ bị xóa, nội dung của chúng sẽ bị kéo vào thẻ chính.

Các vấn đề liên quan