2011-01-13 18 views
17

Problem jest następujący: Mam fragment XML tak:W lxml, jak usunąć tag, ale zachować całą zawartość?

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

na wynik, chcę usunąć wszystkie <a> - i <c> -Tags, ale zachowują swoje (tekstu) -contents i childNodes tylko tak jak oni. Ponadto, <b> -Element powinien pozostać nietknięty. Wynik powinien wyglądać wtedy zatem

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

Na razie, będę powrócić do bardzo brudne sztuczki: Będę etree.tostring fragment, usunąć tagi naruszające poprzez regex i zastąpić oryginalny fragment z etree.fromstring wynik ten (nie prawdziwy kod, ale powinno iść coś takiego):

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) 

wiem, że mogę prawdopodobnie użyć XSLT do osiągnięcia tego celu, i wiem, że lxml mogą skorzystać z XSLT , ale musi być bardziej natywne podejście lxml?

Dla odniesienia: Próbowałem dostać się tam z lxml's element.replace, ale ponieważ chcę wstawić tekst, w którym był wcześniej węzeł elementu, nie sądzę, żebym mógł to zrobić.

Odpowiedz

31

Spróbuj tego: 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

Dzięki, to działa idealnie. Termin "pasek" nie przyszedł mi do głowy, albo sam mogłem znaleźć odpowiedź :) – Thor

+0

Poważnie. Czy będziesz w PyCon 2011? Jeśli tak, pozwól, że kupię ci piwo lub jakikolwiek inny ulubiony napój. Właśnie zrobiłeś moją noc :) – mkelley33

+0

Również niesamowite: '' etree.strip_elements (fragment, * ['tag1', 'tag2']) '' – mkelley33

1

Zastosowanie Cleaner funkcją lxml usunąć tagi html z zawartości. Poniżej znajduje się przykład robienia tego, co chcesz. W przypadku dokumentu HTML, Cleaner jest lepszym ogólnym rozwiązaniem problemu niż użycie elementów strip_elements, ponieważ w takich przypadkach chcesz rozebrać coś więcej niż tylko tag; chcesz także pozbyć się takich rzeczy jak atrybuty onclick = function() na innych znacznikach.

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

Lista tagów do usunięcia. Tylko znaczniki zostaną usunięte, a ich zawartość zostanie przyciągnięta do znacznika nadrzędnego.

Powiązane problemy