Python利用命名空间解析XML文档
本文介绍如何在Python中处理带有命名空间的XML文档。通过封装XMLNamespaces类简化ElementTree的查询操作,避免繁琐的全URI匹配。同时对比了iterparse的高级用法,并建议在需要DTD验证或复杂XPath时优先使用lxml库,以提升解析效率与功能支持。
问题背景
问题
你需要解析一个包含XML命名空间的文档。
解决方案与实现
解决方案
参考以下包含命名空间的文档示例:
<?xml version="1.0" encoding="utf-8"?>
<top>
<author>David Beazley</author>
<content>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
</content>
</top>
直接解析该文档并进行常规查询会发现操作相当繁琐,因为每一步都需要处理复杂的命名空间前缀。
>>> # Some queries that work
>>> doc.findtext('author')
'David Beazley'
>>> doc.find('content')
<Element 'content' at 0x100776ec0>
>>> # A query involving a namespace (doesn't work)
>>> doc.find('content/html')
>>> # Works if fully qualified
>>> doc.find('content/{http://www.w3.org/1999/xhtml}html')
<Element '{http://www.w3.org/1999/xhtml}html' at 0x1007767e0>
>>> # Doesn't work
>>> doc.findtext('content/{http://www.w3.org/1999/xhtml}html/head/title')
>>> # Fully qualified
>>> doc.findtext('content/{http://www.w3.org/1999/xhtml}html/'
... '{http://www.w3.org/1999/xhtml}head/{http://www.w3.org/1999/xhtml}title')
'Hello World'
>>>
你可以将命名空间处理逻辑封装为一个工具类,从而简化这一过程:
class XMLNamespaces:
def __init__(self, **kwargs):
self.namespaces = {}
for name, uri in kwargs.items():
self.register(name, uri)
def register(self, name, uri):
self.namespaces[name] = '{'+uri+'}'
def __call__(self, path):
return path.format_map(self.namespaces)
使用该类的方式如下所示:
>>> ns = XMLNamespaces(html='http://www.w3.org/1999/xhtml')
>>> doc.find(ns('content/{html}html'))
<Element '{http://www.w3.org/1999/xhtml}html' at 0x1007767e0>
>>> doc.findtext(ns('content/{html}html/{html}head/{html}title'))
'Hello World'
>>>
深入讨论与进阶建议
讨论
解析包含命名空间的XML文档通常比较繁琐。上述的 XMLNamespaces 类仅允许你使用缩略名替代完整的URI,使代码看起来稍微简洁一些。
遗憾的是,在基础的 ElementTree 解析中,没有直接获取命名空间信息的方法。不过,如果你使用 iterparse() 函数,则可以获取更多关于命名空间作用域的信息。例如:
>>> from xml.etree.ElementTree import iterparse
>>> for evt, elem in iterparse('ns2.xml', ('end', 'start-ns', 'end-ns')):
... print(evt, elem)
...
end <Element 'author' at 0x10110de10>
start-ns ('', 'http://www.w3.org/1999/xhtml')
end <Element '{http://www.w3.org/1999/xhtml}title' at 0x1011131b0>
end <Element '{http://www.w3.org/1999/xhtml}head' at 0x1011130a8>
end <Element '{http://www.w3.org/1999/xhtml}h1' at 0x101113310>
end <Element '{http://www.w3.org/1999/xhtml}body' at 0x101113260>
end <Element '{http://www.w3.org/1999/xhtml}html' at 0x10110df70>
end-ns None
end <Element 'content' at 0x10110de68>
end <Element 'top' at 0x10110dd60>
>>> elem # This is the topmost element
<Element 'top' at 0x10110dd60>
>>>
最后,如果你处理的XML文本除了使用命名空间外还涉及其他高级XML特性,建议改用 函数库替代 ElementTree。例如,lxml 对利用DTD验证文档、更强大的XPath支持以及其他高级XML特性提供了更好的支持。本节内容主要旨在让XML解析过程变得稍微简单一些。
以上就是Python利用命名空间解析XML文档的详细内容,更多关于Python命名空间解析XML文档的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









