OpenXML 转义非法字符

OpenXML escaping illegal characters

我正在使用 OpenXML Power Tools and it is working as expected. However things break when I have invalid characters in the substitution such as ampersand, so for instance "Harry & Sally" will break and produce an invalid document. According to this post 在 Word Docx 文件中进行一些字符串替换,需要将非法字符转换为 xHHHH。

我无法找到 post 中提到的 OOXML 子句的内容,因此无法正确转义字符。

我希望有人对需要转义的字符有一些代码或见解。我也希望 OpenXML Power Tools 能以某种方式为我做这件事,但我似乎也无法在其中找到任何东西。

规范只是在讨论 XML 中必须转义的标准字符集。链接 post 中提到的 XML 规范来自 W3C,found here

有五个字符需要在它们出现在 XML 数据(名称、值等)中的任何位置进行转义,除非它们是 CDATA 部分的一部分。根据第 2.4 节:

The ampersand character (&) and the left angle bracket (<) must not appear in their literal form, except when used as markup delimiters, or within a comment, a processing instruction, or a CDATA section. If they are needed elsewhere, they must be escaped using either numeric character references or the strings " &amp; " and " &lt; " respectively. The right angle bracket (>) may be represented using the string " &gt; ", and must, for compatibility, be escaped using either " &gt; " or a character reference when it appears in the string " ]]> " in content, when that string is not marking the end of a CDATA section.

To allow attribute values to contain both single and double quotes, the apostrophe or single-quote character (') may be represented as " &apos; ", and the double-quote character (") as " &quot; ".

换句话说,对以下字符进行转义:

' -> &apos;
" -> &quot;
> -> &gt;
< -> &lt;
& -> &amp;

通常,您不会将它们编码为 xHHHH,您会使用上面列出的 XML 实体,但两者都是允许的。您也不需要 需要 在每种情况下都对引号或右尖括号进行编码,只有当它们以其他方式表示 XML 语法时才进行编码,但这样做通常更安全时间。

XML 规范还包括可以出现在 XML 文档中的每个 Unicode 字符的列表,在第 2.2 节中:

Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]

该列表基本上包括 Basic 平面中的每个 Unicode 字符(您可能 运行 进入的每个字符),控制字符除外。只允许使用制表符、CR 和 LF 字符——任何低于 ASCII 32 (space) 的其他字符都需要转义。

列表中的大空缺 (0xD800-0xDFF) 是代理编码值,它们本身不应出现,因为它们不是有效字符。最后两个 0xFFFE 和 0xFFFF 也不是有效字符。

我在 Michael Edenfield 的回答的帮助下创建了一个扩展方法。非常自我解释...... 只要确保你先替换了符号! 否则你最终会错误地替换你的其他转义符号。

public static string EscapeXmlCharacters(this string input)
{
    switch (input)
    {
        case null: return null;
        case "": return "";
        default:
        {
            input = input.Replace("&", "&amp;")
                .Replace("'", "&apos;")
                .Replace("\"", "&quot;")
                .Replace(">", "&gt;")
                .Replace("<", "&lt;");

            return input;
        }
    }
}

.NET Fiddle: https://dotnetfiddle.net/PCqffy