Python:遍历xmltodi创建的所有嵌套keyvalue对

2024-09-28 23:17:42 发布

您现在位置:Python中文网/ 问答频道 /正文

根据xml文件的布局获取特定的值非常简单。(参见:StackOverflow

但是当我不知道xml元素时,我就不能递归它。 因为xmltodoc在OrderedDicts中嵌套OrderedDicts。Python将这些嵌套的ordereddict类型化为“unicode”。而不是(仍然)按顺序排列的图片。所以像这样循环是行不通的:

def myprint(d):
    for k, v in d.iteritems():
        if isinstance(v, list):
            myprint(v)
        else:
            print "Key :{0},  Value: {1}".format(k, v)

我基本上想要的是递归整个xml文件,其中显示每个键值对。当一个键的值是另一个键值对列表时,它应该递归到其中。在

将此xml文件作为输入:

^{pr2}$

而上面列出的代码中,session下的所有数据都作为一个值添加到key session中。在

输出示例:

Key :session,  Value: OrderedDict([(u'@id', u'2934'), (u'@name', u'Valves'), (u'@docVersion', u'5.0.1'), (u'docInfo', OrderedDict([(u'field', [OrderedDict([(u'@name', u'Employee'), (u'@isMandotory', u'True'), ('#text', u'Jake Roberts')]), OrderedDict([(u'@name', u'Section'), (u'@isOpen', u'True'), (u'@isMandotory', u'False'), ('#text', u'5')]), OrderedDict([(u'@name', u'Location'), (u'@isOpen', u'True'), (u'@isMandotory', u'False'), ('#text', u'Munchen')])])]))])

这显然不是我想要的。在


Tags: 文件keytextnamefalsetruevaluesession
1条回答
网友
1楼 · 发布于 2024-09-28 23:17:42

如果在数据中遇到一个列表,则只需对列表的每个元素调用myprint

def myprint(d):
    if isinstance(d,dict): #check if it's a dict before using .iteritems()
        for k, v in d.iteritems():
            if isinstance(v, (list,dict)): #check for either list or dict
                myprint(v)
            else:
                print "Key :{0},  Value: {1}".format(k, v)
    elif isinstance(d,list): #allow for list input too
        for item in d:
            myprint(item)

然后您将得到如下输出:

^{pr2}$

虽然我不确定这有多有用,因为您有很多重复的键,比如@name,但是我想提供一个我不久前创建的函数来遍历嵌套的dicts和list的嵌套json数据:

def traverse(obj, prev_path = "obj", path_repr = "{}[{!r}]".format):
    if isinstance(obj,dict):
        it = obj.items()
    elif isinstance(obj,list):
        it = enumerate(obj)
    else:
        yield prev_path,obj
        return
    for k,v in it:
        for data in traverse(v, path_repr(prev_path,k), path_repr):
            yield data

然后,您可以使用以下方法遍历数据:

for path,value in traverse(doc):
    print("{} = {}".format(path,value))

使用prev_pathpath_repr的默认值,输出如下:

obj[u'session'][u'@id'] = 2934
obj[u'session'][u'@name'] = Valves
obj[u'session'][u'@docVersion'] = 5.0.1
obj[u'session'][u'docInfo'][u'field'][0][u'@name'] = Employee
obj[u'session'][u'docInfo'][u'field'][0][u'@isMandotory'] = True
obj[u'session'][u'docInfo'][u'field'][0]['#text'] = Jake Roberts
obj[u'session'][u'docInfo'][u'field'][1][u'@name'] = Section
obj[u'session'][u'docInfo'][u'field'][1][u'@isOpen'] = True
obj[u'session'][u'docInfo'][u'field'][1][u'@isMandotory'] = False
obj[u'session'][u'docInfo'][u'field'][1]['#text'] = 5
obj[u'session'][u'docInfo'][u'field'][2][u'@name'] = Location
obj[u'session'][u'docInfo'][u'field'][2][u'@isOpen'] = True
obj[u'session'][u'docInfo'][u'field'][2][u'@isMandotory'] = False
obj[u'session'][u'docInfo'][u'field'][2]['#text'] = Munchen

尽管您可以为path_repr编写一个函数来获取prev_path的值(通过递归调用path_repr)和新的键,例如,一个获取元组并在末尾添加另一个元素的函数意味着我们可以获得(索引元组:elem)格式,它非常适合传递给dict构造函数

def _tuple_concat(tup, idx):
    return (*tup, idx)   
def flatten_data(obj):
    """converts nested dict and list structure into a flat dictionary with tuple keys
    corresponding to the sequence of indices to reach particular element"""
    return dict(traverse(obj, (), _tuple_concat))

new_data = flatten_data(obj)
import pprint
pprint.pprint(new_data)

它提供了以下字典格式的数据:

{('session', '@docVersion'): '5.0.1',
 ('session', '@id'): 2934,
 ('session', '@name'): 'Valves',
 ('session', 'docInfo', 'field', 0, '#text'): 'Jake Roberts',
 ('session', 'docInfo', 'field', 0, '@isMandotory'): True,
 ('session', 'docInfo', 'field', 0, '@name'): 'Employee',
 ('session', 'docInfo', 'field', 1, '#text'): 5,
 ('session', 'docInfo', 'field', 1, '@isMandotory'): False,
 ('session', 'docInfo', 'field', 1, '@isOpen'): True,
 ('session', 'docInfo', 'field', 1, '@name'): 'Section',
 ('session', 'docInfo', 'field', 2, '#text'): 'Munchen',
 ('session', 'docInfo', 'field', 2, '@isMandotory'): False,
 ('session', 'docInfo', 'field', 2, '@isOpen'): True,
 ('session', 'docInfo', 'field', 2, '@name'): 'Location'}

在处理json数据时,我发现这一点特别有用,但我不确定您想如何处理xml。在

相关问题 更多 >