【问题标题】:Encoding recognition using heuristic methods over xml/html?在 xml/html 上使用启发式方法编码识别?
【发布时间】:2014-02-17 02:51:02
【问题描述】:

假设我有一个存储在远程计算机上的 XML 文件。我不知道这个文件是如何保存的。 (使用了什么编码)。

我想读取这个文件并对那个 XML 文件做一些操作。

但后来我想:好的,如何如果我不知道分析硬盘驱动器上的字节,我将能够从 <?xml version="1.0" encoding="xxxxx"?> 读取 encoding 部分。 .

discussion with Jon 之后,我被告知可以在 UTF-8 和 UTF-16 之间自动推断编码,而这些是 XML 规范规定的唯一可以省略的编码。

这让我问:其他编码呢?如果该 XML 保存在 encoding-lala 中,我怎么知道它?

正如 Jon 提到我的 w3c 文章 - 我确实找到了 answer

XML 编码声明用作每个内部标签 实体,指示正在使用的字符编码。 之前 XML 处理器可以读取内部标签,但是,它显然 必须 知道正在使用什么字符编码——这就是内部的 标签试图表明

它通过:

因为每个 XML 实体都没有附带外部编码 信息而不是 UTF-8 或 UTF-16 编码必须以 XML 开头 编码声明,其中第一个字符必须是<?xml, 任何符合要求的处理器都可以检测到,经过两到四个八位字节 输入,以下哪种情况适用。在阅读这份清单时, 可能有助于知道在 UCS-4 中,<#x0000003C?#x0000003F,UTF-16 数据流所需的字节顺序标记是 #xFEFF

所以它确实使用启发式方法通过尝试获取适当的<?xml 字符串来获取编码。

另一个有用的信息是encoding 声明的结构

注意正则表达式,(基本 ascii 0..127)字符和 encoding 字。

所以这是我的问题:

即使它保存为 utf-8/16/blabla - 它成功使用第一个字节识别编码(启发式与否)。

如果是这样,为什么还需要<?xml version="1.0" encoding="xxxxx"?>

【问题讨论】:

  • @Tomalak 和那些 ascii 字符,它们保存在哪种编码中?请参阅此处的表格w3.org/TR/xml/#sec-guessing。 (也请阅读我与 Jon 的讨论)。
  • 我现在明白你的问题了,忘记我的评论。

标签: html .net xml parsing encoding


【解决方案1】:

您需要两种编码来读取 XML 文件(我不会提及 BOM,这只是另一个简化事情的提示):

1) 第一种编码用于读取 XML 声明。它更像是一种面向字节编码的编码,因为您只需要读取 US-ASCII 字符。你有一堆字节,你需要读取一堆 ASCII 字符。

请注意,它有效,因为编码名称只能包含 US-ASCII 字符 (IANA Character Sets)。例如,在那个阶段,您实际上不需要区分 UTF-8 和 US-ASCII,因为它们以相同的方式编码 ASCII 字符。

所以,这里要测试的编码数量是有限的,因为你关注的是 byte -> ASCII (1 byte -> 1 char, 2 bytes -> 1 char, 4 bytes -> 1 char, etc.) 字符转换,而不是整个 Unicode 集。您将在此处使用的编码可能不会用于文件的其余部分。

例如,此时您将无法区分使用Windows-1252 编码的文件和使用ISO-8859-1 编码的文件。为此,您需要读取编码名称。

2) 第二种编码用于读取文件的其余部分。

【讨论】:

  • 我在 2 分钟前提出了评论,我会再次粘贴到这里 (:-) ) --- 不过,小问题:我是解析器。我已经阅读了前 3 个字节。我做启发式直到我到达 <?xml 。伟大的!我找到了编码。它是Iso-XXX。好的。那么如果我确实找到了保险箱的钥匙,为什么我还需要阅读钥匙呢? (如果钥匙一开始不正确,我一开始就无法联系到<?xml....)
  • 您可以使用与文件的第一个字节不一致的编码名称(例如,如果第一个字节对每个字符一个字节进行编码,并且编码为 UTF-16)。在这种情况下,XML 文件不正确。
  • 此键的功能有限,如果您愿意,只能读取编码名称。
【解决方案2】:

这是必需的,因为启发式不能总是完全确定编码将是什么。例如对于没有字节顺序标记的序列,00 3C 00 3Fspec 表示编码是:

UTF-16BE 或 big-endian ISO-10646-UCS-2 或其他编码,采用 big-endian 顺序的 16 位代码单元和编码为 ASCII 值的 ASCII 字符(编码声明必须阅读确定哪个)

(已添加重点。)

实际上,如果没有字节顺序标记,看起来在所有情况下(Other 情况除外)都必须读取编码声明。它只是在规范的文本中没有非常突出。

在启发式方法不足以完成确定的情况下,解析器将其解码调整到足以读取编码声明并对编码做出最终确定就足够了. (规范实际上说了这么多。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    • 2021-07-30
    相关资源
    最近更新 更多