XML中的无效字符
目前我正在使用一些XML。
我有像下面这样的string的节点:
<node>This is a string</node>
我传递给节点的一些string将包含&,#,$等字符
<node>This is a string & so is this</node>
这是无效的,
我不能在CDATA中包装这些string,因为它们需要保持原样。 我已经尝试在线查找不能放入XML节点而不在CDATA中的字符列表。
任何人都可以向我指出一个方向,还是给我提供一个非法字符列表?
唯一的非法字符是&
, <
和>
(以及属性中的"
或'
)。
他们使用XML实体转义,在这种情况下,您需要&
为&
。
实际上,您应该使用为您编写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范围之外的控制字符和字符是不允许的。 这也意味着调用例如字符实体
是禁止的。
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) , xFFFE , xFFFF …
但是,不鼓励使用控制字符和未定义的Unicode字符。
还可以注意到,所有parsing器并不总是将这个考虑在内,并且具有控制字符的XML文档可能被拒绝。
2.需要转义的字符(以获得一个格式良好的文档):
<
必须用<
实体,因为它被认为是标签的开始。
&
必须用&
实体,因为它被假定为实体引用的开始
>
应该用>
来转义>
实体。 这不是强制性的 – 这取决于上下文 – 但强烈build议逃避它。
'
应该用'
实体 – 在单引号中定义的属性中是强制性的,但强烈build议总是将其转义。
"
应该用"
实体"
逃避 – 对于在双引号内定义的属性是强制性的,但强烈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, ""); }
用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 & 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>"
对于XSL(在真正的懒惰的日子),我使用:
capture="&(?!amp;)" capturereplace="&amp;"
翻译所有不符合要求的符号。 适当的。
我们有一些情况,input在CDATA中,但使用XML的系统没有考虑到它。 这是一个马虎修复,谨防…