XML与JSON/字典互相转换

11 Apr 2013

其实一直都不太喜欢xml,相比json,非常之难用。之前看到过超过300页的专门讲xml的书,应该还是我没有理解xml的独到之处吧。今天写一些东西必须要用到xml,所以随手写了个xml和python字典互相转化的代码。 言归正传:当然是不可能简单的完美转换的啦,至少xml的节点还有attribute,当然硬要存下来,也可以用一些关键字做key或者其他手段。 不过对我要做的事儿,是不需要关心attribute属性的,所以代码就前提就是完全忽略了attribute。 经过一番考虑 并 结合代码的便利性,确定了下面的转换格式

<root>
   <person age="18">
       <name>hzj</name>
       <sex>man</sex>
   </person>
   <person age="19" des="hello">
       <name>kiki</name>
       <sex>female</sex>
   </person>
   <person2 age="19" des="hello">
       <name>kiki</name>
       <sex>female</sex>
   </person2>
</root>
 
# ==>
{
    'person2': {
        'name': 'kiki',
        'sex': 'female'
    },
    'person': [
        {
            'name': 'hzj',
            'sex': 'man'
        },
        {
            'name': 'kiki',
            'sex': 'female'
        }
    ]
}

可能细心的会注意到:xml 的 root tag在转换后没有了! 是的,原因是:

  1. xml的标准是根节点必须只有一个,所以没必要再套一层
  2. 便于编码,可以只使用一个递归函数,就完成转换(主要原因,一写就发现了)。

下面是规则和代码:

'''
实现xml和python字典之间的互相转换
规则为:
1. node的attribute全部忽略
2. xml转换到dict的时候,root的tag会被忽略掉,所以结果的最外层的key为xml的第一级子节点的tag
3. dict转xml第2条的逆向,所以需要手动指定一个root的tag
4. xml中有相同tag名的兄弟节点,在转换成dict的时候会变成一个list(因为python的dict是hash字典,不允许重复key)
'''
 
from xml.etree.ElementTree import  Element
 
def xml2dict(element):
    assert  isinstance(element,Element)
    ret = {}
    for child in  list(element):
        print child.tag,child.text
        if len(child) != 0:
            value =  xml2dict(child)
        else:
            value =  child.text
        if child.tag in ret:
            if type(ret[child.tag]) != list:
                ret[child.tag] = [ret[child.tag]]
            ret[child.tag].append(value)
        else:
            ret[child.tag] = value
    return ret
 
def dict2xml(root,content):
    if type(content) == str or type(content) == unicode:
        e = Element(root)
        e.text = content
        return e
 
    e = Element(root)
    for key in content:
        if type(content[key]) == list:
            for one in content[key]:
                e.append(dict2xml(key,one))
        else:
            e.append(dict2xml(key,content[key]))
    return e

完整的包含测试的在这里: https://github.com/dingyaguang117/PythonGist/blob/master/xml_dict.py