2008-12-19 23 views

Respuesta

5

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 
+0

Eso fallaría cuando no hay texto o cola, ¿no? – PEZ

+0

PEZ, sí, falla cuando no hay texto, solo lo encontró ejecutando mi código y lo solucionó. Tengo muchas instancias sin cola y eso no falla. No estoy seguro por qué. – Pablo

+0

Solo un detalle: + = en cadenas es menos eficiente. Lo mejor es acumular una lista de cadenas y unirlas al final. – cdleary

11

elementtree funciona perfectamente, tiene para armar la respuesta usted mismo. Algo como esto ...

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

Gracias a JV amd 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 necesaria.

+0

Simplemente señalando un error tipográfico - nombre del método - "finall", que creo que debería haber sido "findall". Incluso si se usa findall, esto da como resultado este http://pastebin.com/f6de9a841. Por favor revisa tu respuesta. –

+0

@JV: gracias. Fijo. –

+0

Estoy haciendo algo similar a eso, pero con una apariencia. En realidad te estás perdiendo la cola. – Pablo

-3

ni idea de si una biblioteca externa podría ser una opción, pero de todos modos - asumiendo que hay una <p> con este texto en la página, un jQuery solución sería:

alert($('p').html()); // returns blah <b>bleh</b> blih 
1

dudo elementtree es la cosa para usar para esto. Pero suponiendo que tiene fuertes razones para usarlo tal vez usted podría intentar despojar a la etiqueta raíz del fragmento:

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

Estas son buenas respuestas, las cuales responda la pregunta del OP, especialmente 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 getTextContent de DOM() que tendría que utilizar un mecanismo recursivo (muy) simples.

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 acerca de 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 párrafo en LibreOffice doc escritor (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 dura y rápida 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 pueda imaginar. OTOH a veces puede encontrar, por ejemplo, un documento donde la primera letra está en negrita por alguna razón, 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 primariamente "centrada en el inglés", mayor es la discusión sobre las sutilezas y complejidades.

0

La mayoría de las respuestas se basan en el analizador XML ElementTree, incluso PEZ's regex-based answer todavía se basa parcialmente en ElementTree.

Todos estos son buenos y adecuados para la mayoría de los casos de uso pero, para completar, vale la pena señalar que ElementTree.tostring(...) le dará un fragmento equivalente, pero no siempre idéntico al contenido original. Si, por alguna extraña razón, desea extraer el contenido tal como está, debe usar una solución pura basada en expresiones regulares. This example es la forma en que uso la solución basada en expresiones regulares.

Cuestiones relacionadas