我正在处理一些XML,其中包含以下字符串:
<node>This is a string</node>
有的,我传递给各节点的字符串将有字符,如&
,#
,$
,等:
<node>This is a string & so is this</node>
由于,此无效&
。
我无法将这些字符串包装在CDATA中,因为它们必须保持原样。我试图寻找一个字符列表,这些字符如果不包含在CDATA中就不能放入XML节点中。
有人可以指出我的方向或向我提供一系列非法字符吗?
我正在处理一些XML,其中包含以下字符串:
<node>This is a string</node>
有的,我传递给各节点的字符串将有字符,如&
,#
,$
,等:
<node>This is a string & so is this</node>
由于,此无效&
。
我无法将这些字符串包装在CDATA中,因为它们必须保持原样。我试图寻找一个字符列表,这些字符如果不包含在CDATA中就不能放入XML节点中。
有人可以指出我的方向或向我提供一系列非法字符吗?
Answers:
好,让我们分开以下字符的问题:
@dolmen在“ 什么是XML无效字符 ”中提供的答案仍然有效,但需要使用XML 1.1规范进行更新。
此处描述的字符是允许在XML文档中插入的所有字符。
允许的字符的全局列表是:
[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
基本上,控制字符和超出Unicode范围的字符都是不允许的。这也意味着
禁止调用字符实体。
允许的字符的全局列表是:
[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),xFFFE,xFFFF ...
但是,不建议使用控制字符和未定义的Unicode字符。
还应注意,并非所有解析器都将其考虑在内,带有控制字符的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, "");
}
\u10000
并\u10FFFF
作为单个字符,因为它们需要两个UTF-16 char
每个实例,并根据文档,可能没有更多的是4个位数。[\u10000-\u10FFFF]
最有可能解析为[ \u1000
,0-\u10FF
,F
,F
]这是怪异的,但合法的。
逃脱C#中潜在有害XML / XHTML字符的另一种简便方法是:
WebUtility.HtmlEncode(stringWithStrangeChars)
删除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。
总之,文本中的有效字符为:
&
和外,所有非控制字符均有效<
。>
如果遵循,则无效]]
。XML规范的2.2和2.4节提供了详细的答案:
性格
合法字符为制表符,回车符,换行符以及Unicode和ISO / IEC 10646的合法字符
角色数据
除用于标记分隔符时,或在注释,处理指令或CDATA节中,“&”字符(&)和左尖括号(<)均不得以其文字形式出现。如果在其他地方需要它们,则必须使用数字字符引用或分别使用字符串“&”和“ <”对其进行转义。右尖括号(>)可以使用字符串“>”表示,并且为了兼容起见,当内容中出现在字符串“]]>”中时,必须使用“>”或字符引用对其进行转义,字符串未标记CDATA节的结尾。
“ XmlWriter和较低的ASCII字符 ”对我有用
string code = Regex.Replace(item.Code, @"[\u0000-\u0008,\u000B,\u000C,\u000E-\u001F]", "");
ampersand (&) is escaped to &
double quotes (") are escaped to "
single quotes (') are escaped to '
less than (<) is escaped to <
greater than (>) is escaped to >
在C#中,使用System.Security.SecurityElement.Escape
或System.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
"<node>it's my "node" & i like it 0x12 x09 x0A 0x09 0x0A <node>"
encodedXml2
"<node>it's my "node" & i like it 0x12 x09 x0A 0x09 0x0A <node>"
在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");
从这里来