在 Python 中使用未声明的前缀解析 XML

Parsing XML with undeclared prefixes in Python

我正在尝试使用使用前缀的 Python 解析 XML 数据,但并非每个文件都有前缀声明。例子 XML:

<?xml version="1.0" encoding="UTF-8"?>
<item subtype="bla">
    <thing>Word</thing>
    <abc:thing2>Another Word</abc:thing2>
</item>

我一直在使用 xml.etree.ElementTree 来解析这些文件,但是每当没有正确声明前缀时,ElementTree 就会抛出解析错误。 (unbound prefix,就在 <abc:thing2> 的开头) 搜索此错误会引导我找到建议我修复命名空间声明的解决方案。但是,我无法控制我需要使用的 XML,因此修改输入文件不是一个可行的选择。

一般搜索命名空间解析让我产生了很多关于以与命名空间无关的方式进行搜索的问题,这不是我需要的。

我正在寻找一些方法来自动解析这些文件,即使名称空间声明被破坏。我考虑过执行以下操作:

更新: Har07让我走上lxml的道路后,我试着看看这是否会让我执行我想到的不同解决方案,结果会是什么:

一种可能的方法是使用 ElementTree 兼容库 lxml。例如:

from lxml import etree as ElementTree

xml = """<?xml version="1.0" encoding="UTF-8"?>
<item subtype="bla">
    <thing>Word</thing>
    <abc:thing2>Another Word</abc:thing2>
</item>"""
parser = ElementTree.XMLParser(recover=True)
tree = ElementTree.fromstring(xml, parser)

thing = tree.xpath("//thing")[0]
print(ElementTree.tostring(thing))

要使用 lxml 解析格式不正确的 XML,您需要做的就是将参数 recover=True 传递给 XMLParser 的构造函数。 lxml 还完全支持 xpath 1.0,这在您需要使用更复杂的条件获取 XML 文档的一部分时非常有用。

更新:

我不知道 recover=True 选项可以容忍的所有类型的 XML 错误。但是除了未绑定的命名空间前缀之外,我还知道另一种类型的错误:unclosed tag。 lxml 将通过自动添加相应的关闭标签来修复 - 而不是忽略 - 未关闭的标签。例如,给定以下损坏的 XML :

xml = """<item subtype="bla">
    <thing>Word</thing>
    <bad>
    <abc:thing2>Another Word</abc:thing2>
</item>"""
parser = ElementTree.XMLParser(recover=True)
tree = ElementTree.fromstring(xml, parser)

print(ElementTree.tostring(tree))

经过lxml解析后的最终输出XML如下:

<item subtype="bla">
    <thing>Word</thing>
    <bad>
    <abc:thing2>Another Word</abc:thing2>
</bad></item>