2011-01-13 6 views
17

El problema es el siguiente: Tengo un fragmento de XML, así:En lxml, ¿cómo elimino una etiqueta pero retengo todo el contenido?

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

Para el resultado, quiero eliminar todos <a> - y <c> -Tags, pero conservan sus -Contenido (texto), y solo childNodes ya que son. Además, el elemento <b> no debe tocarse. El resultado debe entonces busca por lo tanto

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

Por el momento, voy a volver a una muy mala pasada: Voy a etree.tostring el fragmento, eliminar las etiquetas ofensivas a través de expresiones regulares y reemplazar el fragmento original con el resultado de esta etree.fromstring (no el código real, pero debe ser algo así):

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) 

sé que probablemente puedo usar XSLT para lograr esto, y sé que lxml puede hacer uso de XSLT , pero tiene que haber un enfoque nativo más lxml?

Como referencia: He intentado llegar allí con element.replace de lxml, pero como quiero insertar texto donde antes había un nodo de elementos, no creo que pueda hacerlo.

Respuesta

31

Prueba esto: 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

Gracias, esto funciona a la perfección. El término "tira" no se me ocurrió, o podría haber encontrado la respuesta yo mismo :) – Thor

+0

En serio. ¿Vas a estar en PyCon 2011? Si es así, déjame que te compre una cerveza, o cualquiera que sea tu bebida preferida. Usted acaba de hacer mi noche :) – mkelley33

+0

También es impresionante: '' etree.strip_elements (fragmento, * ['tag1', 'tag2']) '' – mkelley33

1

Uso de la función de limpiador lxml para eliminar las etiquetas de contenido HTML. A continuación se muestra un ejemplo para hacer lo que desea. Para un documento HTML, Cleaner es una mejor solución general al problema que el uso de strip_elements, porque en casos como este no se necesita solo una etiqueta; también desea deshacerse de elementos como los atributos onclick = function() en otras etiquetas.

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

una lista de etiquetas de eliminar. Solo se eliminarán las etiquetas y su contenido se subirá a la etiqueta principal.

Cuestiones relacionadas