在XML文件中存储VT100转义码

0 投票
3 回答
530 浏览
提问于 2025-04-17 04:48

我正在写一个Python程序,用来记录终端的交互(类似于script程序),我想把日志存储为XML格式。

问题是,终端的交互中包含VT100转义码。Python在我把数据以UTF-8编码写入文件时并不会报错,比如:

...
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解析器在遇到转义码时会出错。

解决这个问题的一种方法是先过滤掉转义码。但是,有没有可能做到保留转义码的同时,让生成的文件可以被像etree这样的XML工具解析呢?

3 个回答

-1

你有没有试过把你的数据放在一个CDATA部分里?这样可以防止解析器去读取标签的内容。

http://en.wikipedia.org/wiki/CDATA

1

正如查尔斯所说,大多数控制代码在 XML 1.0 文件中根本不能使用。

不过,如果你愿意使用 XML 1.1,那么就可以使用这些控制代码。它们不能直接写成字符,但可以用字符引用的方式来表示。例如:

&#27;

因为你不能在 CDATA 区域中写字符引用(它们会被解释成“&”加上数字的形式),所以你需要去掉 <![CDATA[ 的包裹,并手动把 &<> 这些字符转换成它们的实体引用形式。

请注意,你无论如何都应该这样做:CDATA 区域并不能免除你对文本转义的责任,因为如果文本中包含了 ]]> 这个序列,CDATA 区域就会出错。(由于你总是需要进行一些转义,这使得 CDATA 区域在大多数情况下几乎没什么用。)

XML 1.1 对控制代码的限制比较宽松,但并不是所有的地方都支持它,而且你仍然不能包含 NUL 字符(&#0;)。一般来说,在 XML 中包含控制字符并不是个好主意。你可以使用一种临时的编码方式来处理二进制数据;比如 base-64 就很流行,但人类不太容易读懂。另一种选择是,如果只有你自己的应用程序会处理这些文件,可以用私用区域的随机字符作为替代,或者把它们编码成元素(例如 <esc color="1"/>)。

2

你的问题不是控制代码不符合UTF-8标准,它们是符合的。问题在于ASCII中的ESC和其他字符在XML中不算是合法字符,即使是在CDATA部分也不行。

在XML 1.0中,所有值小于U+0020的合法字符只有三个:U+0009(制表符)、U+000A(换行符)和U+000D(回车符)。如果你想记录其他代码,比如转义字符(U+001B),你就得用某种方式对它们进行转义。别无选择。

撰写回答