如何强制plistlib在Python中保存转义的特殊字符?



我有一种问题与模块plistlib。它工作得很好,除了保存列表。它不会将撇号保存为特殊字符。它确实将&保存为&,这很好,但将撇号保存为'(而不是'),这就不好了。我有很多有很多文本的列表,当我改变一些东西时(用脚本批量改变),它给了我一个头痛的git diff,因为每一个'将成为'

如何强制plistlib保存所有特殊字符转义的plist(毕竟,只有5个字符)?

我自己来回答这个问题,因为我已经找到了答案。

问题是模块plistlib中的功能_escape(text)。它只转义&, <>,虽然Xcode与它的plist阅读器转义所有五个字符(&, <, >, '"),这就是为什么我认为这个模块也应该。这也是模块plistlib的一个很好的补充,类似于函数escape()中ElementTree的参数entities。该参数是一个包含要替换的附加字符的字典。与plistlib's函数类似的save_plist()将是一个好主意,这样我们可以转义额外的字符。

我的解决方案是基于所谓的猴子补丁。基本上,我复制了整个函数_escape(text),只是添加了额外的转义('"):

from plistlib import _controlCharPat
def patched_escape(text):
    m = _controlCharPat.search(text)
    if m is not None:
        raise ValueError("strings can't contains control characters; "
                         "use bytes instead")
    text = text.replace("rn", "n")       # convert DOS line endings
    text = text.replace("r", "n")         # convert Mac line endings
    text = text.replace("&", "&amp;")       # escape '&'
    text = text.replace("<", "&lt;")        # escape '<'
    text = text.replace(">", "&gt;")        # escape '>'
    text = text.replace("'", "&apos;")      # escape '''
    text = text.replace(""", "&quot;")     # escape '"'
    return text

现在在我的脚本中,我将plistlib's函数_escape(text)替换为我的:

plistlib._escape = patched_escape

现在plistlib正确转义和保存列表。关于猴子打补丁的通常警告也适用于此。我没有其他调用者,只有这个脚本,所以这样做很好。

最新更新