我正在尝试使用Python的lxml库解析超过2GB的XML文件。不幸的是,XML文件没有告诉字符编码的行,因此我必须手动设置它。在遍历文件时,偶尔还会出现一些奇怪的字符。

我不确定如何确定行的字符编码,但是lxml会从for循环的范围内引发XMLSyntaxError。如何正确捕获此错误并正确处理?这是一个简单的代码片段:

from lxml import etree
etparse = etree.iterparse(file("my_file.xml", 'r'), events=("start",), encoding="CP1252")
for event, elem in etparse:
    if elem.tag == "product":
        print "Found the product!"
        elem.clear()

最终会产生错误:
XMLSyntaxError: PCDATA invalid Char value 31, line 1565367, column 50
文件的该行如下所示:
% sed -n "1565367 p" my_file.xml
<romance_copy>Ravioli Florentine. Tender Ravioli Filled With Creamy Ricotta Cheese And

填充的“F”实际上在我的终端中看起来像这样:

最佳答案

在这里要做的正确的事情是确保XML文件的创建者确保:
A.)文件的编码已声明
B.)XML文件格式正确(没有无效字符控制字符,没有无效字符不属于编码方案,所有元素均已正确关闭,等等)
C.)如果要确保存在某些属性/元素,具有某些值或与某种格式相对应,请使用DTD或XML模式(注意:这将对性能造成影响)

所以,现在到你的问题。当您使用LXml解析XML时,它支持大量参数。 Check out the documentation。您将要查看以下两个参数:

->恢复->尝试通过损坏的XML进行解析
-> huge_tree->禁用安全限制,并支持非常深的树和非常长的文本内容(仅影响libxml2 2.7+)

它们将在某种程度上为您提供帮助,但是某些无效字符将无法恢复,因此再次确保确保文件正确编写是清理/正常工作代码的最佳选择。

是的,还有一件事。 2GB是巨大的。我假设您在此文件中有一个类似元素的列表(示例书籍列表)。尝试在OS上使用Regex表达式将文件拆分,然后启动多个进程来分割文件。这样一来,您将可以在盒子上使用更多的内核,并且处理时间将减少。当然,然后您必须处理将结果合并回一起的复杂性。我无法为您做出这种折衷,而是想将其作为“深思熟虑的食物”提供给您

添加到发布:
如果您无法控制输入文件且其中包含错误字符,我将尝试通过在将字符串解析为文件之前对字符串进行迭代来替换/删除这些错误字符。这里是删除Unicode control characters that you wont need的代码示例:

#all unicode characters from 0x0000 - 0x0020 (33 total) are bad and will be replaced by "" (empty string)
for line in fileinput.input(xmlInputFileLocation, inplace=1):
    for pos in range(0,len(line)):
        if unichr(line[pos]) < 32:
            line[pos] = None
    print u''.join([c for c in line if c])

关于python - 解析大型XML文件时,如何处理Python的lxml中的XMLSyntaxError?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8888628/

10-11 22:16
查看更多