在XML中什么是无效字符

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

<node>This is a string</node>

我传递给节点的一些字符串将具有&#$等字符:

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

由于&,这是无效的。

我不能在CDATA中包装这些字符串,因为它们需要这样。我尝试寻找一个字符列表,这些字符不能放在XML节点中,而不能放在CDATA中。

有人能给我指个方向或者给我一份非法字符的列表吗?

769638 次浏览

预先声明的字符是:

& < > " '

更多信息见“XML中的特殊字符是什么?”。

唯一的非法字符是&<>(以及属性中的"',这取决于使用哪个字符来分隔属性值:attr="must use &quot; here, ' is allowed"attr='must use &apos; here, " is allowed')。

它们使用XML实体进行转义,在这种情况下,你需要&amp;来表示&

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

有效字符列表在XML规范中:

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

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

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

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

翻译所有没有遵循的&-符号på amp;敬合适的人。

在某些情况下,输入是CDATA,但是使用XML的系统没有考虑到它。这是一个草率的修复,小心…

另一个简单的方法是在c#中转义可能不需要的XML / XHTML字符:

WebUtility.HtmlEncode(stringWithStrangeChars)

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

在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. 在任何XML文档中都无效。
  2. 需要逃脱。

@dolmen在"https://stackoverflow.com/questions/730133/invalid-characters-in-xml/5110103#5110103"仍然有效,但需要使用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标准的新修订,但仍然不允许使用这些字符:空(x00)xFFFExFFFF

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

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

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

<必须用&#60;实体进行转义,因为它被假定为标记的开始。

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

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

'应该用&#39;实体进行转义——在单引号内定义的属性中是强制性的,但强烈建议总是转义它。

"应该用&#34;实体进行转义——在双引号内定义的属性中是强制性的,但强烈建议总是转义它。

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

除了potame的答案,如果你想转义使用CDATA块。

如果你把你的文本在CDATA块中,你不需要使用转义。 在这种情况下,你可以使用以下范围内的所有字符:

可能字符的图形表示

注意:在此之上,你不允许使用]]>字符序列。因为它将匹配CDATA块的末尾。

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

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

。净小提琴< / >

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

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

XmlWriter和低ASCII字符”对我有用

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

综上所述,文本中的有效字符为:

  • 制表符,换行和换行。
  • 所有非控制字符都是有效的除了 &<
  • 如果跟随]],则>无效。

XML规范的2.2节和2.4节详细给出了答案:

字符

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

字符数据

不能出现&号(&)和左尖括号(<) 以文字形式出现,除非用作标记分隔符, 或在注释、处理指令或CDATA节中。如果 如果在其他地方需要它们,则必须使用任一数字进行转义 字符引用或字符串“&和“<” 分别。右尖括号(>)可以使用 字符串”>,为了兼容性,必须使用其中之一进行转义 “比;"或出现在字符串中的字符引用"]]> ,当该字符串没有标记CDATA的结束时 部分。< / p >