使用Python 3.2从头开始创建Unicode XML

mik*_*173 6 python xml unicode python-3.x xml.etree

基本上,我想生成一个XML,其中包含从python字典中的数据生成的元素,其中将成为标记的是字典的键,而文本是字典的值.我没有必要给项目赋予属性,我想要的输出看起来像这样:

<AllItems>

  <Item>
    <some_tag> Hello World </some_tag>
    ...
    <another_tag />
  </Item>

  <Item> ... </Item>
  ...

</AllItems>
Run Code Online (Sandbox Code Playgroud)

我尝试使用xml.etree.ElementTree包,通过创建树,将Element"AllItems"设置为根,如下所示:

from xml.etree import ElementTree as et

def dict_to_elem(dictionary):
    item = et.Element('Item')
    for key in dictionary:
        field = et.Element(key.replace(' ',''))
        field.text = dictionary[key]
        item.append(field)
    return item

newtree = et.ElementTree()
root = et.Element('AllItems')
newtree._setroot(root)

root.append(dict_to_elem(  {'some_tag':'Hello World', ...}  )
# Lather, rinse, repeat this append step as needed

with open(  filename  , 'w', encoding='utf-8') as file:
    tree.write(file, encoding='unicode')
Run Code Online (Sandbox Code Playgroud)

在最后两行中,我尝试在open()语句中省略了编码,在write()方法中省略并更改为'UTF-8'编码,我得到的错误是'')类型为str不可序列化

所以我的问题 - 我想知道的是我应该如何使用上面的格式从头开始创建UTF-8 XML,并且使用另一个包有更强大的解决方案,这将正确地允许我处理UTF-8字符?我没有与ElementTree结婚以获得解决方案,但我宁愿不必创建架构.提前感谢任何建议/解决方案!

pep*_*epr 6

在我看来,这ElementTree是一个不错的选择.如果将来需要更强大的软件包,可以切换到lxml使用相同接口的第三方模块.

您可以在文档http://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.ElementTree.write中找到问题的答案.

输出是字符串(str)或二进制(字节).这由encoding参数控制.如果编码是"unicode",则输出是一个字符串; 否则,它是二进制的.请注意,如果它是一个打开的文件对象,这可能与文件类型冲突; 确保不要尝试将字符串写入二进制流,反之亦然.

基本上,你正确地做到了.你open()在文本模式下的文件,这样文件接受字符串,你需要使用'unicode'参数tree.write().否则,您可以以二进制模式打开文件(在其中没有编码参数open())并使用'utf-8'tree.write().

一个有点清理的代码,可以自行运行:

#!python3
from xml.etree import ElementTree as et

def dict_to_elem(dictionary):
    item = et.Element('Item')
    for key in dictionary:
        field = et.Element(key.replace(' ',''))
        field.text = dictionary[key]
        item.append(field)
    return item

root = et.Element('AllItems')     # create the element first...
tree = et.ElementTree(root)       # and pass it to the created tree

root.append(dict_to_elem(  {'some_tag':'Hello World', 'xxx': 'yyy'}  ))
# Lather, rinse, repeat this append step as needed

filename = 'a.xml'
with open(filename, 'w', encoding='utf-8') as file:
    tree.write(file, encoding='unicode')

# The alternative is...    
fname = 'b.xml'
with open(fname, 'wb') as f:
    tree.write(f, encoding='utf-8')
Run Code Online (Sandbox Code Playgroud)

这取决于目的.在这两者中,我个人更喜欢第一种解决方案.它清楚地说你写了一个文本文件(而XML是一个文本文件).

但是,您不需要告诉编码的最简单的替代方法就是将文件名传递给tree.write:

tree.write('c.xml', encoding='utf-8')
Run Code Online (Sandbox Code Playgroud)

它打开文件,使用给定的编码写入内容(在下面的Sebastian评论后更新),然后关闭文件.你可以轻松阅读它,你可以在这里犯错误.

  • 注意:`tree.write()`使用ascii而没有明确的`encoding`参数.它将所有非ascii字符转换为xml字符引用,例如,`'☺' - >'&#9786'. (2认同)

jfs*_*jfs 5

它应该没有必要,但如果您的工具不理解生成的xml文件,您可以显式添加xml声明:

#!/usr/bin/env python3
from xml.etree import ElementTree as etree

your_dict = {'some_tag': 'Hello World ?'}

def add_items(root, items):
    for name, text in items:
        elem = etree.SubElement(root, name)
        elem.text = text

root = etree.Element('AllItems')
add_items(etree.SubElement(root, 'Item'),
          ((key.replace(' ', ''), value) for key, value in your_dict.items()))
tree = etree.ElementTree(root)
tree.write('output.xml', xml_declaration=True, encoding='utf-8')
Run Code Online (Sandbox Code Playgroud)

与Output.xml:

<?xml version='1.0' encoding='utf-8'?>
<AllItems><Item><some_tag>Hello World ?</some_tag></Item></AllItems>
Run Code Online (Sandbox Code Playgroud)