2012-01-26 19 views
7

Dentro de lxml, ¿es posible, dado un elemento, mover todo en otro lugar en el documento xml sin tener que leer todos sus elementos secundarios y volver a crearlo? Mi mejor ejemplo sería cambiar a los padres. He rebuscado un poco en los documentos pero no he tenido mucha suerte. ¡Gracias por adelantado!Mover un elemento completo con lxml.etree

Respuesta

14

.append, .insert y otras operaciones de hacer que por defecto

>>> from lxml import etree 
>>> tree = etree.XML('<a><b><c/></b><d><e><f/></e></d></a>') 
>>> node_b = tree.xpath('/a/b')[0] 
>>> node_d = tree.xpath('/a/d')[0] 
>>> node_d.append(node_b) 
>>> etree.tostring(tree) # complete 'b'-branch is now under 'd', after 'e' 
'<a><d><e><f/></e><b><c/></b></d></a>' 
>>> node_f = tree.xpath('/a/d/e/f')[0] # Nothing stops us from moving it again 
>>> node_f.append(node_a) # Now 'a' is deep under 'f' 
>>> etree.tostring(tree) 
'<a><d><e><f><b><c/></b></f></e></d></a>' 

Tenga cuidado al mover los nodos que tienen un texto de cola. En lxml, el texto de cola pertenece al nodo y se mueve con él. (También, cuando se elimina un nodo, también se elimina el texto de la cola)

>>> tree = etree.XML('<a><b><c/></b>TAIL<d><e><f/></e></d></a>') 
>>> node_b = tree.xpath('/a/b')[0] 
>>> node_d = tree.xpath('/a/d')[0] 
>>> node_d.append(node_b) 
>>> etree.tostring(tree) 
'<a><d><e><f/></e><b><c/></b>TAIL</d></a>' 

A veces es un efecto deseado, pero a veces se necesita algo así:

>>> tree = etree.XML('<a><b><c/></b>TAIL<d><e><f/></e></d></a>') 
>>> node_b = tree.xpath('/a/b')[0] 
>>> node_d = tree.xpath('/a/d')[0] 
>>> node_a = tree.xpath('/a')[0] 
>>> # Manually move text 
>>> node_a.text = node_b.tail 
>>> node_b.tail = None 
>>> node_d.append(node_b) 
>>> etree.tostring(tree) 
>>> # Now TAIL text stays within its old place 
'<a>TAIL<d><e><f/></e><b><c/></b></d></a>' 
+0

Exactamente lo que necesitaba. ¡Gracias! – Cryptite

+0

Tipo-o ?: node_a debe ser node_b en la línea "node_f.append (node_a) # Ahora 'a' está muy por debajo de 'f'" (también corrige el comentario 'a') –

0

Usted podría utilizar .append(), .insert() métodos para agregar un subelemento al elemento existente:

>>> from lxml import etree 
>>> from_ = etree.fromstring("<from/>") 
>>> to = etree.fromstring("<to/>") 
>>> to.append(from_) 
>>> etree.tostring(to) 
'<to><from/></to>' 
Cuestiones relacionadas