使用 lxml 修改大型 xml 文件
Modify large xml file using lxml
语言:- 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) Update/Alter 几个节点(如果 <id>
属性的文本在 python dict
D) Append/Write 一些新节点
问题是我的 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 背景。
您不能就地编辑 XML 文件。您必须将输出写入新的(临时)文件,然后用新文件替换原始文件。
所以基本算法是:
- 遍历所有元素。
- 如果该节点是要删除的节点,则继续下一个元素
- 如果节点是一个要改变的,改变它的值
- 写出节点 ««« 这是您缺少的关键部分
- 当您即将完成处理作为新节点之一的父节点的节点时,写出新节点,并将其从新节点集合中删除。
- 关闭输出文件
- 重命名。
回答补充问题:您需要认识到 XML 文件是一个(长)字符串。如果要插入一个字符,则必须将所有其他字符洗牌;如果你想删除一个角色,你必须将所有其他角色洗牌。你不能用文件做到这一点;你不能只从文件中间删除一个字符。
如果您有数百万个元素(这是一个真正的问题,而不是 class 的练习),那么您需要使用数据库。当有人说 "database" 时,我首先想到的是 SQLite,但正如 Charles Duffy 在下面指出的那样,鉴于您已经拥有 XML,XQuery 数据库可能是一个更好的起点。有关一些开源实现,请参阅 BaseX 或 eXist。
语言:- 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) Update/Alter 几个节点(如果 <id>
属性的文本在 python dict
D) Append/Write 一些新节点
问题是我的 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 背景。
您不能就地编辑 XML 文件。您必须将输出写入新的(临时)文件,然后用新文件替换原始文件。
所以基本算法是:
- 遍历所有元素。
- 如果该节点是要删除的节点,则继续下一个元素
- 如果节点是一个要改变的,改变它的值
- 写出节点 ««« 这是您缺少的关键部分
- 当您即将完成处理作为新节点之一的父节点的节点时,写出新节点,并将其从新节点集合中删除。
- 关闭输出文件
- 重命名。
回答补充问题:您需要认识到 XML 文件是一个(长)字符串。如果要插入一个字符,则必须将所有其他字符洗牌;如果你想删除一个角色,你必须将所有其他角色洗牌。你不能用文件做到这一点;你不能只从文件中间删除一个字符。
如果您有数百万个元素(这是一个真正的问题,而不是 class 的练习),那么您需要使用数据库。当有人说 "database" 时,我首先想到的是 SQLite,但正如 Charles Duffy 在下面指出的那样,鉴于您已经拥有 XML,XQuery 数据库可能是一个更好的起点。有关一些开源实现,请参阅 BaseX 或 eXist。