[英]python lxml using iterparse to edit and output xml
我一直在搞亂lxml庫一段時間,也許我沒有正確理解它或者我錯過了一些東西但我似乎無法弄清楚如何在捕獲某個xpath后編輯文件然后能夠在我逐個元素地解析時將其寫回xml。
假設我們以xml為例:
<xml>
<items>
<pie>cherry</pie>
<pie>apple</pie>
<pie>chocolate</pie>
</items>
</xml>
我在解析時想要做的是當我點擊“/ xml / items / pie”的xpath時是在pie之前添加一個元素,所以它會像這樣:
<xml>
<items>
<item id="1"><pie>cherry</pie></item>
<item id="2"><pie>apple</pie></item>
<item id="3"><pie>chocolate</pie></item>
</items>
</xml>
當我點擊每個標簽並在某些xpath處編輯xml時,需要通過逐行寫入文件來完成該輸出。 我的意思是我可以讓它打印起始標簽,文本,屬性(如果它存在),然后通過硬編碼某些部分來結束標簽,但這將是非常混亂的,如果有辦法避免如果可能。
這是我的猜測代碼:
from lxml import etree
path=[]
count=0
context=etree.iterparse(file,events=('start','end'))
for event, element in context:
if event=='start':
path.append(element.tag)
if /'+'/'.join(path)=='/xml/items/pie':
itemnode=etree.Element('item',id=str(count))
itemnode.text=""
element.addprevious(itemnode)#Not the right way to do it of course
#write/print out xml here.
else:
element.clear()
path.pop()
編輯:另外,我需要運行相當大的文件,所以我必須使用iterparse。
有一種更簡潔的方法可以進行所需的修改:
pie
元素 item
元素 item
替換pie
元素 replace(self,old_element,new_element)
用作為第二個參數傳遞的元素替換子元素。
from lxml import etree
from lxml.etree import XMLParser, Element
data = """<xml>
<items>
<pie>cherry</pie>
<pie>apple</pie>
<pie>chocolate</pie>
</items>
</xml>"""
tree = etree.fromstring(data, parser=XMLParser())
items = tree.find('.//items')
for index, pie in enumerate(items.xpath('.//pie'), start=1):
item = Element('item', {'id': str(index)})
items.replace(pie, item)
item.append(pie)
print etree.tostring(tree, pretty_print=True)
打印:
<xml>
<items>
<item id="1"><pie>cherry</pie></item>
<item id="2"><pie>apple</pie></item>
<item id="3"><pie>chocolate</pie></item>
</items>
</xml>
這是使用iterparse()
的解決方案。 我們的想法是捕獲所有標記“開始”事件,記住父items
( items
)標記,然后為每個pie
標記創建一個item
標記並將其放入其中:
from StringIO import StringIO
from lxml import etree
from lxml.etree import Element
data = """<xml>
<items>
<pie>cherry</pie>
<pie>apple</pie>
<pie>chocolate</pie>
</items>
</xml>"""
stream = StringIO(data)
context = etree.iterparse(stream, events=("start", ))
for action, elem in context:
if elem.tag == 'items':
items = elem
index = 1
elif elem.tag == 'pie':
item = Element('item', {'id': str(index)})
items.replace(elem, item)
item.append(elem)
index += 1
print etree.tostring(context.root)
打印:
<xml>
<items>
<item id="1"><pie>cherry</pie></item>
<item id="2"><pie>apple</pie></item>
<item id="3"><pie>chocolate</pie></item>
</items>
</xml>
我建議你使用XSLT模板,因為它似乎更適合這項任務。 最初XSLT有點棘手,直到你習慣它,如果你想要的只是從XML生成一些輸出,那么XSLT是一個很好的工具。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.