我有一个较大的xml文件,其父标签具有97k个子标签。我想分成10个文件,每个文件有1万个标签,最后一个有剩余的文件。
我有这段代码,可以在每个文件中写入一个子标签,但无法进行分组。
因此,假设我的示例XML具有10个子标记,并且我想创建5个文件,每个文件具有2个子标记。
我的示例XML:
<root>
<row>
<NAME>A</NAME>
<FIRSTNAME>A</FIRSTNAME>
<GENDER>M</GENDER>
</row>
<row>
<NAME>B</NAME>
<FIRSTNAME>B</FIRSTNAME>
<GENDER>M</GENDER>
</row>
<row>
<NAME>A</NAME>
<FIRSTNAME>A</FIRSTNAME>
<GENDER>M</GENDER>
</row>
<row>
<NAME>B</NAME>
<FIRSTNAME>B</FIRSTNAME>
<GENDER>M</GENDER>
</row>
<row>
<NAME>A</NAME>
<FIRSTNAME>A</FIRSTNAME>
<GENDER>M</GENDER>
</row>
<row>
<NAME>B</NAME>
<FIRSTNAME>B</FIRSTNAME>
<GENDER>M</GENDER>
</row>
<row>
<NAME>A</NAME>
<FIRSTNAME>A</FIRSTNAME>
<GENDER>M</GENDER>
</row>
<row>
<NAME>B</NAME>
<FIRSTNAME>B</FIRSTNAME>
<GENDER>M</GENDER>
</row>
<row>
<NAME>A</NAME>
<FIRSTNAME>A</FIRSTNAME>
<GENDER>M</GENDER>
</row>
<row>
<NAME>B</NAME>
<FIRSTNAME>B</FIRSTNAME>
<GENDER>M</GENDER>
</row>
</root>
我的结果应该是5个文件,每个文件有2个条目,如下所示:
<root>
<row>
<NAME>A</NAME>
<FIRSTNAME>A</FIRSTNAME>
<GENDER>M</GENDER>
</row>
<row>
<NAME>B</NAME>
<FIRSTNAME>B</FIRSTNAME>
<GENDER>M</GENDER>
</row>
</root>
下面的代码在每个文件中放置每个子标记,但我想在此例如每个文件2个标记。
import xml.etree.ElementTree as ET
context = ET.iterparse('file.xml', events=('end', ))
index = 0
for event, elem in context:
if elem.tag == 'row':
index += 1
filename = format(str(index) + ".xml")
with open(filename, 'wb') as f:
f.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
f.write(ET.tostring(elem))
谢谢!
编辑以添加配方:
from itertools import zip_longest
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
答案 0 :(得分:1)
您有一个(事件,元素)对可迭代:
context = ET.iterparse('file.xml', events=('end', ))
现在,您希望将其过滤为row
个元素:
rows = (elem for event, elem in context if elem.tag == 'row')
现在,您要将它们分组。使用the grouper
recipe from the itertools
docs:
groups = grouper(rows, 2)
一旦工作正常并且想要真正运行,您显然可以将2
更改为1000
或其他任何内容。
现在,您可以仅迭代组。在此过程中,请使用enumerate
,这样您就不需要手动的index += 1
东西了。此外,让我们只使用format
。而不是手动构建一个字符串然后无意义地调用an f-string。
for index, group in enumerate(groups):
# If you need to run on 3.5 or 2.7, use "{}.xml".format(index)
filename = f"{index}.xml"
with open(filename, 'wb') as f:
f.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
…然后迭代组中的元素-但要小心;如果元素数量奇数,则grouper
将使用None
值填充不完整的最后一组。 1
for elem in group:
if elem:
f.write(ET.tostring(elem))
1。并不是很难更改,但是我直接在文档之外使用配方,因此不必解释如何更改。