使用lxml xpath的语法麻烦

时间:2014-07-03 22:10:48

标签: python xpath lxml

在使用lxml解析Python中的XML时,我很难理解用于获取单个元素的正确语法。

当我这样做时:

print self.root.xpath("descendant::*[@Name='GevCCP']/*",namespaces=self.nsmap)

我得到了一个下级节点列表:

[<Element {http://www.genicam.org/GenApi/Version_1_0}ToolTip at 0x1175830>, <Element {http://www.genicam.org/GenApi/Version_1_0}Description at 0x117b6c8>, <Element {http://www.genicam.org/GenApi/Version_1_0}DisplayName at 0x117bb48>, <Element {http://www.genicam.org/GenApi/Version_1_0}Visibility at 0x117bb90>, <Element {http://www.genicam.org/GenApi/Version_1_0}Streamable at 0x117bd88>, <Element {http://www.genicam.org/GenApi/Version_1_0}EnumEntry at 0x117b8c0>, <Element {http://www.genicam.org/GenApi/Version_1_0}EnumEntry at 0x1214878>, <Element {http://www.genicam.org/GenApi/Version_1_0}EnumEntry at 0x1214560>, <Element {http://www.genicam.org/GenApi/Version_1_0}pValue at 0x1214a70>]

那么如何使用xpath语法直接说出该列表的第一个子元素?

我试过了:

print self.root.xpath("descendant::*[@Name='GevCCP']/ToolTip",namespaces=self.nsmap)

给了我一个空集:

[]

我还尝试在xpath中指定名称空间,这总是会导致lxml.etree.XPathEvalError: Invalid expression错误。

最终,我想在各种元素上执行此操作,例如:

self.root.xpath("descendant::*[@Name='GevCCP']/pValue")
self.root.xpath("descendant::*[@Name='GevCCP']/EnumEntry[@Name='Group']/Value")
self.root.xpath("descendant::*[@Name='GevHeartbeatTimeoutReg']/Address")

lxml文档似乎没有涵盖我的用例,我发现的关于xpath和命名空间的任何其他内容似乎都不完整。

1 个答案:

答案 0 :(得分:3)

最佳解决方案是注册 XML源中使用的命名空间。通常通过将其分配给您可以在表达式中使用的前缀来完成。您的nsmap变量是否正确映射了命名空间?选择一个前缀(例如g):

self.nsmap = {'g': 'http://www.genicam.org/GenApi/Version_1_0'}

然后使用前缀来限定XPath选择器:

self.root.xpath("descendant::*[@Name='GevCCP']/g:ToolTip", namespaces=self.nsmap)