使用beautifulsoup将大型xml文件拆分为多个文件

时间:2019-06-05 13:41:31

标签: python xml beautifulsoup

我正在尝试将大型xml文件拆分为较小的文件,首先我开始了beautifulsoup:

from bs4 import BeautifulSoup
import os
# Core settings
rootdir = r'C:\Users\XX\Documents\Grant Data\2010_xml'
extension = ".xml"
to_save = r'C:\Users\XX\Documents\all_patents_as_xml'

index = 0
for root, dirs, files in os.walk(rootdir):
    for file in files:
        if file.endswith(extension):
            print(file)
            file_name = os.path.join(root,file)
            with open(file_name) as f:
                data = f.read()
            texts = data.split('?xml version="1.0" encoding="UTF-8"?')
            for text in texts:
                index += 1
                filename = to_save + "\\"+ str(index) + ".txt"
                with open(filename, 'w') as f:
                    f.write(text)

但是,我遇到了内存错误。然后我切换到xml etree:

from xml.etree import ElementTree as ET
import re


file_name = r'C:\Users\XX\Documents\Grant Data\2010_xml\2010cat_xml.xml'


with open(file_name) as f:
    xml = f.read()
tree = ET.fromstring(re.sub(r"(<\?xml[^>]+\?>)", r"\1<root>", xml) + "</root>")
parser = ET.iterparse(tree)
to_save = r'C:\Users\Yilmaz\Documents\all_patents_as_xml'
index = 0
for event, element in parser:
    # element is a whole element
    if element.tag == '?xml version="1.0" encoding="UTF-8"?':
        index += 1
        filename = to_save + "\\"+ str(index) + ".txt"
        with open(filename, 'w') as f:
            f.write(ET.tostring(element))
        # do something with this element
        # then clean up
        element.clear()

,我收到以下错误消息:

OverflowError: size does not fit in an int

我正在使用Windows操作系统,我知道在Linux中您可以从领事中拆分xml,但就我而言,我不知道该怎么办。

2 个答案:

答案 0 :(得分:1)

如果由于内存限制而无法加载XML,则应考虑使用SAX

使用SAX,您将阅读文档的“小片段”,并对其进行处理(例如:将每N个元素保存到一个新文件中)。

Python SAX example 1

Python SAX example 2

答案 1 :(得分:1)

您的问题和解决问题的主要问题:

  1. 您提到使用美丽汤。但是,当您在代码中导入Beautiful Soup时,实际上并没有做任何

  2. 您显示的使用xml.etree的代码是完全错误的。在parser = ET.iterparse(tree)行,tree是已经用ET.fromstring解析的XML树,但是iterparse的参数必须是文件名文件对象。 XML树都不是。这样一来,尝试就死定了。

但更重要的是,您似乎要处理的是一个包含一堆串联XML文件的文件。在您的xml.etree尝试中,您进行了以下测试:

element.tag == '?xml version="1.0" encoding="UTF-8"?'

对于此测试,我唯一能想到的是您认为xml.etree将以某种方式将<?xml version="1.0" encoding="UTF-8"?>解释为XML {em> element ,其名称为{{1} }。但是,结构'?xml version="1.0" encoding="UTF-8"?'不是XML 元素,而是 XML声明

并且由于您的代码似乎在每次遇到XML声明时都会尝试拆分,因此似乎您的输入是一个包含多个XML声明的文件。该文件不是有效的XML。 XML规范允许XML声明在XML文件的开头出现一次,只能出现一次。 (不要将XML声明与处理指令混淆。它们看起来很相似,因为它们都由<?xml version="1.0" encoding="UTF-8"?><?分隔,但是XML声明不是处理指令。)如果使用XML输入文件中的语法分析器,并且该语法分析器符合XML规范,因此它必须拒绝您的文件不是XML,因为XML不允许XML声明出现在文档中的随机位置。

那会留在哪里?如果源文档中存在的所有XML声明都相同,则有一种相对简单的方法使XML解析器可解析您的文档。 (您所做的尝试表明它们都是相同的,因为您没有使用正则表达式来匹配XML声明的不同形式(例如,将指定?>参数的形式)。)您只需删除全部 XML声明,将其包装在新的根元素中,然后使用standalone进行解析。 (这假定串联在一起组成您的源文档的各个XML文档都是格式正确的。如果不是,那么它将不起作用。)

但是,请注意,字符串xml.etree可以出现在XML文档中,而该字符串实际上不是XML声明。这是一个格式正确的XML文档,它将引发一种算法,该算法仅查找看起来像XML声明的字符串:

<?xml version="1.0" encoding="UTF-8"?>

如果您知道源文件的创建方式,则可能已经可以确定没有上述任何情况。否则,您可能需要检查您的来源,以确保以上均不发生。

一旦您解决了这个问题,就可以使用基于<?xml version = "1.0" encoding = "UTF-8"?> <a> <![CDATA[ <?xml version = "1.0" encoding = "UTF-8"?> ]]> <?q <?xml version = "1.0" encoding = "UTF-8"?> ?> <!-- <?xml version = "1.0" encoding = "UTF-8"?> --> </a> 或SAX的策略。