¿Cómo obtengo el contenido XML o HTML completo de un elemento utilizando ElementTree?

Es decir, ¿todo texto y subtags, sin la etiqueta de un elemento en sí?

Teniendo

blah bleh blih

quiero

 blah bleh blih 

element.text devuelve “blah” y etree.tostring (element) devuelve:

 

blah bleh blih

ElementTree funciona perfectamente, tienes que armar la respuesta tú mismo. Algo como esto…

 "".join( [ "" if t.text is None else t.text ] + [ xml.tostring(e) for e in t.getchildren() ] ) 

Gracias a JV y PEZ por señalar los errores.


Editar.

 >>> import xml.etree.ElementTree as xml >>> s= '

blah bleh blih

\n' >>> t=xml.fromstring(s) >>> "".join( [ t.text ] + [ xml.tostring(e) for e in t.getchildren() ] ) 'blah bleh blih' >>>

Cola no es necesaria.

Esta es la solución que terminé usando:

 def element_to_string(element): s = element.text or "" for sub_element in element: s += etree.tostring(sub_element) s += element.tail return s 

Estas son buenas respuestas, que responden a la pregunta del OP, especialmente si la pregunta está limitada a HTML. Pero los documentos son intrínsecamente desordenados, y la profundidad del anidamiento de elementos es generalmente imposible de predecir.

Para simular getTextContent () de DOM, tendría que usar un mecanismo recursivo (muy) simple.

Para obtener sólo el texto desnudo:

 def get_deep_text( element ): text = element.text or '' for subelement in element: text += get_deep_text( subelement ) text += element.tail or '' return text print( get_deep_text( element_of_interest )) 

Para obtener todos los detalles sobre los límites entre el texto sin formato:

 root_el_of_interest.element_count = 0 def get_deep_text_w_boundaries( element, depth = 0 ): root_el_of_interest.element_count += 1 element_no = root_el_of_interest.element_count indent = depth * ' ' text1 = '%s(el %d - attribs: %s)\n' % ( indent, element_no, element.attrib, ) text1 += '%s(el %d - text: |%s|)' % ( indent, element_no, element.text or '', ) print( text1 ) for subelement in element: get_deep_text_w_boundaries( subelement, depth + 1 ) text2 = '%s(el %d - tail: |%s|)' % ( indent, element_no, element.tail or '', ) print( text2 ) get_deep_text_w_boundaries( root_el_of_interest ) 

Ejemplo de salida de un solo para en LibreOffice Writer doc (archivo .fodt):

 (el 1 - attribs: {'{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name': 'Standard'}) (el 1 - text: |Ci-après individuellement la "|) (el 2 - attribs: {'{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name': 'T5'}) (el 2 - text: |Partie|) (el 2 - tail: |" et ensemble les "|) (el 3 - attribs: {'{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name': 'T5'}) (el 3 - text: |Parties|) (el 3 - tail: |", |) (el 1 - tail: | |) 

Uno de los puntos sobre el desorden es que no hay reglas duras y rápidas sobre cuándo un estilo de texto indica un límite de palabra y cuando no lo tiene: el superíndice inmediatamente después de una palabra (sin espacios en blanco) significa una palabra separada en todos los casos de uso que puedo imagina. OTOH a veces puede encontrar, por ejemplo, un documento en el que la primera letra esté en negrita por alguna razón, o tal vez use un estilo diferente para que la primera letra lo represente en mayúscula, en lugar de simplemente usar el carácter normal de UC.

¡Y, por supuesto, cuanto menos se centre el inglés en esta discusión, mayor será la complejidad y las sutilezas!

Dudo que ElementTree sea lo que se use para esto. Pero suponiendo que tenga fuertes razones para usarlo, tal vez podría intentar eliminar la etiqueta raíz del fragmento:

  re.sub(r'(^<%s\b.*?>|$)' % (element.tag, element.tag), '', ElementTree.tostring(element)) 

La mayoría de las respuestas aquí se basan en el analizador XML ElementTree , incluso la respuesta basada en ElementTree regulares de PEZ aún se basa parcialmente en ElementTree.

Todos estos son buenos y adecuados para la mayoría de los casos de uso pero, solo para completarlos, vale la pena señalar que ElementTree.tostring(...) le dará un fragmento equivalente, pero no siempre idéntico a la carga útil original. Si, por alguna extraña razón, que desea extraer el contenido tal como está, debe utilizar una solución basada en expresiones regulares puras. Este ejemplo es cómo uso la solución basada en expresiones regulares.

No tengo idea de si una biblioteca externa podría ser una opción, pero de todos modos, si asumimos que hay una

con este texto en la página, una solución jQuery sería:

 alert($('p').html()); // returns blah bleh blih