2012-01-26 31 views
7

在lxml中,給定一個元素,有可能在xml文檔的其他地方移動整個東西,而不必讀取它的所有子元素並重新創建它?我最好的例子就是改變父母。我在文檔上翻了一下,但沒有多少運氣。提前致謝!用lxml.etree移動整個元素

回答

14

.append.insert等操作做,默認情況下

>>> 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>' 

移動節點具有時要小心尾巴文字。在lxml尾部文本屬於該節點並隨其移動。 (此外,當你刪除一個節點,它的尾巴文本也被刪除)

>>> 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>' 

有時候這是一個預期的效果,但有時你需要這樣的事情:我需要

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

究竟是什麼。謝謝! – Cryptite

+0

Type-o ?: node_a應該是node_b online「node_f.append(node_a)#現在'a'在'f'之下'(同時修復註釋'a') –

0

你可以使用.append().insert()方法的子元素添加到現有的元素:

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