什么是 XML 中的无效字符

Posted

技术标签:

【中文标题】什么是 XML 中的无效字符【英文标题】:What are invalid characters in XML 【发布时间】:2010-10-18 07:48:06 【问题描述】:

我正在使用一些包含以下字符串的 XML:

<node>This is a string</node>

我传递给节点的一些字符串将包含&amp;#$ 等字符:

<node>This is a string & so is this</node>

由于&amp;,这无效。

我无法将这些字符串包装在 CDATA 中,因为它们需要保持原样。我尝试寻找一个字符列表,这些字符在没有 CDATA 的情况下无法放入 XML 节点。

有人可以指点我的方向或向我提供非法字符列表吗?

【问题讨论】:

不使用 CDATA 的任何正当理由? 是的,我正在将字符串传递给一个名为 Fatwire 的 CMS,而带有数据的节点不能在 CDATA 中,我不确定为什么 Fatwire 是这样工作的 :( @Peter:在我的情况下如何使用 CDATA? ***.com/questions/6906705/… 【参考方案1】:

好的,让我们将字符的问题分开:

    在任何 XML 文档中都完全无效。 需要转义。

@dolmen 在“https://***.com/questions/730133/invalid-characters-in-xml/5110103#5110103”中提供的答案仍然有效,但需要使用 XML 1.1 规范进行更新。

1。无效字符

这里所描述的字符是XML文档中允许插入的所有字符。

1.1。在 XML 1.0 中

参考:见XML recommendation 1.0, §2.2 Characters

允许的字符的全局列表是:

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

基本上,控制字符和超出 Unicode 范围的字符是不允许的。 这也意味着禁止调用例如字符实体&amp;#x3;

1.2。在 XML 1.1 中

参考:见XML recommendation 1.1, §2.2 Characters和1.3 Rationale and list of changes for XML 1.1

允许的字符的全局列表是:

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

[2a] RestrictedChar ::= [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]

此版本的 XML 建议扩展了允许的字符,因此允许使用控制字符,并考虑了 Unicode 标准的新版本,但仍然不允许使用这些字符:NUL (x00)xFFFExFFFF...

但是,不鼓励使用控制字符和未定义的 Unicode 字符。

还可以注意到,并非所有解析器都将这一点考虑在内,带有控制字符的 XML 文档可能会被拒绝。

2。需要转义的字符(以获得格式良好的文档):

&lt; 必须使用 &amp;#60; 实体进行转义,因为它被假定为标签的开头。

&amp; 必须使用 &amp;#38; 实体进行转义,因为它被假定为实体引用的开始

&gt; 应使用 &amp;#62; 实体进行转义。这不是强制性的——它取决于上下文——但强烈建议不要使用它。

' 应使用 &amp;#39; 实体进行转义——在单引号内定义的属性中是必需的,但强烈建议始终对其进行转义。

" 应使用 &amp;#34; 实体进行转义——在双引号内定义的属性中是必需的,但强烈建议始终对其进行转义。

【讨论】:

" 但强烈建议始终避开它" - 你能澄清一下吗?谁建议这样做,为什么? (在我看来,在语法允许的任何地方使用文字引号都没有错。)【参考方案2】:

有效字符列表在XML specification:

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

【讨论】:

您应该注意,尽管它们是合法字符,但 &amp; &lt; &gt; " ' 在某些情况下必须转义。 “合法”在这种情况下意味着它们的最终解码值是合法的,而不是它们在流中是合法的。如上所述,某些合法值必须在流中转义。 我有一个问题,其中 0x1c 是一个非法字符......在 java 中寻找一种可能性如何避免这些...... 一个很好的概述哪些字符是有效的,哪些不是可以在这里找到validchar.com/d/xml10/xml10_namestart @xamde 这个列表很好,但它只显示了可用于启动 XML 元素的字符。手头的问题是通常在 XML 文件中哪些字符是有效的。某些字符在任何地方都不允许使用。【参考方案3】:

唯一的非法字符是&amp;amp;&lt;&gt;(以及属性中的"',具体取决于用于分隔属性值的字符:attr="must use &amp;quot; here, ' is allowed"和@ 987654328@).

它们使用XML entities 进行转义,在这种情况下,您需要&amp;amp; 来代替&amp;amp;

不过,实际上,您应该使用为您编写 XML 并为您抽象出这类东西的工具或库,这样您就不必担心了。

【讨论】:

某些控制字符也是不允许的。请参阅下面的答案。 其实这并不完全正确。一些较低的 ascii 字符也是无效的。如果您尝试将 0x03 写入 Xml 文档,您通常会收到错误,并且如果您设法将其正确转义到 XML 文档中,大多数查看者会抱怨无效字符。边缘情况,但确实会发生。 这个答案是绝对错误的。这是我的 XML 异常,带有 0x12 非法字符 'System.Xml.XmlException:'',十六进制值 0x12,是无效字符' 另一个方向也是错的;除了遗漏每一个非法字符外,它声称非法的字符也是完全合法的,尽管在上下文中具有特殊含义。 在 XML 1.0 中有很多非法字符。事实上,即使对大多数控制字符使用字符实体,在解析时也会导致错误。【参考方案4】:

这是一个 C# 代码,用于从字符串中删除 XML 无效字符并返回一个新的有效字符串。

public static string CleanInvalidXmlChars(string text) 
 
    // From xml spec valid chars: 
    // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]     
    // any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. 
    string re = @"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]"; 
    return Regex.Replace(text, re, ""); 

【讨论】:

对于 Java,正则表达式模式是相同的。然后您可以在 String 类中使用名为 replaceAll 的方法,该方法需要正则表达式模式作为参数。检查这个:docs.oracle.com/javase/6/docs/api/java/lang/… 我的字符串中有这样的无效字符:SUSITARIMO DL DARBO SUARTIES 此代码不会删除 所以xml文档初始化失败。 我相信您不能只将此模式放入 .NET 正则表达式构造函数中。我认为它不会将 \u10000\u10FFFF 识别为单个字符,因为它们每个都需要两个 utf-16 char 实例,并且根据 docs 可能不会超过 4 位数。 [\u10000-\u10FFFF] 很可能被解析为 [\u1000, 0-\u10FF, F, F] 看起来很奇怪但合法。 一个更好的处理 utf-16 字符的实现可以在这里找到:***.com/a/17735649/1639057 小心使用此方法,你的有效UTF字符也会被空字符串替换,导致应用程序出现意外结果【参考方案5】:

预先声明的字符是:

& < > " '

有关详细信息,请参阅“What are the special characters in XML?”。

【讨论】:

错了。这些都不是无效的。只有 & 和 【参考方案6】:

除了 potame 的回答,如果你确实想使用 CDATA 块进行转义。

如果您将文本放在 CDATA 块中,则无需使用转义。 在这种情况下,您可以使用以下范围内的所有字符

注意:除此之外,您不能使用]]&gt; 字符序列。因为它会匹配 CDATA 块的结尾。

