Ric*_*kyA 39 python xpath jmespath json-path-expression
有没有办法为嵌套的python词典定义XPath类型查询.
像这样的东西:
foo = {
'spam':'eggs',
'morefoo': {
'bar':'soap',
'morebar': {'bacon' : 'foobar'}
}
}
print( foo.select("/morefoo/morebar") )
>> {'bacon' : 'foobar'}
Run Code Online (Sandbox Code Playgroud)
我还需要选择嵌套列表;)
这可以通过@ 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")
Run Code Online (Sandbox Code Playgroud)
[编辑2016]这个问题和接受的答案是古老的.较新的答案可能比原始答案更好地完成工作.但是我没有测试它们所以我不会改变接受的答案.
nik*_*lay 19
我能够识别的最好的库之一,另外,它是非常积极开发的,是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]
Run Code Online (Sandbox Code Playgroud)
小智 14
现在有一种更简单的方法可以做到这一点.
http://github.com/akesterson/dpath-python
$ easy_install dpath
>>> dpath.util.search(YOUR_DICTIONARY, "morefoo/morebar")
Run Code Online (Sandbox Code Playgroud)
......完成了 或者,如果您不希望将结果返回到视图中(保留路径的合并字典),请改为:
$ easy_install dpath
>>> for (path, value) in dpath.util.search(YOUR_DICTIONARY, "morefoo/morebar", yielded=True)
Run Code Online (Sandbox Code Playgroud)
... 并做了.在这种情况下,'价值'将保持{'培根':'foobar'}.
Joh*_*rra 12
不是很漂亮,但你可能会喜欢......
def xpath_get(mydict, path):
elem = mydict
try:
for x in path.strip("/").split("/"):
elem = elem.get(x)
except:
pass
return elem
Run Code Online (Sandbox Code Playgroud)
这当然不支持索引之类的xpath东西......更不用说/
unutbu指示的关键陷阱了.
ank*_*tis 12
有更新的jsonpath-rw库支持JSONPATH语法,但是对于python 词典和数组,正如您所希望的那样.
所以你的第一个例子变成:
from jsonpath_rw import parse
print( parse('$.morefoo.morebar').find(foo) )
Run Code Online (Sandbox Code Playgroud)
第二个:
print( parse("$.morefoo[0].morebar.bacon").find(foo) )
Run Code Online (Sandbox Code Playgroud)
PS:支持字典的另一个更简单的库是python-json-pointer,它具有更多类似XPath的语法.
您可以使用JMESPath,它是一种 JSON 查询语言,并且具有python 实现。
import jmespath # pip install jmespath
data = {'root': {'section': {'item1': 'value1', 'item2': 'value2'}}}
jmespath.search('root.section.item2', data)
Out[42]: 'value2'
Run Code Online (Sandbox Code Playgroud)
jmespath 查询语法和实例:http ://jmespath.org/tutorial.html
另一种选择是使用诸如dicttoxml 之类的东西将您的字典转换为 XML ,然后使用常规 XPath 表达式,例如通过lxml或您喜欢的任何其他库。
from dicttoxml import dicttoxml # pip install dicttoxml
from lxml import etree # pip install lxml
data = {'root': {'section': {'item1': 'value1', 'item2': 'value2'}}}
xml_data = dicttoxml(data, attr_type=False)
Out[43]: b'<?xml version="1.0" encoding="UTF-8" ?><root><root><section><item1>value1</item1><item2>value2</item2></section></root></root>'
tree = etree.fromstring(xml_data)
tree.xpath('//item2/text()')
Out[44]: ['value2']
Run Code Online (Sandbox Code Playgroud)
另一个选项是Json Pointer,它是一个具有 Python 实现的IETF 规范:
from jsonpointer import resolve_pointer
obj = {"foo": {"anArray": [ {"prop": 44}], "another prop": {"baz": "A string" }}}
resolve_pointer(obj, '') == obj
# True
resolve_pointer(obj, '/foo/another%20prop/baz') == obj['foo']['another prop']['baz']
# True
>>> resolve_pointer(obj, '/foo/anArray/0') == obj['foo']['anArray'][0]
# True
Run Code Online (Sandbox Code Playgroud)
小智 5
如果你喜欢简洁:
def xpath(root, path, sch='/'):
return reduce(lambda acc, nxt: acc[nxt],
[int(x) if x.isdigit() else x for x in path.split(sch)],
root)
Run Code Online (Sandbox Code Playgroud)
当然,如果你只有字典,那就更简单了:
def xpath(root, path, sch='/'):
return reduce(lambda acc, nxt: acc[nxt],
path.split(sch),
root)
Run Code Online (Sandbox Code Playgroud)
祝你在你的路径规范中找到任何错误 ;-)
归档时间: |
|
查看次数: |
22688 次 |
最近记录: |