我尝试使用使用使用前缀的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,因此修改输入文件不是一个可行的选项。
一般来说,搜索名称空间解析会导致许多关于以不可知名称空间的方式搜索的问题,这不是我需要的。
我正在寻找自动解析这些文件的方法,即使名称空间声明被破坏。我考虑过做以下工作:
告诉elementtree预先需要什么名称空间,因为我知道哪些名称空间可以发生。我发现了,但这似乎不起作用。
在解析之前先读取完整的DTD,看看是否能解决问题。我找不到一种方法来处理elementtree。
告诉elementtree不要为名称空间操心。它不应该对我的数据造成问题,但我找不到方法来做这件事。
使用其他可以处理这个问题的解析库-尽管我不希望安装额外的库。如果有其他人能解决我的问题,我很难从文档中看到。
我目前没有看到的其他路线?
更新:
在har07将我置于register_namespace的路径之后,我试图了解这是否会让我执行我曾经想到的不同解决方案,以及结果是什么:
告诉解析器预先需要什么名称空间:我仍然找不到任何“正式”的方法来实现这一点,但是在我之前的搜索中,我发现了一个建议,可以简单地以编程方式将必要的声明添加到数据中。(对于另一种编程情况-不幸的是,我再也找不到链接了)它对我来说似乎非常糟糕,但我还是尝试过。它包括将数据作为字符串加载,将封闭元素更改为具有正确的lxml声明,然后将其传递给xmlnslxml.etree方法。不幸的是,这还需要从字符串中删除对编码声明的所有引用。不过,它起作用了。
在解析之前读取DTD:可以使用fromstring(通过lxmlattribute_defaultsdtd_validation),但不幸的是不能解决命名空间问题。
告诉load_dtd不要为名称空间操心:可以通过lxml选项。不幸的是,这也忽略了其他可能破坏XML的方法(有关详细信息,请参阅har07的答案)。

最佳答案

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

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))

对于使用ElementTree解析非格式良好的XML,只需将参数lxml传递给lxml的构造函数。recover=True还完全支持xpath 1.0,当需要使用更复杂的条件获取XML文档的一部分时,它非常有用。
更新:
我不知道XMLParser选项可以容忍的所有类型的XML错误。但除了未绑定的名称空间前缀之外,我还知道另一种类型的错误:未关闭的标记。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))

recover=True解析后的最终输出xml如下:
<item subtype="bla">
    <thing>Word</thing>
    <bad>
    <abc:thing2>Another Word</abc:thing2>
</bad></item>

07-24 18:27
查看更多