Elementtree和Unicode或UTF-8混淆

时间:2013-11-07 15:29:10

标签: python xml unicode utf-8

好的,我现在感觉有点失落。我有unicode(或utf-8?)

的问题

我在linux上使用Python3.3(但我在Windows上遇到同样的问题)。

我尝试使用Elementtree创建XML文件。

    item = ET.Element("item")
    item_title = Et.SubElement(item, "title")

这当然不是一切,只是一个例子。 所以现在我希望标签'title'有这样的文本(用随机内容替换## Content ##,并不重要):

    # Thats how I create the text for the tag
    item.title.text = u'<![CDATA[##CONTENT##]>'

    # This is how I want it to look like
    <title><![CDATA[##CONTENT##]></title>

    # Thats what I get
    <title>&lt;![CDATA[##CONTENT##]&gt;</title>

    # These are some of the things I tried for writing it to an xml file
    ET.ElementTree(item).write(myOutputFile, encoding="unicode")
    myOutputFile.write(ET.tostring(item, encoding='unicode', method='xml')))
    myOutputFile.write(str(ET.tostring(item, encoding='utf-8', method='xml'))) 
    myOutputFile.write(str(ET.tostring(item)

    # Oh and thats how I open the file for writing
    myOutputFile = codecs.open(HereIsMyFile, 'w', encoding='utf-8')

我试图搜索并发现了一些类似的声音问题(我试过的一些东西已经来自SO),但似乎都没有。他们改变了输出中的一些东西,但从未显示过&lt;或者&gt;。 我也注意到,如果我使用utf-8,我必须在写入文件时使用str()。这让我对unicode和utf-8的区别感到困惑,我试着读一些关于那个的东西,但这对我的实际问题并没有真正的帮助。

此时我真的不知道在哪里寻找我的错误,我想知道在哪里寻找。 这是我写入文件的方式吗?我怎么打开它? 或者是Elementtree导致错误? (我没有尝试过别的东西,比如lxml,因为好吧,这意味着重写很多东西我猜)。

我希望你能帮助我,如果事情不明确,我会尝试更好地解释一下!

编辑:哦,我也尝试在没有编解码器的情况下打开文件,因为我在Python3.x中不再需要读取它,但我不再那么确定了,所以我试了一下。

2 个答案:

答案 0 :(得分:1)

  1. 使用ElementTree编写XML文档的正确方法是:

    with codecs.open(HereIsMyFile,'w',encoding ='utf-8'):        root.write(myOutputFile)

  2. 如果您为write()指定编码,则必须使用what the XML standard definesunicode不是编码,而是标准。

  3. ElementTree不支持CDATA。你看到的效果是ElementTree注意到节点text中的特殊字符,它会逃脱它们;没有办法阻止它。

    此答案包含CDATA元素的实现:How to output CDATA using ElementTree

答案 1 :(得分:1)

这里似乎有几层混乱。

首先采用较低级别:UTF-8等编码将 Unicode字符转换为字节。您的问题是生成的XML中的字符不是您想要的字符,而不是这些字符如何存储为字节,因此没有任何东西可以修复。

其次,你似乎在期待这一行的错误:

item.title.text = u'<![CDATA[##CONTENT##]>'

这告诉ElementTree您希望在解析的文档中使用该文本。考虑一下:

item.title.text = u'I <3 ASCII art.'

ElementTree不会将其直接存储在标记中:它会将其转换为

<title>I &lt;3 ASCII art.</title>

同样地:

item.title.text = u"This </title> isn’t the end of the title"

变为

<title>This &lt;/title&gt; isn&#8217;t the end of the title</title>

希望你能看到这个的价值:无论你在那里放什么文字,它都不会破坏元素标记,或者确实以任何方式影响它。

请注意,由于此自动转换,您很可能根本不需要CDATA部分

但是,如果出于某种原因,你可以通过明确说明它来使用它(使用lxml.etree):

title = lxml.etree.Element('title')
title.text = lxml.etree.CDATA('###CONTENT###')
print(lxml.etree.tostring(title))

输出:

<title><![CDATA[###CONTENT###]]></title>