【问题标题】:What are invalid characters in XML什么是 XML 中的无效字符
【发布时间】:2010-10-18 07:48:06
【问题描述】:

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

<node>This is a string</node>

我传递给节点的一些字符串将包含&amp;#$ 等字符:

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

由于&amp;,这无效。

我无法将这些字符串包装在 CDATA 中,因为它们需要保持原样。我尝试寻找一个字符列表,这些字符在没有 CDATA 的情况下无法放入 XML 节点。

有人可以指点我的方向或向我提供非法字符列表吗?

【问题讨论】:

  • 不使用 CDATA 的任何正当理由?
  • 是的,我正在将字符串传递给一个名为 Fatwire 的 CMS,而带有数据的节点不能在 CDATA 中,我不确定为什么 Fatwire 是这样工作的 :(
  • @Peter:在我的情况下如何使用 CDATA? stackoverflow.com/questions/6906705/…

标签: xml


【解决方案1】:

好的,让我们将字符的问题分开:

  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 范围的字符是不允许的。 这也意味着禁止调用例如字符实体&amp;#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 标准的新版本,但仍然不允许使用这些字符:NUL (x00)xFFFExFFFF...

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

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

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

&lt; 必须使用 &amp;#60; 实体进行转义,因为它被假定为标签的开头。

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

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

' 应使用 &amp;#39; 实体进行转义——在单引号内定义的属性中是必需的,但强烈建议始终对其进行转义。

" 应使用 &amp;#34; 实体进行转义——在双引号内定义的属性中是必需的,但强烈建议始终对其进行转义。

【讨论】:

  • " 但强烈建议始终避开它" - 你能澄清一下吗?谁建议这样做,为什么? (在我看来,在语法允许的任何地方使用文字引号都没有错。)
【解决方案2】:

有效字符列表在XML specification:

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

【讨论】:

  • 您应该注意,尽管它们是合法字符,但 &amp; &lt; &gt; " ' 在某些情况下必须转义。
  • “合法”在这种情况下意味着它们的最终解码值是合法的,而不是它们在流中是合法的。如上所述,某些合法值必须在流中转义。
  • 我有一个问题,其中 0x1c 是一个非法字符......在 java 中寻找一种可能性如何避免这些......
  • 一个很好的概述哪些字符是有效的,哪些不是可以在这里找到validchar.com/d/xml10/xml10_namestart
  • @xamde 这个列表很好,但它只显示了可用于启动 XML 元素的字符。手头的问题是通常在 XML 文件中哪些字符是有效的。某些字符在任何地方都不允许使用。
【解决方案3】:

唯一的非法字符是&amp;amp;&lt;&gt;(以及属性中的"',具体取决于用于分隔属性值的字符:attr="must use &amp;quot; here, ' is allowed"和@ 987654328@).

它们使用XML entities 进行转义,在这种情况下,您需要&amp;amp; 来代替&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 字符的实现可以在这里找到:stackoverflow.com/a/17735649/1639057
  • 小心使用此方法,你的有效UTF字符也会被空字符串替换,导致应用程序出现意外结果
【解决方案5】:

预先声明的字符是:

& < > " '

有关详细信息,请参阅“What are the special characters in XML?”。

【讨论】:

  • 错了。这些都不是无效的。只有 & 和
【解决方案6】:

除了 potame 的回答,如果你确实想使用 CDATA 块进行转义。

如果您将文本放在 CDATA 块中,则无需使用转义。 在这种情况下,您可以使用以下范围内的所有字符

注意:除此之外,您不能使用]]&gt; 字符序列。因为它会匹配 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】:

      总之,文本中的有效字符是:

      • 制表符、换行和回车。
      • 所有非控制字符都有效除了&amp;&lt;
      • 如果关注]]&gt; 无效。

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

          【讨论】:

            【解决方案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;(?!amp;)" capturereplace="&amp;amp;"
                

                翻译所有未遵循的 & 符号 på amp;正确的。

                我们有输入在 CDATA 中但使用 XML 的系统没有考虑到它的情况。这是一个草率的修复,当心...

                【讨论】:

                • 如果马虎,真的有必要发到这里吗?
                猜你喜欢
                • 2019-02-05
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-07-29
                • 1970-01-01
                相关资源
                最近更新 更多