【问题标题】:xmltodict does not return a list for one elementxmltodict 不返回一个元素的列表
【发布时间】:2016-05-13 10:15:42
【问题描述】:

如果“车库”中只有一辆“汽车”,则以下代码会产生错误:

import xmltodict

mydict = xmltodict.parse(xmlstringResults)    
for carsInGarage in mydict['garage']['car']:
    # do something...

原因是mydict['garage']['car'] 只是一个列表,如果有多个“汽车”元素。所以我做了这样的事情:

import xmltodict

mydict = xmltodict.parse(xmlstringResults)
if isinstance(mydict['garage']['car'], list):
    for carsInGarage in mydict['garage']['car']:
        # do something for each car...
else:
    # do something for the car

让代码运行。但对于更高级的操作,这不是解决方案。

是否有人知道使用某种功能,即使只有一个元素?

【问题讨论】:

  • 不要使用保留关键字如dict作为变量名!
  • 如果xmltodict 返回一辆汽车或一辆list 的汽车,则您的解决方案是合适的(请参阅Python 中的duck typing)。但是,请记住 XML 是有序的,生成的 JSON 使用无序的 dict!有什么理由不直接使用 XML,例如lxml?
  • 在我的真实代码中它有一个不同的名称,但我也修复了代码上面的代码,谢谢。 - 我的第一次尝试是使用 ElementTree,但我遇到了一些编码问题......我认为这种方式可能更好......也许我错了

标签: python list xmltodict


【解决方案1】:

this issue on Github 讨论了这个问题。 xmltodict 包现在支持

d = xmltodict.parse(s, force_list={'car'})

尽管如果该字段不存在,这仍然不会创建一个空列表。

【讨论】:

  • 谢谢。我是 Python 中 XML 解析的新手,所以这为我节省了大量工作。
【解决方案2】:

这当然不是一种优雅的方式,但这是我为使代码运行所做的工作(如果有人遇到同样的问题并通过谷歌找到了这个):

import xmltodict

def guaranteed_list(x):
    if not x:
        return []
    elif isinstance(x, list):
        return x
    else:
        return [x]

mydict = xmltodict.parse(xmlstringResults)    
for carsInGarage in guaranteed_list(mydict['garage']['car']):
    # do something...

但我想我会再次编写我的代码并像其中一位 cmets 所说的那样“直接使用 XML”。

【讨论】:

    【解决方案3】:

    我正在使用的组合

    1)

    json_dict = xmltodict.parse(s, force_list={'item'})
    

    2)

    # Removes a level in python dict if it has only one specific key
    # 
    # Examples: 
    # recursive_skip_dict_key_level({"c": {"a": "b"}}, "c")  # -> {"a", "b"}
    # recursive_skip_dict_key_level({"c": ["a", "b"]}, "c") # -> ["a", "b"]
    #
    def recursive_skip_dict_key_level(d, skipped_key):
        if issubclass(type(d), dict):
            if list(d.keys()) == [skipped_key]:
                return recursive_skip_dict_key_level(d[skipped_key], skipped_key)
            else:
                for key in d.keys():
                    d[key] = recursive_skip_dict_key_level(d[key], skipped_key)
                return d
        elif issubclass(type(d), list):
            new_list = []
            for e in d: 
                new_list.append(recursive_skip_dict_key_level(e, skipped_key))
            return new_list
        else: 
            return d
    
    
    # Removes None values from a dict
    # 
    # Examples: 
    # recursive_remove_none({"a": None})  # -> {}
    # recursive_remove_none([None]) # -> []
    #
    def recursive_remove_none(d):
        if issubclass(type(d), dict):
            new_dict = {}
            for key in d.keys():
                if not (d[key] is None):
                    new_dict[key] = recursive_remove_none(d[key])
            return new_dict
        elif issubclass(type(d), list):
            new_list = []
            for e in d: 
                if not (e is None):
                    new_list.append(recursive_remove_none(e))
            return new_list
        else: 
            return d       
    
    
    json_dict = recursive_skip_dict_key_level(json_dict, "item")
    json_dict = recursive_remove_none(json_dict)
    

    将任何“项目”XML 元素解释为列表。

    【讨论】:

      【解决方案4】:

      除了现有的答案之外,xmltodict 现在还支持以下内容以强制 everything 成为列表:

      xml = xmltodict.parse(s, force_list=True)
      

      【讨论】:

        猜你喜欢
        • 2022-01-15
        • 1970-01-01
        • 1970-01-01
        • 2021-11-19
        • 2016-09-26
        • 2023-04-02
        • 2016-01-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多