为什么LINQ to XML不能像'\ x1A'那样转义字符?

时间:2015-12-17 09:53:20

标签: c# xml linq

如果在XElement的内容中包含'\ x1A','\ x1B','\ x1C','\ x1D','\ x1E'或'\ x1F'等字符,我会收到异常

using System;
using System.Collections.Generic;
using System.Xml.Linq;

namespace LINQtoXMLInvalidChars
{
    class Program
    {
        private static readonly IReadOnlyCollection<char> InvalidCharactersInXml = new List<char>
        {
            '<',
            '>',
            '&',
            '\'',
            '\"',
            '\x1A',
            '\x1B',
            '\x1C',
            '\x1D',
            '\x1E',
            '\x1F'
        };

        static void Main()
        {
            foreach (var c in InvalidCharactersInXml)
            {
                var xEl = new XElement("tag", "Character: " + c);
                var xDoc = new XDocument(new XDeclaration("1.0", "utf-8", null), xEl);

                try
                {
                    Console.Write("Writing " + c + ": ");
                    Console.WriteLine(xDoc);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Oops.    " + e.Message);
                }
            }

            Console.ReadKey();
        }
    }
}

In an answer from Jon Skeet问题String escape into XML我读了

  

您在节点中设置文本,它将自动转义所需的任何内容。

所以现在我很困惑。我误解了什么吗?

一些背景信息XElement的字符串内容来自最终用户。我看到了两个使我的应用程序健壮的选项: 1)到Base-64对字符串进行编码,然后将其传递到XElement 2)以缩小接受的集合例如,字符字母数字字符。

1 个答案:

答案 0 :(得分:4)

大多数这些字符根本不在XML 1.0中有效。我个人希望LINQ to XML无法生成以后无法解析的文档,但基本上你应该避免使用它们。

我还建议尽量避免使用\x作为转义序列,更喜欢\u - \x将取“4个十六进制数字”这一事实可能非常令人困惑。

来自XML 1.0 spec

  

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

现在U + 000D和U + 000A是有趣的案例 - 它们不会在文本节点中转义;他们只是逐字被包括在内。当你解析节点时,它是否存在将取决于解析设置(以及它周围是否有非空白字符)。

就如何处理这种情况而言:你肯定有以下选项:

  • 执行您自己的编码/转义。这通常有点痛苦,并且会导致与常规XML文档相比难以阅读的XML文档。您可以潜在地仅在需要时执行此操作,例如向元素添加属性以表明您已完成此操作。
  • 检测并删除XML中无效的字符
  • 检测并拒绝包含XML无效字符的字符串

我们无法确定哪种情况最适合您的情景。