Created
March 4, 2022 06:42
-
-
Save ImN1/cbcbfabb9ed2f277c926427f4598bbb7 to your computer and use it in GitHub Desktop.
python xpath string/text convert to nested dict
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
def xpath2Dict(xpaths, nested:bool=True, sep:str='/')->Dict: | |
''' | |
xpaths: String | Iterable,前者按 splitlines 拆分为后者\n | |
可以包含或不包含枝节点,例如:\n | |
topnode/node\n | |
topnode/node/leaf\n | |
两条同时存在,或者仅有第二条,都能构建树状 dict。\n | |
分隔符在开头或结尾都会舍弃,相应的首节点、末节点按照处理后的 xpath 计算\n | |
leaf 将优先视为 json 格式,按 json.loads 处理,不能处理才按 string 构建末节点的值\n | |
如果 leaf 只有单值(整数、小数或字符串等),字典的值为一维列表\n | |
如果 leaf 为列表等对象,则值为二维列表(整数、小数或字符串等转为单元素列表)\n | |
nested: bool, default True\n | |
True: 返回格式 {'topnode': {'node': leaf}}\n | |
False: 返回格式 {'topnode/node': leaf} | |
''' | |
def tryJson(item): | |
try: | |
return json.loads(item) | |
except: | |
return item | |
if isinstance(xpaths, (str, bytes)): | |
xpaths = xpaths.splitlines() | |
# xpaths = sorted(xpaths.splitlines()) | |
# xpaths = sorted(xpaths, key=lambda x: x.count(sep), reverse=True) | |
fd0 = (x.strip(sep).rsplit(sep, 1) for x in xpaths) | |
# fd = dict((x[0], tryJson(x[1])) for x in fd) | |
fd = {} | |
dims = False | |
for x in fd0: | |
key = x[0] | |
v = tryJson(x[1]) | |
if isinstance(v, (int, float, complex, str, bytes, type(None))): | |
v = [v] | |
else: | |
dims = True | |
if key in fd: | |
value = fd[key] | |
value.append(v) | |
else: | |
value = [v] | |
fd[key] = value | |
if not dims: | |
fd = {k:list(chain.from_iterable(v)) for k,v in fd.items()} | |
if not nested: | |
return fd | |
def insert(dct, lst): | |
for x in lst[:-2]: | |
dct[x] = dct = dct.get(x, dict()) | |
dct.update({lst[-2]: lst[-1]}) | |
d = {} | |
lsts = ([*k.split(sep), v] for k, v in fd.items()) | |
for lst in lsts: | |
insert(d, lst) | |
return d | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment