Python 3:拆分连接的XML文件

时间:2018-06-14 12:26:17

标签: xml python-3.x split

我有一个由连接的XML文件组成的大型文本文件(我将每个文件称为'XML子文件')。

我知道当我来到字符串

时,每个新的XML部分都会启动
<?xml version = "1.0"?>

目标是解析每个XML子文件,但作为第一步,我需要

我的想法是将文本文件拆分为单独的XML文件,然后我可以解析。 (其他想法?)

如何“循环”文本文件并将文件拆分?我无法读取整个文件,因为它太大,我无法遍历这些行(因为文件在技术上是一行,文件中没有换行符。)

知道如何在Python 3中解决这个问题吗?

PS:看起来这是一个类似的问题,但链接已经死了:

Link to other post

1 个答案:

答案 0 :(得分:0)

假设输入文件相当大并且您可能不想将其完全加载到内存中,那么将其传输是有意义的。

Optimal是生成器,它会在某些点将文件的传入流分解为块,即当一条线等于你的“分裂”线时。

这可以概括为可以将任何可迭代分组的函数。 itertools.groupby有助于完成任务,我们需要做的就是当我们点击“split here”值时增加一个索引,并使用该索引作为组密钥:

from itertools import groupby

def split_chunks(values, split_val):
    '''splits a list of values into chunks at a certain value'''

    index = 0
    def chunk_index(val):
        nonlocal index
        if val == split_val:
            index += 1
        return index

    return groupby(values, chunk_index)

测试 - 让我们将数字列表拆分为0

的块
for i, numbers in split_chunks([0,1,2,3,0,4,5,6,0,7,8,9], 0):
     print(list(numbers))

打印


[0, 1, 2, 3]
[0, 4, 5, 6]
[0, 7, 8 ,9]

出现空行,因为输入中的第一个0之前没有任何内容。拆分字符串'abcabc'.split('a')时会发生完全相同的事情。

因此,使用“大文本文件中的行”代替“数字”很简单:

import xml.etree.ElementTree as ET

with open('large_container_file', 'r', encoding='utf8') as container_file:
    for doc_num, doc in split_chunks(container_file, '<?xml version="1.0"?>'):
        print(f'processing sub-document #{doc_num}')
        tree = ET.fromstringlist(doc)

确保使用正确的编码打开容器文件。

由于生成器仅在您推进迭代时才起作用,因此在处理当前large_container_file时读取tree会停止,因此内存使用量应该相当低,与输入文件大小无关。

doc在这种情况下是一个生成器,这很好,因为它非常节省内存。但与列表相反,您无法轻易找出它是否为空,如果'<?xml version="1.0"?>'是文档中的第一行,则会出现这种情况。

ET.fromstringlist()对生成器很满意,但是当它发现生成器为空时它会抛出。但是,当XML中存在错误时它也会抛出,所以我要做的是添加try

try:
    tree = ET.fromstringlist(doc)
except:
    pass

或者,您可以预先致电list(),然后检查是否有任何行:

lines = list(doc)
if lines:
    tree = ET.fromstringlist(lines)