【问题标题】:Converting xml to dictionary with values on tags将 xml 转换为带有标签值的字典
【发布时间】:2016-06-20 14:47:01
【问题描述】:

我有一个 XML,每个标签的属性如下:

<?xml version= "1.0" encoding="ISO-8859-1" ?>
<month xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="my.xsd">
    <day Day="2016-1-01">
        <hour Hour="00:00">
            <Variables>
                <a>211.3</a>
                <b>78.94</b>
                <c>0.6</c>
            </Variables>
        </hour>
        <hour Hour="12:00">
            <Variables>
                <a>155.5</a>
                <b>85.5</b>
                <c>0.42</c>
            </Variables>
        </hour>
    </day>
</month>

我希望解析 XML 并转换为字典,但不使用标签,使用属性值。

我的意思是,如何制作类似于:

>>> print d['2016-1-01']['12:00']['b']
>>> 85.5

真正的 XML 还有很多天和几个小时。这可能吗?

我能做的唯一解析它的方法是这个,但如果你想在不同的时间寻找几个不同的变量,这很困难:

# Day
for child_day in root:
    print child_day.tag, child_day.attrib

    # Hour
    for child_hour in child_day:
        print '\t', child_hour.tag, child_hour.attrib

        # Variables
        for child_Variables in child_hour:
            print '\t\t', child_Variables.find('b').text

是否有任何类似于this answer 的函数使属性大小写与此相同而不是标签?

【问题讨论】:

    标签: python xml dictionary elementtree


    【解决方案1】:

    您链接的答案是使用所谓的dict comprehension。这是一个非常简单而优雅的解决方案,因为它将在ElementTree 的每个级别执行相同的操作以生成dict 的该级别,因此该函数可以递归地调用自身。

    但是,如果我理解正确,您将获取每个标签的不同属性,具体取决于您在 ElementTree 结构中的级别以用作 dict 键,然后您将在底层将其切换为使用标签名称作为键,使用文本作为值。所以我想不出一个像你链接的答案中那样优雅的解决方案。

    我们也可以使用dict理解,但我们将不得不使用它几次(至少对于我想出的解决方案)。

    听起来您希望得到一个看起来像这样的dict(给定您的示例 XML):

    {
        "2016-1-01": {
            "12:00": {
                "a": "155.5",
                "b": "85.5",
                "c": "0.42",
            },
            "00:00": {
                "a": "211.3",
                "b": "78.94",
                "c": "0.6",
            },
        },
    }
    

    为此,您需要 3 个函数; 1 来处理dict(天、小时和变量)的每个级别的创建。它们的外观如下:

    def month_etree_to_dict(month):
        d_list = month.getchildren()
        d_dict = {d.attrib["Day"]: day_etree_to_dict(d) for d in d_list}
        return d_dict
    
    def day_etree_to_dict(day):
        h_list = day.getchildren()
        h_dict = {h.attrib["Hour"]: hour_etree_to_dict(h) for h in h_list}
        return h_dict
    
    def hour_etree_to_dict(hour):
        v_list = hour.getchildren()[0].getchildren()
        v_dict = {v.tag: v.text for v in v_list}
        return v_dict
    

    函数month_etree_to_dict 生成一个dict,其中的键是每天的日期。这些值是使用day_etree_to_dict 函数生成的字典。 day_etree_to_dict 函数通过调用 hour_etree_to_dict 函数每小时做同样的事情。 hour_etree_to_dict 函数的工作方式略有不同,它在 ElementTree 中向下跳了一个额外的级别,因此它可以遍历 &lt;Variables&gt; Element 的孩子(&lt;a&gt;&lt;b&gt;&lt;c&gt;)使用它们的标签名称作为 dict 的键,它们的文本作为值。

    我希望这是有道理的,对你有用。

    【讨论】:

    • 简直完美!有了你的解释,我真的理解了更好的词典。谢谢。
    • 没问题!很高兴我能帮上忙!
    【解决方案2】:

    在将 XML 转换为 dict 时,我经常使用递归 defaultdict,如下所示:

    import xml.etree.ElementTree as ET
    from collections import defaultdict
    
    
    def Tree():
        return defaultdict(Tree)
    
    tree = ET.parse('x.xml')
    root = tree.getroot()
    d = Tree()
    for day in root.findall('day'):
        for hour in day.findall('hour'):
            for v in hour.findall('./Variables/*'):
                d[day.attrib['Day']][hour.attrib['Hour']][v.tag] = v.text
    
    print d['2016-1-01']['12:00']['b']
    

    参考:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      • 2015-01-14
      • 2016-08-17
      • 2021-01-18
      • 1970-01-01
      • 2021-03-28
      相关资源
      最近更新 更多