python - leer - ¿Cómo obtengo el contenido XML o HTML completo de un elemento usando ElementTree?
xml python 3 (5)
Dudo que ElementTree sea lo mejor para esto. Pero suponiendo que tienes razones sólidas para usarlo, tal vez podrías intentar eliminar la etiqueta raíz del fragmento:
re.sub(r''(^<%s/b.*?>|</%s/b.*?>$)'' % (element.tag, element.tag), '''', ElementTree.tostring(element))
Es decir, ¿todo el texto y las subetiquetas, sin la etiqueta de un elemento en sí?
Teniendo
<p>blah <b>bleh</b> blih</p>
yo quiero
blah <b>bleh</b> blih
element.text devuelve "blah" y etree.tostring (elemento) devuelve:
<p>blah <b>bleh</b> blih</p>
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= ''<p>blah <b>bleh</b> blih</p>/n''
>>> t=xml.fromstring(s)
>>> "".join( [ t.text ] + [ xml.tostring(e) for e in t.getchildren() ] )
''blah <b>bleh</b> blih''
>>>
Cola no es necesaria.
No tengo idea de si una biblioteca externa podría ser una opción, pero de todos modos, suponiendo que haya una <p>
con este texto en la página, una solución jQuery sería:
alert($(''p'').html()); // returns blah <b>bleh</b> blih
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, particularmente si la pregunta está limitada a HTML. Pero los documentos son intrínsecamente desordenados, y la profundidad de anidación de elementos suele ser imposible de predecir.
Para simular el getTextContent () de DOM, tendrías que usar un mecanismo recursivo (muy) simple.
Para obtener solo el texto simple:
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 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 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 una regla rígida sobre cuándo un estilo de texto indica un límite de palabra y cuándo no: superíndice inmediatamente después de una palabra (sin espacio en blanco) significa una palabra separada en todos los casos de uso que puedo imagina. OTOH a veces puede encontrar, por ejemplo, un documento donde la primera letra está en negrita por algún motivo, o tal vez utiliza un estilo diferente para la primera letra para representarlo en mayúscula, en lugar de simplemente usar el carácter UC normal.
¡Y, por supuesto, cuanto menos "centrada en el inglés" sea esta discusión, mayores serán las sutilezas y complejidades!