如何在mako中正确转义输出(用于XHTML)?

3 投票
2 回答
1842 浏览
提问于 2025-04-15 18:23

尽管提供了一种很好的方式来使用过滤器处理输出,但这些过滤器都没有做到正确的效果。我们来看这个字符串:

x=u"&\u0092"

这些过滤器的处理方式如下:

x             Turns the & into an entity but not the \u0092 (valid XML but not XHTML)
h             Exactly the same
u             Escapes both, but obviously uses url escaping
entities      Only converts named entities, so again only the & is escaped
decode.latin1 The same

HTML使用的是标准的UNICODE字符集,其中有65个字符代码是未定义的(包括0到31和127到159的字符)

这些字符似乎是被遗漏掉的。有没有什么想法?

补充说明

如果我在离线状态下使用这个文件,它似乎是有效的。这可能是内容类型的问题吗?

2 个回答

1

除了验证问题,能够去掉这些字符(反正它们也不太好显示)是很有用的,而且不需要去处理其他任何东西。为此,我在 `lib/helpers.py` 文件里添加了以下这个函数:

__sgml_invalid = re.compile(r'[\x82-\x8c\x91-\x9c\x9f]', re.UNICODE)

def sgmlsafe(text):
    lookup = {
        130:"‚",    #Single Low-9 Quotation Mark
        131: "ƒ",    #Latin Small Letter F With Hook
        132:"„",    #Double Low-9 Quotation Mark
        133:"…",    #Horizontal Ellipsis
        134:"†",    #Dagger
        135:"‡",    #Double Dagger
        136: "ˆ",    #Modifier Letter Circumflex Accent
        137:"‰",    #Per Mille Sign
        138: "Š",    #Latin Capital Letter S With Caron
        139:"‹",    #Single Left-Pointing Angle Quotation Mark
        140: "Œ",    #Latin Capital Ligature OE
        145:"‘",    #Left Single Quotation Mark
        146:"’",    #Right Single Quotation Mark
        147:"“",    #Left Double Quotation Mark
        148:"”",    #Right Double Quotation Mark
        149:"•",    #Bullet
        150:"–",    #En Dash
        151:"—",    #Em Dash
        152: "˜",    #Small Tilde
        153:"™",    #Trade Mark Sign
        154: "š",    #Latin Small Letter S With Caron
        155:"›",    #Single Right-Pointing Angle Quotation Mark
        156: "œ",    #Latin Small Ligature OE
        159: "Ÿ"     #Latin Capital Letter Y With Diaeresis
        }

    return __sgml_invalid.sub(lambda x: lookup[ord(x.group())], text)

然后你可以通过编辑 environment.py 来把这个函数作为一个过滤器提供出来:

config['pylons.app_globals'].mako_lookup = TemplateLookup(
    ...
    imports=[....,'from appname.lib.helpers import sgmlsafe',...]

这样一来,它就可以在你的模板中使用了:

${c.content|n,sgmlsafe}
2

在HTML中,除非你特意使用ASCII字符集,否则不需要把Unicode字符转换成&#xxxx;这种形式。其实,使用命名实体来转义字符更简单、更高效,然后把整个字符串编码成UTF-8格式,直接这样写就可以了。你最好在HTTP头部或者在<meta>标签中声明你使用的编码方式。

编辑:

如果我在离线状态下使用这个文件,它似乎可以通过验证。这可能是内容类型的问题吗?

没错。你可以通过HTTP头部来强制使用UTF-8字符集,或者直接在HTML中通过meta标签来指定:

<meta http-equiv="Content-Type" content="application/xhtml+xml;charset=utf-8" />

撰写回答