1

语言:- Python 2.7.6

文件大小:- 1.5 GB

XML 格式

<myfeed>
    <product>
        <id>876543</id>
        <name>ABC</name>
        ....
     </product>

    <product>
        <id>876567</id>
        <name>DEF</name>
        ....
     </product>

    <product>
        <id>986543</id>
        <name>XYZ</name>
        ....
     </product>

我必须

A)读取所有节点<product>

B)删除其中一些节点(如果<id>属性的文本在 python set()

C)更新/更改几个节点(如果<id>属性的文本在 python dict 中

D)追加/写入一些新节点

问题是我的 XML 文件很大(大约 1.5 GB)。我做了一些研究并决定将 lxml 用于所有这些目的。

我正在尝试使用 iterparse() 和 element.clear() 来实现这一点,因为它不会消耗我所有的内存。

for event, element in etree.iterparse(big_xml_file,tag = 'product'):
        for child in element:
            if child.tag == unique_tag:
                if child.text in products_id_hash_set_to_delete: #python set()
                    #delete this element node

                else:
                    if child.text in products_dict_to_update:
                        #update this element node  
                        else:
                            print child.text
        element.clear()

注意:- 我想在一次扫描 XML 文件中完成所有这 4 项任务

问题

1)我可以在一次扫描文件中实现所有这些吗?

2)如果是,如何删除和更新我正在处理的元素节点?

3) 我应该改用 tree.xpath() 吗?如果是,它会为 1.5 GB 文件消耗多少内存,或者它的工作方式与 iterparse() 相同

我对python不是很有经验。我来自Java背景。

4

1 回答 1

2

您不能就地编辑 XML 文件。您必须将输出写入新的(临时)文件,然后用新文件替换原始文件。

所以基本算法是:

  • 循环遍历所有元素。
  • 如果节点是要删除的节点,则继续下一个元素
  • 如果节点是一个要改变的,改变它的值
  • 写出节点«««这是您缺少的关键位
  • 当您即将完成处理作为新节点之一的父节点的节点时,写出新节点,并将其从新节点集合中删除。
  • 关闭输出文件
  • 改名。

要回答补充问题:您需要意识到 XML 文件是一个(长)字符串。如果要插入一个字符,则必须将所有其他字符洗牌;如果你想删除一个字符,你必须把所有其他的都洗掉。你不能用文件做到这一点。您不能只从文件中间删除一个字符。

如果您有数百万个元素(这是一个真正的问题,而不是一个类的练习),那么您需要使用数据库。当有人说“数据库”时,我首先想到的是 SQLite,但正如 Charles Duffy 在下面指出的那样,考虑到您已经拥有 XML,XQuery 数据库可能是一个更好的起点。有关一些开源实现,请参阅 BaseX 或 eXist。

于 2015-12-16T08:19:50.223 回答