2011-09-19 11 views
11

tengo el siguiente código HTMLpitón LXML anexar elemento tras otro elemento

<div id="contents"> 
    <div id="content_nav"> 
     something goes here 
    </div> 
    <p> 
     some contents 
    </p> 
</div> 

Para solucionar algún problema de CSS, quiero añadir una etiqueta div <div style="clear:both"></div> después de los content_nav div como este

<div id="contents"> 
    <div id="content_nav"> 
     something goes here 
    </div> 

    <div style="clear:both"></div> 

    <p> 
     some contents 
    </p> 
</div> 

Lo estoy haciendo de esta manera:

import lxml.etree 

tree = lxml.etree.fromString(inputString, parser=lxml.etree.HTMLParser()) 

contentnav = tree.find(".//div[@id='content_nav']") 
contentnav.append(lxml.etree.XML("<div style='clear: both'></div>")) 

Pero eso no funciona termina el nuevo div justo después de content_nav div pero dentro.

<div id="content_nav"> 
    something goes here 
    <div style="clear:both"></div> 
</div> 

¿Hay alguna manera de añadir un div en medio de content_nav div y algunos p como que en el interior contents?

Gracias

+0

CSS única solución: http://www.quirksmode.org/css/clearing.html –

Respuesta

24

en lugar de añadir a contentnav, subir a la matriz (contentdiv) y insert la nueva div en un índice en particular. Para encontrar ese índice, use contentdiv.index(contentnav), que da el índice de contentnav dentro de contentdiv. Agregar uno a eso le da el índice deseado.

import lxml.etree as ET 

content='''\ 
<div id="contents"> 
    <div id="content_nav"> 
     something goes here 
    </div> 
    <p> 
     some contents 
    </p> 
</div> 
''' 
tree = ET.fromstring(content, parser=ET.HTMLParser()) 
contentnav = tree.find(".//div[@id='content_nav']") 
contentdiv = contentnav.getparent() 
contentdiv.insert(contentdiv.index(contentnav)+1, 
        ET.XML("<div style='clear: both'></div>")) 
print(ET.tostring(tree)) 

rendimientos

<html><body><div id="contents"> 
    <div id="content_nav"> 
     something goes here 
    </div> 
    <div style="clear: both"/><p> 
     some contents 
    </p> 
</div></body></html> 
+0

Sí, lo hice lo mismo después de hacer la pregunta. :) –

2

Creo que una función genérica abordar la cuestión "insertar un elemento tras otro elemento" podría ser útil, incluso si es sólo una reformulación de la respuesta aceptada:

def insert_after(element, new_element): 
    parent = element.getparent() 
    parent.insert(parent.index(element)+1, new_element) 

que permite insertar un new_element después de una element existente con sólo

insert_after(element, new_element) 
+0

Todo lo que has hecho es volver a implementar 'element.appendnext()'. – shrewmouse

+0

@Shrewmouse Supongo que te refieres a 'element.addnext()'. No sé cuándo se agregó a la API, pero ahora definitivamente es la mejor solución. – mmj

1

Uso addprevious y addnext para anteponiendo y añadiendo hermanos.

Un elemento etree tiene dos métodos: addprevious y addnext para hacer exactamente lo que usted desea.

import lxml.etree as ET 

content='''\ 
<div id="contents"> 
    <div id="content_nav"> 
     something goes here 
    </div> 
    <p> 
     some contents 
    </p> 
</div> 
''' 
tree = ET.fromstring(content, parser=ET.HTMLParser()) 
contentnav = tree.find(".//div[@id='content_nav']") 
contentnav.addnext(ET.XML("<div style='clear: both'></div>")) 
print(ET.tostring(tree)) 

Salida:

<html><body><div id="contents"> 
    <div id="content_nav"> 
     something goes here 
    </div><div style="clear: both"/> 
    <p> 
     some contents 
    </p> 
</div> 
</body></html> 
Cuestiones relacionadas