XML中的无效字符

目前我正在使用一些XML。

我有像下面这样的string的节点:

<node>This is a string</node> 

我传递给节点的一些string将包含&,#,$等字符

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

这是无效的,

我不能在CDATA中包装这些string,因为它们需要保持原样。 我已经尝试在线查找不能放入XML节点而不在CDATA中的字符列表。

任何人都可以向我指出一个方向,还是给我提供一个非法字符列表?

唯一的非法字符是&<> (以及属性中的"' )。

他们使用XML实体转义,在这种情况下,您需要&amp;&

实际上,您应该使用为您编写XML的工具或库,并为您抽象这种东西,所以您不必担心它。

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

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

好的,让我们分离(1)在任何XML文档中都是无效的字符的问题,以及(2)需要转义的字符:

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

1.无效的字符

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

1.1。 在XML 1.0中

  • 参考:请参阅XMLbuild议1.0,§2.2字符

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

[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中

  • 参考:请参阅XMLbuild议1.1,§2.2字符和1.3 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]

XMLbuild议的这个修订版本扩展了允许的字符,以便允许控制字符,并考虑到Unicode标准的新修订,但是这些仍然是不允许的: NUL(x00)xFFFExFFFF

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

还可以注意到,所有parsing器并不总是将这个考虑在内,并且具有控制字符的XML文档可能被拒绝。

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

<必须用&lt; 实体,因为它被认为是标签的开始。

&必须用&amp; 实体,因为它被假定为实体引用的开始

>应该用&gt;来转义&gt; 实体。 这不是强制性的 – 这取决于上下文 – 但强烈build议逃避它。

'应该用&apos; 实体 – 在单引号中定义的属性中是强制性的,但强烈build议总是将其转义。

"应该用&quot;实体&quot;逃避 – 对于在双引号内定义的属性是强制性的,但强烈build议总是将其转义。

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

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

预先定义的字符是:

 & < > " ' 

http://xml.silmaril.ie/specials.html

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

 WebUtility.HtmlEncode(stringWithStrangeChars) 

除了potame的回答之外,如果你确实想用CDATA块来逃避。

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

可能的字符的图形表示

注意:最重要的是,你不能使用]]>字符序列。 因为它会匹配CDATA块的末尾。

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

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

来自这里

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

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

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

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

翻译所有不符合要求的符号。 适当的。

我们有一些情况,input在CDATA中,但使用XML的系统没有考虑到它。 这是一个马虎修复,谨防…