我正在编写一个记录终端交互的Python程序(类似于脚本程序),我想以XML格式存储日志。
问题是终端交互包括VT100转义码。如果我将数据写入UTF-8编码的文件,Python就不会抱怨,例如:
...
pid, fd = pty.fork()
if pid==0:
os.execvp("bash",("bash","-l"))
else:
# Lots of TTY-related stuff here
# see http://groups.google.com/group/comp.lang.python/msg/de40b36c6f0c53cc
fout = codecs.open("session.xml", encoding="utf-8", mode="w")
fout.write('<?xml version="1.0" encoding="UTF-8"?>\n')
fout.write("<session>\n")
...
r, w, e = select.select([0, fd], [], [], 1)
for f in r:
if f==fd:
fout.write("<entry><![CDATA[")
buf = os.read(fd, 1024)
fout.write(buf)
fout.write("]]></entry>\n")
else:
....
fout.write("</session>")
fout.close()
这个脚本“工作”意味着它将文件写入磁盘,但生成的文件不正确utf-8,这会导致像etree这样的XML解析器对转义码进行barf。
解决这个问题的一种方法是首先filter out the escape codes。但是,如果可以做这样的事情,其中维护转义码并且结果文件可以由像etree这样的XML工具解析?
答案 0 :(得分:2)
你的问题不在于控制代码不是正确的UTF-8,它们只是ASCII ESC
而朋友不是正确的XML字符,即使在CDATA部分内也是如此。
XML 1.0中唯一有效值小于U + 0020的XML字符是U + 0009(制表符),U + 000A(换行符)和U + 000D(回车)。如果你想记录涉及其他代码的东西,比如escape(U + 001B)那么你将不得不以某种方式逃避它们。没有其他选择。
答案 1 :(得分:1)
正如Charles所说,大多数控制代码可能根本不包含在XML 1.0文件中。
但是,如果您可以使用XML 1.1,则可以在那里使用它们。它们不能作为原始字符包含在内,但可以作为字符引用。例如:

因为您无法在CDATA部分中编写字符引用(它们只是被解释为ampersand-hash -...),您将不得不丢失<![CDATA[
包装并手动转义{{1字符到它们的实体引用等价物。
请注意,无论如何都应该这样做:CDATA部分不会免除您对文本转义的责任,因为如果内部文本包含序列&<>
,它们将失败。 (因为你总是必须进行一些转义,这使得CDATA部分在大多数情况下都没用。)
XML 1.1对控制代码更加宽容,但并非所有内容都支持它,您仍然不能包含NUL字符(]]>
)。通常,在XML中包含控制字符并不是一个好主意。您可以使用ad-hoc编码方案来适应二进制; base-64很受欢迎,但不是很容易阅读。替代方案可能包括使用私有使用区中的随机字符作为替代,如果它只是您自己的应用程序将处理文件,或将它们编码为元素(例如�
)。
答案 2 :(得分:-1)
您是否尝试将数据放入CDATA部分?这应该可以防止解析器尝试读取标记的内容。