嵌套Python字典的XPath类似查询
有没有办法为嵌套的Python字典定义一个XPath类型的查询?
类似这样的:
foo = {
'spam':'eggs',
'morefoo': {
'bar':'soap',
'morebar': {'bacon' : 'foobar'}
}
}
print( foo.select("/morefoo/morebar") )
>> {'bacon' : 'foobar'}
我还需要选择嵌套的列表;)
这可以很简单地通过@jellybean的解决方案来实现:
def xpath_get(mydict, path):
elem = mydict
try:
for x in path.strip("/").split("/"):
try:
x = int(x)
elem = elem[x]
except ValueError:
elem = elem.get(x)
except:
pass
return elem
foo = {
'spam':'eggs',
'morefoo': [{
'bar':'soap',
'morebar': {
'bacon' : {
'bla':'balbla'
}
}
},
'bla'
]
}
print xpath_get(foo, "/morefoo/0/morebar/bacon")
[编辑 2016] 这个问题和被接受的答案已经很久了。更新的答案可能比原来的答案更好。不过我没有测试过它们,所以我不会更改被接受的答案。
11 个回答
19
现在有一个更简单的方法来做到这一点。
http://github.com/akesterson/dpath-python
$ easy_install dpath
>>> dpath.util.search(YOUR_DICTIONARY, "morefoo/morebar")
... 完成了。或者如果你不喜欢以视图的形式(合并字典并保留路径)获取结果,可以选择直接返回结果:
$ easy_install dpath
>>> for (path, value) in dpath.util.search(YOUR_DICTIONARY, "morefoo/morebar", yielded=True)
... 这样就完成了。在这种情况下,'value' 将会包含 {'bacon': 'foobar'}。
22
我找到的一个非常棒的库,还是一个正在积极开发的项目,就是从boto中提取出来的:JMESPath。它有一种非常强大的语法,可以用很少的代码完成通常需要很多代码才能实现的事情。
下面是一些例子:
search('foo | bar', {"foo": {"bar": "baz"}}) -> "baz"
search('foo[*].bar | [0]', {
"foo": [{"bar": ["first1", "second1"]},
{"bar": ["first2", "second2"]}]}) -> ["first1", "second1"]
search('foo | [0]', {"foo": [0, 1, 2]}) -> [0]
18
虽然看起来不太美观,但你可以用类似下面的方式来实现:
def xpath_get(mydict, path):
elem = mydict
try:
for x in path.strip("/").split("/"):
elem = elem.get(x)
except:
pass
return elem
当然,这个方法不支持像索引这样的xpath功能……更不用说unutbu提到的/
键的陷阱了。