因为我第二次遇到这个烦人的问题,所以我认为询问会有所帮助。
有时我必须从 XML 文档中获取元素,但是这样做的方法很尴尬。
我想知道一个 python 库,它可以做我想做的事,一种优雅的方式来制定我的 XPath,一种在前缀中自动注册命名空间的方法,或者在内置 XML 实现或 lxml 中隐藏首选项以完全剥离命名空间。除非你已经知道我想要什么,否则澄清如下:)
示例文档:
<root xmlns="http://really-long-namespace.uri"
xmlns:other="http://with-ambivalent.end/#">
<other:elem/>
</root>
我可以做什么
ElementTree API 是唯一(我知道的)提供 XPath 查询的内置 API。但它要求我使用“UNames”。这看起来像这样:/{http://really-long-namespace.uri}root/{http://with-ambivalent.end/#}elem
如您所见,这些内容非常冗长。我可以通过执行以下操作来缩短它们:
default_ns = "http://really-long-namespace.uri"
other_ns = "http://with-ambivalent.end/#"
doc.find("/{{{0}}}root/{{{1}}}elem".format(default_ns, other_ns))
但这既 {{{ugly}}} 又脆弱,因为http…end/#
≃ http…end#
≃ http…end/
≃ http…end
,我有谁知道将使用哪个变体?
此外,lxml 支持命名空间前缀,但它既不使用文档中的前缀,也不提供处理默认命名空间的自动化方式。我仍然需要获取每个命名空间的一个元素才能从文档中检索它。命名空间属性没有保留,因此也无法从这些属性中自动检索它们。
也有一种与命名空间无关的 XPath 查询方式,但在内置实现中它既冗长/丑陋又不可用:/*[local-name() = 'root']/*[local-name() = 'elem']
我想做的事
我想找到一个库、选项或通用 XPath 变形函数来实现上述示例,只需键入以下内容……</p>
- 未命名空间:
/root/elem
- 文档中的命名空间前缀:
/root/other:elem
…加上一些我确实想使用文档前缀或剥离名称空间的语句。
进一步澄清:虽然我当前的用例就这么简单,但我将来必须使用更复杂的用例。
谢谢阅读!
解决了
用户 samplebias 将我的注意力引向py-dom-xpath;正是我想要的。我的实际代码现在如下所示:
#parse the document into a DOM tree
rdf_tree = xml.dom.minidom.parse("install.rdf")
#read the default namespace and prefix from the root node
context = xpath.XPathContext(rdf_tree)
name = context.findvalue("//em:id", rdf_tree)
version = context.findvalue("//em:version", rdf_tree)
#<Description/> inherits the default RDF namespace
resource_nodes = context.find("//Description/following-sibling::*", rdf_tree)
与文档一致,简单,命名空间感知;完美的。