使用C#.NET处理XML中的禁用字符

时间:2009-10-29 22:37:35

标签: c# .net xml serialization xml-serialization

我有一个对象,我正在序列化为xml。看来其中一个属性中的值包含十六进制字符0x1E。我已经尝试将XmlWriterSettings的Encoding属性设置为“utf-16”和“unicode”但我仍然会抛出异常:

这是生成XML文档的错误。 ---> System.InvalidOperationException:生成XML文档时出错。 ---> System.ArgumentException:'',十六进制值0x1E,是无效字符。

有没有办法让这些字符进入xml?如果没有,是否还有其他字符会导致问题?

6 个答案:

答案 0 :(得分:7)

XML推荐(又名规范)http://www.w3.org/TR/2000/REC-xml-20001006概述了哪些字符不被允许且必须被转义

<小时/> 2.2字符

[定义:解析的实体包含文本,一系列字符,可以表示标记或字符数据。] [定义:字符是ISO / IEC 10646 [ISO / IEC 10646]规定的文本原子单位(另见[ISO / IEC 10646-2000])。合法字符包括制表符,回车符,换行符以及Unicode和ISO / IEC 10646的合法字符.A.1规范性引用文件中引用的这些标准的版本在本文档编写时是最新的。可以通过修订或新版本将新字符添加到这些标准中。因此,XML处理器必须接受为Char指定的范围内的任何字符。不建议使用[Unicode]第6.8节中定义的“兼容性字符”(参见[Unicode3]第3.6节中的D21)。]

角色范围

[2]     Char       ::=      #x9 | #xA | #xD | [#x20-#xD7FF] |
            [#xE000-#xFFFD] | [#x10000-#x10FFFF]    
     /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */

将字符代码点编码为位模式的机制可能因实体而异。所有XML处理器必须接受10646的UTF-8和UTF-16编码;用于发信号通知两者中的哪一个正在使用或用于使其他编码发挥作用的机制将在后面的4.3.3实体中的字符编码中讨论。


答案 1 :(得分:2)

你可以像对待HTML那样逃避。 0x1E与十进制30相同,所以只需用字符串“&amp; 30;”替换你的记录分隔符。它应该没问题。

答案 2 :(得分:2)

我知道这是一个老问题,但是我找到了一个链接,我在这里发布了它,对于遇到这个问题的人来说会很有用。它对我有用。

http://seattlesoftware.wordpress.com/2008/09/11/hexadecimal-value-0-is-an-invalid-character/

来自该网站的代码。(如果网站出现故障)

/// <summary>
/// Remove illegal XML characters from a string.
/// </summary>
public string SanitizeXmlString(string xml)
{
if (xml == null)
{
    throw new ArgumentNullException("xml");
}

StringBuilder buffer = new StringBuilder(xml.Length);

foreach (char c in xml)
{
    if (IsLegalXmlChar(c))
    {
        buffer.Append(c);
    }
}

return buffer.ToString();
}

/// <summary>
/// Whether a given character is allowed by XML 1.0.
/// </summary>
public bool IsLegalXmlChar(int character)
{
return
(
     character == 0x9 /* == '\t' == 9   */          ||
     character == 0xA /* == '\n' == 10  */          ||
     character == 0xD /* == '\r' == 13  */          ||
    (character >= 0x20    && character <= 0xD7FF  ) ||
    (character >= 0xE000  && character <= 0xFFFD  ) ||
    (character >= 0x10000 && character <= 0x10FFFF)
);
}

答案 3 :(得分:1)

XML是一种人类可读的格式,禁止使用不可打印的控制字符。您可以使用十进制字符实体代码,例如&amp;#30;表示它们,或base-64编码内容。

答案 4 :(得分:1)

由于您没有提供任何详细信息,我猜您的属性属于System.String类型。如果是这样,那么你不能按原样序列化它。相反,您必须将其序列化为byte []:

[XmlRoot("root")]
public class HasBase64Content
{
    [XmlIgnore]
    public string Content { get; set; }

    [XmlElement("Content")]
    public byte[] Base64Content
    {
        get
        {
            return System.Text.Encoding.UTF8.GetBytes(Content);
        }
        set
        {
            if (value == null)
            {
                Content = null;
                return;
            }

            Content = System.Text.Encoding.UTF8.GetString(value);
        }
    }
}

答案 5 :(得分:1)

如果您的数据不允许来自Unicode Control Picture块的字符,则可以通过在序列化时将它们替换为控制字符来保持人类可读性,并在反序列化时再次返回。

以下是字符:

␀␁␂␃␅␆␇␈␉␊␋␍␎␏␏

␐␑␒␓␕␖␗␘␙␚␛␝␞␟␟

␠␡

希望它们能在您的浏览器和编辑器中呈现。即使他们不是,他们在XML中也是合法的。