什么是 XML 中的无效字符
Posted
技术标签:
【中文标题】什么是 XML 中的无效字符【英文标题】:What are invalid characters in XML 【发布时间】:2010-10-18 07:48:06 【问题描述】:我正在使用一些包含以下字符串的 XML:
<node>This is a string</node>
我传递给节点的一些字符串将包含&
、#
、$
等字符:
<node>This is a string & so is this</node>
由于&
,这无效。
我无法将这些字符串包装在 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 范围的字符是不允许的。
这也意味着禁止调用例如字符实体&#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)、xFFFE、xFFFF...
但是,不鼓励使用控制字符和未定义的 Unicode 字符。
还可以注意到,并非所有解析器都将这一点考虑在内,带有控制字符的 XML 文档可能会被拒绝。
2。需要转义的字符(以获得格式良好的文档):
<
必须使用 &#60;
实体进行转义,因为它被假定为标签的开头。
&
必须使用 &#38;
实体进行转义,因为它被假定为实体引用的开始
>
应使用 &#62;
实体进行转义。这不是强制性的——它取决于上下文——但强烈建议不要使用它。
'
应使用 &#39;
实体进行转义——在单引号内定义的属性中是必需的,但强烈建议始终对其进行转义。
"
应使用 &#34;
实体进行转义——在双引号内定义的属性中是必需的,但强烈建议始终对其进行转义。
【讨论】:
" 但强烈建议始终避开它" - 你能澄清一下吗?谁建议这样做,为什么? (在我看来,在语法允许的任何地方使用文字引号都没有错。)【参考方案2】:有效字符列表在XML specification:
Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
【讨论】:
您应该注意,尽管它们是合法字符,但& < > " '
在某些情况下必须转义。
“合法”在这种情况下意味着它们的最终解码值是合法的,而不是它们在流中是合法的。如上所述,某些合法值必须在流中转义。
我有一个问题,其中 0x1c 是一个非法字符......在 java 中寻找一种可能性如何避免这些......
一个很好的概述哪些字符是有效的,哪些不是可以在这里找到validchar.com/d/xml10/xml10_namestart
@xamde 这个列表很好,但它只显示了可用于启动 XML 元素的字符。手头的问题是通常在 XML 文件中哪些字符是有效的。某些字符在任何地方都不允许使用。【参考方案3】:
唯一的非法字符是&amp;
、<
和>
(以及属性中的"
或'
,具体取决于用于分隔属性值的字符:attr="must use &quot; here, ' is allowed"
和@ 987654328@).
它们使用XML entities 进行转义,在这种情况下,您需要&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 块中,则无需使用转义。 在这种情况下,您可以使用以下范围内的所有字符:
注意:除此之外,您不能使用]]>
字符序列。因为它会匹配 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】:总之,文本中的有效字符是:
制表符、换行和回车。 所有非控制字符都有效除了&
和<
。
如果关注]]
,>
无效。
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 &
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>"
【讨论】:
【参考方案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;)" capturereplace="&amp;"
翻译所有未遵循的 & 符号 på amp;正确的。
我们有输入在 CDATA 中但使用 XML 的系统没有考虑到它的情况。这是一个草率的修复,当心...
【讨论】:
如果马虎,真的有必要发到这里吗?以上是关于什么是 XML 中的无效字符的主要内容,如果未能解决你的问题,请参考以下文章