所以,我认为这是一个非常典型的用例,但我在 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/