如何在不读取python中整个文件的情况下覆盖XML属性值

时间:2018-06-28 21:04:26

标签: python xml xml.etree

一次只读取一个元素时,如何覆盖单个属性值?

具体地说,我正在使用xml.etree.cElementTree.iterparse()来读取每个单独的元素。然后,我要更改属性值。

然后我要做的是用original element覆盖changed element

这是到目前为止的示例代码:

osm_file = open(sample.osm, 'r+')

for event, elem in ET.iterparse(osm_file events=("start",)):

    # Making some changes
    elem.attrib['v'] = 'new_value'

    # Some how write the elem back to the XML file

我不能做的一件事是将整个XML文件读入python,因为该文件太大。

3 个答案:

答案 0 :(得分:1)

注释中usr2564301的

解释了为什么这不可能。

  

那可能行不通。 XML处理不知道数据来自文件,因此无法在文件中完全相同的位置“回写”更改后的值。即使可以:在没有重写整个文件的情况下,用较短或较长的文本替换文件中的文本在物理上也是不可能的。 (唯一的例外是“长度完全相同的文本”和“数据在最后”。)– usr2564301

答案 1 :(得分:1)

iterparse仍然处理整个树。您无法避免:

http://effbot.org/zone/element-iterparse.htm#incremental-parsing

  

增量解析#请注意,iterparse仍会构建一棵树,只是   就像解析一样,但是您可以安全地重新排列或删除树的一部分   同时解析。例如,要解析大型文件,您可以摆脱   元素处理后:

     

对于事件,iterparse中的elem(源):       如果elem.tag ==“ record”:           ...处理记录元素...           elem.clear()

如果您的XML文件太大,无法在程序中处理,则需要考虑其他数据存储格式,例如数据库。

否则,您可以使用sed和awk或其他工具对文本文件进行一些文件操作魔术。

答案 2 :(得分:0)

我最近也一直在处理大型文件,但无法将其容纳在内存中。为了解决这个问题,我整理了一个简单的程序包bigreadpip install bigread),该程序包可将文件的n行立即流进RAM:

from bigread import Reader

# this will be the output file
with open('updated.xml', 'w') as out:
  # read the input file
  for i in Reader(file='input.xml', block_size=1):
    # check if this is a line you need to operate on
    if i.lstrip()[:5] == '<tag ':
      # replace the target attribute
      i = i.replace(' attr="cats" ', ' attr="dogs" ')
    # write the new line to disk
    out.write(i + '\n')