Ani*_*que 8 python xml parsing namespaces xml-namespaces
我正在尝试使用使用前缀的Python解析XML数据,但并非每个文件都具有前缀声明。XML示例:
<?xml version="1.0" encoding="UTF-8"?>
<item subtype="bla">
<thing>Word</thing>
<abc:thing2>Another Word</abc:thing2>
</item>
Run Code Online (Sandbox Code Playgroud)
我一直在使用xml.etree.ElementTree解析这些文件,但是只要未正确声明前缀,ElementTree就会引发解析错误。(unbound prefix,位于的开头<abc:thing2>)。搜索此错误将导致我提出解决方案,建议我修复名称空间声明。但是,我无法控制需要使用的XML,因此修改输入文件不是一个可行的选择。
通常,搜索名称空间解析会使我想到许多与以名称空间无关的方式进行搜索的问题,这不是我所需要的。
我正在寻找一种自动解析这些文件的方法,即使名称空间声明已损坏。我已经考虑过要执行以下操作:
register_namespace,但这似乎不起作用。更新:在Har07使我走上的道路之后lxml,我试图查看这是否可以执行我曾想到的不同解决方案,其结果将是:
xmlns声明,然后将其传递给lxml.etree的fromstring方法。不幸的是,这还需要从字符串中删除对编码声明的所有引用。虽然可以。lxml(通过attribute_defaults,dtd_validation或load_dtd),但遗憾的是没有解决的命名空间的问题。lxml不要打扰名称空间:可以通过该recover选项进行操作。不幸的是,这也忽略了破坏XML的其他方式(有关详细信息,请参见Har07的答案)。一种可能的方法是使用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))
Run Code Online (Sandbox Code Playgroud)
使用解析格式不正确的XML所需要做的lxml就是将参数传递recover=True给的构造函数XMLParser。lxml还完全支持xpath 1.0,当您需要使用更复杂的条件获取XML文档的一部分时,xpath 1.0非常有用。
更新:
我不知道该recover=True选项可以容忍的所有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))
Run Code Online (Sandbox Code Playgroud)
解析后的最终输出XML lxml如下:
<item subtype="bla">
<thing>Word</thing>
<bad>
<abc:thing2>Another Word</abc:thing2>
</bad></item>
Run Code Online (Sandbox Code Playgroud)