本节书摘来自异步社区《Python Cookbook(第3版)中文版》一书中的第6章,第6.5节,作者[美]David Beazley , Brian K.Jones,陈舸 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。
6.5 将字典转换为XML
6.5.1 问题
我们想将Python字典中的数据转换为XML。
6.5.2 解决方案
尽管xml.etree.ElementTree库通常用来解析XML文档,但它同样也可以用来创建XML文档。例如,考虑下面这个函数:
from xml.etree.ElementTree import Element
def dict_to_xml(tag, d):
'''
Turn a simple dict of key/value pairs into XML
'''
elem = Element(tag)
for key, val in d.items():
child = Element(key)
child.text = str(val)
elem.append(child)
return elem
下面是使用这个函数的示例:
>>> s = { 'name': 'GOOG', 'shares': 100, 'price':490.1 }
>>> e = dict_to_xml('stock', s)
>>> e
<Element 'stock' at 0x1004b64c8>
>>>
转换的结果是一个Element实例。对于I/O操作来说,可以利用xml.etree.ElementTree中的tostring()函数将其转换为字节串。示例如下:
>>> from xml.etree.ElementTree import tostring
>>> tostring(e)
b'<stock><price>490.1</price><shares>100</shares><name>GOOG</name>'
>>>
如果想为元素附加上属性,可以使用set()方法实现:
>>> e.set('_id','1234')
>>> tostring(e)
b'<stock _id="1234"><price>490.1</price><shares>100</shares><name>GOOG</name>
</stock>'
>>>
如果需要考虑元素间的顺序,可以创建OrderedDict(有序字典)来取代普通的字典。参见1.7节中对有序字典的介绍。
6.5.3 讨论
当创建XML时,也许会倾向于只使用字符串来完成。比如:
def dict_to_xml_str(tag, d):
'''
Turn a simple dict of key/value pairs into XML
'''
parts = ['<{}>'.format(tag)]
for key, val in d.items():
parts.append('<{0}>{1}</{0}>'.format(key,val))
parts.append('</{}>'.format(tag))
return ''.join(parts)
问题在于如果尝试手工处理的话,那么这就是在自找麻烦。比如,如果字典中包含有特殊字符时会发生什么?
>>> d = { 'name' : '<spam>' }
>>> # String creation
>>> dict_to_xml_str('item',d)
'<item><name><spam></name></item>'
>>> # Proper XML creation
>>> e = dict_to_xml('item',d)
>>> tostring(e)
b'<item><name><spam></name></item>'
>>>
请注意在上面这个示例中,字符<和>分别被<和>取代了。
下面的提示仅供参考。如果需要手工对这些字符做转义处理,可以使用xml.sax.saxutils中的escape()和unescape()函数。示例如下:
>>> from xml.sax.saxutils import escape, unescape
>>> escape('<spam>')
'<spam>'
>>> unescape(_)
'<spam>'
>>>
为什么说创建Element实例要比使用字符串好?除了可以产生出正确的输出外,其他的原因在于这样可以更加方便地将Element实例组合在一起,创建出更大的XML文档。得到的Element实例也能够以各种方式进行处理,完全不必担心解析XML文本方面的问题。最重要的是,我们能够站在更高的层面上对数据进行各种处理,只在最后把结果作为字符串输出即可。