如果仍有无效字符(例如控制字符),那么最好使用某种编码(例如 base64)。

【讨论】:

无论是否在 CDATA 块中,XML 中都禁止使用某些字符。 没错,这不是我写的吗?引用:“以下范围内的所有字符”。我的意思是,只有这个特定范围内的字符。不允许使用其他字符。 - 完全同意 ;但我不明白反对票。 - 虽然没有难过的感觉。【参考方案7】:

在 C# 中删除不正确 XML 字符的另一种方法是使用 XmlConvert.IsXmlChar(自 .NET Framework 4.0 起可用)

public static string RemoveInvalidXmlChars(string content)

   return new string(content.Where(ch => System.Xml.XmlConvert.IsXmlChar(ch)).ToArray());

或者您可以检查所有字符是否都是 XML 有效的:

public static bool CheckValidXmlChars(string content)

   return content.All(ch => System.Xml.XmlConvert.IsXmlChar(ch));

.Net Fiddle

例如,垂直制表符(\v)对 XML 无效,它是有效的 UTF-8,但不是有效的 XML 1.0,甚至许多库(包括 libxml2)都错过了它并默默地输出无效的 XML。

【讨论】:

【参考方案8】:

在 C# 中转义可能不需要的 XML / Xhtml 字符的另一种简单方法是:

WebUtility.HtmlEncode(stringWithStrangeChars)

【讨论】:

无效字符 他写的是 Xml 而不是 Html。【参考方案9】:

对于 Java 人员,Apache 有一个实用程序类 (StringEscapeUtils),它有一个辅助方法 escapeXml,可用于使用 XML 实体转义字符串中的字符。

【讨论】:

【参考方案10】:

总之,文本中的有效字符是:

制表符、换行和回车。 所有非控制字符都有效除了&amp;&lt;。 如果关注]]&gt; 无效。

XML 规范的第 2.2 和 2.4 节提供了详细的答案:

字符

合法字符包括制表符、回车、换行以及 Unicode 和 ISO/IEC 10646 的合法字符

字符数据

& 符号 (&) 和左尖括号 () 可以使用 字符串“>”,并且为了兼容性,必须使用以下任一方法进行转义 " > " 或出现在字符串 " ]]> 中的字符引用 " 在内容中,当该字符串未标记 CDATA 的结尾时 部分。

【讨论】:

【参考方案11】:

“XmlWriter and lower ASCII characters”为我工作

string code = Regex.Replace(item.Code, @"[\u0000-\u0008,\u000B,\u000C,\u000E-\u001F]", "");

【讨论】:

【参考方案12】:
ampersand (&) is escaped to &amp;

double quotes (") are escaped to &quot;

single quotes (') are escaped to &apos; 

less than (<) is escaped to &lt; 

greater than (>) is escaped to &gt;

在 C# 中,使用 System.Security.SecurityElement.EscapeSystem.Net.WebUtility.HtmlEncode 转义这些非法字符。

string xml = "<node>it's my \"node\" & i like it 0x12 x09 x0A  0x09 0x0A <node>";
string encodedXml1 = System.Security.SecurityElement.Escape(xml);
string encodedXml2= System.Net.WebUtility.HtmlEncode(xml);


encodedXml1
"&lt;node&gt;it&apos;s my &quot;node&quot; &amp; i like it 0x12 x09 x0A  0x09 0x0A &lt;node&gt;"

encodedXml2
"&lt;node&gt;it&#39;s my &quot;node&quot; &amp; i like it 0x12 x09 x0A  0x09 0x0A &lt;node&gt;"

【讨论】:

【参考方案13】:

在 Woodstox XML 处理器中,无效字符按以下代码分类:

if (c == 0) 
    throw new IOException("Invalid null character in text to output");

if (c < ' ' || (c >= 0x7F && c <= 0x9F)) 
    String msg = "Invalid white space character (0x" + Integer.toHexString(c) + ") in text to output";
    if (mXml11) 
        msg += " (can only be output using character entity)";
    
    throw new IOException(msg);

if (c > 0x10FFFF) 
    throw new IOException("Illegal unicode character point (0x" + Integer.toHexString(c) + ") to output; max is 0x10FFFF as per RFC");

/*
 * Surrogate pair in non-quotable (not text or attribute value) content, and non-unicode encoding (ISO-8859-x,
 * Ascii)?
 */
if (c >= SURR1_FIRST && c <= SURR2_LAST) 
    throw new IOException("Illegal surrogate pair -- can only be output via character entities, which are not allowed in this content");

throw new IOException("Invalid XML character (0x"+Integer.toHexString(c)+") in text to output");

来源here

【讨论】:

【参考方案14】:

有人试过这个System.Security.SecurityElement.Escape(yourstring)吗? 这将用有效的等效字符替换字符串中的无效 XML 字符。

【讨论】:

【参考方案15】:

对于 XSL(在非常懒惰的日子)我使用:

capture="&amp;(?!amp;)" capturereplace="&amp;amp;"

翻译所有未遵循的 & 符号 på amp;正确的。

我们有输入在 CDATA 中但使用 XML 的系统没有考虑到它的情况。这是一个草率的修复,当心...

【讨论】:

如果马虎,真的有必要发到这里吗?

以上是关于什么是 XML 中的无效字符的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PHP 跳过 XML 文件中的无效字符

解析Xml数据错误:文本内容中发现无效字符怎么处理

XML 中的无效字符使 Datastage 作业失败

无效的 XML 字符错误 - 如何从 VARCHAR2 数据库列中查找无效字符?

XML 转换中的无效字符

Flex TextArea - 从 Word 复制/粘贴 - xml 解析中的 unicode 字符无效