什么是XML中的无效字符


229

我正在处理一些XML,其中包含以下字符串:

<node>This is a string</node>

有的,我传递给各节点的字符串将有字符,如&#$,等:

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

由于,此无效&

我无法将这些字符串包装在CDATA中,因为它们必须保持原样。我试图寻找一个字符列表,这些字符如果不包含在CDATA中就不能放入XML节点中。

有人可以指出我的方向或向我提供一系列非法字符吗?


4
任何不使用CDATA的正当理由?
PeterPerháč09年

1
是的,我正在将字符串传递给名为Fatwire的CMS,并且带有数据的节点不能位于CDATA中,我不确定为什么它是Fatwire的工作方式:(
RailsS​​on

@Peter:如何使用CDATA?stackoverflow.com/questions/6906705/...
拉德克

Answers:


147

唯一的非法字符&<并且>(和"'在属性)。

他们使用逃脱XML实体,在你想这种情况下&amp;&

但是,实际上,您应该使用为您编写XML并为您抽象化此类内容的工具或库,这样您就不必担心它了。


82
也不允许某些控件字符。请参阅下面的答案。
dolmen

43
其实那不是真的。许多较低的ASCII字符也是无效的。如果您尝试将0x03写入Xml文档,则通常会出现错误,并且如果确实设法将其正确转义为XML文档,则大多数查看器都会抱怨该无效字符。边缘情况,但确实发生了。
里克·斯特拉

16
这个答案是绝对错误的。这是我的XML异常,带有0x12非法字符'System.Xml.XmlException:”,十六进制值0x12,是无效字符”
George

8
在另一个方向上也是错误的。除了遗漏每个非法字符外,它声称的非法字符完全是合法的,尽管在上下文中具有特殊含义。
乔恩·汉娜

6
在XML 1.0中,有许多非法字符。实际上,即使对大多数控制字符使用字符实体,在解析时也会导致错误。
Thayne 2015年

218

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

  1. 在任何XML文档中都完全无效。
  2. 需要逃脱。

@dolmen在“ 什么是XML无效字符 ”中提供的答案仍然有效,但需要使用XML 1.1规范进行更新。

1.无效字符

此处描述的字符是允许在XML文档中插入的所有字符。

1.1。在XML 1.0中

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

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

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

1.2。在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;实体,因为它被认为是开始时的实体引用

>应进行转义&gt;实体。它不是强制性的-它取决于上下文-但强烈建议您对其进行转义。

'应该用转义&apos;实体-在单引号内定义的属性强制性的,但它强烈建议总是逃避它。

"应该用转义&quot;实体-在双引号内定义的属性强制性的,但它强烈建议总是逃避它。


171

有效字符列表在XML规范中

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

7
您应注意,尽管它们是合法字符,& < > " '但在某些情况下必须转义。
D.Shawley,

7
在这种情况下,“合法”表示它们的最终解码值是合法的,而不是在流中它们是合法的。如上所述,某些法律价值必须在流内转义。
SilverbackNet

我有一个问题,为0x1c是非法字符...寻找Java中的可能性如何避免这些....
basZero

一个很好的概述,哪些字符有效,哪些字符无效,请在此处找到有效的字符validchar.com/d/xml10/xml10_namestart
博士,2014年

8
@xamde该列表很好,但是它仅显示可用于启动XML元素的字符。当前的问题是,哪些字符通常在XML文件中有效。有些字符不允许在任何地方使用。
乔恩·森奇纳

59

这是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, ""); 
}

6
对于Java,正则表达式模式将相同。然后,您可以在类String中使用名为replaceAll的方法,该方法需要使用正则表达式模式作为参数。检查:docs.oracle.com/javase/6/docs/api/java/lang/...
mathifonseca

2
我的字符串中包含这样的无效字符:SUSITARIMO D&#x5; L DARBO SUTARTIES此代码不会删除&#x5; 因此xml文档无法初始化。
Dainius Kreivys

我相信您不能只是将此模式放入.NET正则表达式构造函数中。我不认为它承认\u10000\u10FFFF作为单个字符,因为它们需要两个UTF-16 char每个实例,并根据文档,可能没有更多的是4个位数。[\u10000-\u10FFFF]最有可能解析为[ \u10000-\u10FFFF]这是怪异的,但合法的。
GSerg '18年


7

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

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

可能字符的图形表示

注意:最重要的是,您不允许使用]]>字符序列。因为它将与CDATA块的末尾匹配。

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


3
不管是否在CDATA块中,XML中都禁止某些字符。
支石墓

4
确切地说,这不是我写的吗?引用:“ 以下范围内的所有字符”。我的意思是,仅此特定范围内的字符。不允许使用其他字符。- 完全同意 ; 但我不理解反对意见。-虽然没有难过的感觉。
bvdb


6

删除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小提琴

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


2

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

  • 标签,换行和回车。
  • &,所有非控制字符均有效<
  • >如果遵循,则无效]]

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

性格

合法字符为制表符,回车符,换行符以及Unicode和ISO / IEC 10646的合法字符

角色数据

除用于标记分隔符时,或在注释,处理指令或CDATA节中,“&”字符(&)和左尖括号(<)均不得以其文字形式出现。如果在其他地方需要它们,则必须使用数字字符引用或分别使用字符串“&”和“ <”对其进行转义。右尖括号(>)可以使用字符串“>”表示,并且为了兼容起见,当内容中出现在字符串“]]>”中时,必须使用“>”或字符引用对其进行转义,字符串未标记CDATA节的结尾。



1
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;"

1

对于Java专家来说,Apache有一个实用程序类(StringEscapeUtils),该类具有一个辅助方法escapeXml,该方法可用于使用XML实体对字符串中的字符进行转义。


1

在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");

这里来


-1

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


-5

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

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

翻译所有未遵循的&标记;适当的。

在某些情况下,输入是在CDATA中,但是使用XML的系统没有考虑到它。这是草率的修补程序,请注意...


8
如果草率的话,真的需要在这里发布吗?
2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.