【问题标题】:What is the set of valid first characters in an XML document?XML 文档中的有效首字符集是什么?
【发布时间】:2009-08-21 22:37:48
【问题描述】:

我正在编写一些代码来确定 Web 服务器返回的 XML 文档的字符编码(在这种特殊情况下为 RSS 提要)。不幸的是,有时 Web 服务器会撒谎并告诉我文档是 UTF-8,而实际上它不是,或者服务器上的样板 XML 生成代码在开头有 <?xml encoding='UTF-8'?> 但文档包含无效的 UTF-8 字节序列。

由于我无法控制服务器,我需要让我的客户端代码容忍这种不一致并显示一些东西,即使某些字符没有正确解码. 这是我的应用程序的一项重要要求。

我很清楚在这种情况下服务器违反了 XML 规范。我会尽可能与服务器端开发人员合作,以根据规范使事情正确,但有时这对他们或他们的组织来说是一个低优先级,或者服务器端代码没有被任何人积极维护。

为了稳健,我想查看 XML 数据的前几个字节,并尝试确定它是某种形式的 UTF-16 还是某种 8 位编码。我已经有了查找字节顺序标记 (BOM) 的代码。

但有时服务器不包含 BOM,即使是 UTF-16 也是如此。我想通过查看前两个字节并根据 XML 文档中可能的第一个字符列表检查它们来尝试确定它是否是 UTF-16。

显然我必须在某处画线。如果文档不是格式良好的 XML,我无论如何都无法解析它,除非我编写自己的非常宽容的解析器(我不打算这样做)。但鉴于它的格式正确,除了 BOM,我还能在文档的第一个字符中看到什么?

就我从规范中可以看出,这组将是:空格(空格、制表符、换行符、回车)和“<?xml?> 声明可能不存在,即使规范要求。

内部 DTD、处理指令、标签和 cmets 都以“

编辑:重写以强调我的特殊要求。

【问题讨论】:

  • 我的建议是,如果服务器返回垃圾,告诉用户服务器返回垃圾。也许用户会变得足够愤怒,以至于他们会踢出确实控制服务的人来修复它。我们启用的松弛度越多,我们收到的松弛度就越多。
  • 不幸的是,这不是一个实用的选择,因为大多数非技术用户不会区分我的应用程序和我正在显示的信息的来源。他们所看到的只是它不起作用。您不妨尝试通过一项法律,即所有 PHP 程序员在被允许编写任何 PHP 代码之前必须证明其具备字符编码的工作知识 :-)
  • @Don:您已经描述了程序中的错误 - 您的错误消息不清楚。该消息应显示类似“从服务器 servername 收到垃圾。请联系您的网络管理员并要求他停止发送垃圾”。它停在哪里?如果你向后弯得太远,你会摔断背部。
  • @Don:顺便说一句,我认为你应该向 PHP 开发人员道歉,因为他们暗示他们太愚蠢了,无法编写生成有效字符编码的 PHP 程序。
  • @John S:对不起,挖 PHP 程序员的目的是为了讽刺和幽默(因此最后是笑脸)。我之所以选择 PHP,是因为它是最流行的 Web 编程语言,并且拥有庞大的新手社区。​​span>

标签: xml parsing character-encoding


【解决方案1】:

XML 规范提供了关于检测字符编码的some guidance。问题是几乎不可能查看前几个字节并判断它是 UTF-8、ISO-8859-1 还是 CP437。规范包含的信息至少可以让您区分格式正确的文档。

【讨论】:

  • 我以前从未注意到规范中的那部分——绝对有用!
  • 我确实倾向于同意 John 关于 garbage-in/garbage-out 的概念。我已经看到很多基于 HTTP 的 XML 破坏了关于编码的所有规则,这让我无休无止。看看这个 (annevankesteren.nl/2005/03/text-xml) 关于这个主题的博客文章,然后注意到它来自 3 多年前。然而问题仍然存在。对不起,咆哮。
  • 原则上我完全同意,但是当一位体育作家无辜地从 Word 复制并粘贴到他公司的自制 CMS 中时,根本不处理字符编码并且您发现 Word 的弯引号字符的默认编码形成了无效的 UTF-8 字节序列,并且您的用户发现他们的应用不再向他们显示最新的体育比分(或任何其他内容),您开始想要更宽容其他程序员的缺点。
  • 呵呵呵呵...我完全忘记了那些“花哨”的报价。听起来您实际上正在查看 Windows 1252。您可能需要考虑嗅探其中一个 HTTP 标头,或者您可能很幸运拥有一个 &lt;generator&gt; 元素。尝试对识别出错误内容生成器的内容发出非标准处理信号。
【解决方案2】:

问题在于,如果提要无效,它可能不遵守任何有关合法字符的规则。查看Universal Feed Parser 的代码。它是经过良好测试的代码,可将垃圾文本解析为可能正确的数据结构。

UFP 使用名为Universal Encoding Detector 的子库,其中应包含对一般编码检测有用的信息。

【讨论】:

    【解决方案3】:

    这并不理想,但是当我需要处理错误的编码(伪代码警报)时,我有时会这样做。

    str = decode("utf-8", input)
    if (!str) {
      str = decode("cp1252", input)
    }
    

    也就是说,尝试将输入解释为 UTF-8,如果失败,则将其视为来自 Windows 系统(可能是)。对我来说,这似乎是一个合理的妥协。

    当然,这确实需要您先将整个输入下载到内存中,这可能不切实际。

    【讨论】:

      猜你喜欢
      • 2010-10-18
      • 2019-02-05
      • 1970-01-01
      • 2012-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-21
      相关资源
      最近更新 更多