繁体   English   中英

python lxml使用iterparse来编辑和输出xml

[英]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元素
  • 使用replace()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()的解决方案。 我们的想法是捕获所有标记“开始”事件,记住父itemsitems )标记,然后为每个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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM