python - 使用 lxml 解析包含多个 xml 文档的文件

标签 python xml lxml

所以,我认为这是一个非常典型的用例,但我在 lxml 文档中找不到任何关于对此的支持。基本上我有一个 xml 文件,其中包含许多不同的 xml 文档(特别是评论),其结构大约为:

<review>
    <!-- A bunch of metadata -->
</review>
<!-- The issue is here -->
<review>
    <!-- A bunch of metadata -->
</review>

基本上,我尝试像这样读取文件:

import lxml

document = lxml.etree.fromstring(open(xml_file).read())

但是当我这样做时出现错误:

lxml.etree.XMLSyntaxError: Extra content at the end of the document

完全合理的错误,事实上它是一个 xml 错误,应该这样对待,但我的问题是:如何让 lxml 识别出这是一个 xml 文档列表并相应地解析?

list_of_reviews = lxml.magic(open(xml_file).read())

magic 是真正的 lxml 函数吗?

最佳答案

所以,它有点老套,但应该相对健壮。这里有两个主要的缺点:

  • 重复调用 fromstring 意味着此代码速度不是很快。与单独解析每个文档的速度大致相同,比全部解析一个文档慢得多
  • 抛出相对于文档中当前位置的错误。添加相对位置支持很容易(只需添加一个累加器来跟踪当前位置)

基本上,该方法是找到引发的错误,然后仅解析错误上方的文件部分。如果抛出与最后一个根节点无​​关的错误,则会像典型的异常一样进行处理。

def fix_xml_list(test_file):
    documents = []
    finished = False
    while not finished:
        try:
            lxml.etree.fromstring(test_file)
        except XMLSyntaxError as e:
            if e.code == 5 and e.position[1] == 1:
                doc_end = e.position[0]
                end_char = find_nth(test_file, '\n', doc_end - 2)
                documents.append(lxml.etree.fromstring(test_file[:end_char]))
                if end_char == len(test_file):
                    finished = True
                test_file = test_file[end_char:]
            else:
                print e
                break
    return documents

def find_nth(doc, search, n=0):
    l = len(search)
    i = -l
    for c in xrange(n + 1):
        i = doc.find(search, i + l)
        if i < 0:
            break
    return i

find_nth 代码被无耻地从 this 窃取问题。这段代码很有用的情况可能并不多,但对于我来说,有大量稍微不规则的文档(在学术数据中很常见),它的值(value)是无价的。

关于python - 使用 lxml 解析包含多个 xml 文档的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31392105/

相关文章:

python - 如何在 python 3.6 中打开混合编码的 unicode 文件?

java - 单击 RadioGroup 时如何显示首选项

python - 将 XML 解析为具有相同节点的 python 中的数据框

python - 如何使用 lxml 有效地解析这个包含嵌套元素的巨大 XML 文件?

python - 在 Visual Studio Code 中从正确的 anaconda 环境启动 PyLint

python - 如何在X*Y网格中找到最短路径

python - Pandas 的负时差

.net - WCF、ASMX 基本 HTTP 绑定(bind)和 IIS

java - 如何在平板电脑上显示 Bitmap/Drawable 作为 centerCrop 以及在手机上显示 fitXY

python - tree.xpath() 使用 lxml 库在 Webscraping 中返回空列表