如何让 SAX 解析器从 xml 声明中确定编码?

2022-09-01 13:20:35

我正在尝试解析来自不同来源的xml文件(我对此几乎没有控制权)。它们中的大多数都以 UTF-8 编码,使用以下代码段不会造成任何问题:

SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
FeedHandler handler = new FeedHandler();
InputSource is = new InputSource(getInputStream());
parser.parse(is, handler);

由于 SAX 默认为 UTF-8,这很好。然而,一些文件声明:

<?xml version="1.0" encoding="ISO-8859-1"?>

即使 ISO-8859-1 声明为 SAX,它仍然默认为 UTF-8。只有当我添加:

is.setEncoding("ISO-8859-1");

SAX 是否使用正确的编码。

如何让 SAX 自动检测 xml 声明中的正确编码,而无需我专门设置它?我需要这个,因为我事先不知道文件的编码是什么。

提前致谢,艾伦


答案 1

当您希望 Sax 自动检测编码时,请使用 InputStream 作为 InputSource 的参数。

如果要设置特定编码,请使用具有指定编码的 ReadersetEncoding 方法。

为什么?因为自动检测编码算法需要原始数据,而不是转换为字符。

主题中的问题是:如何让SAX解析器从xml声明中确定编码?我发现艾伦对这个问题的回答具有误导性,我根据Jörn Horstmann的评论和我后来的经验提供了另一个答案。


答案 2

我自己找到了答案。

SAX 解析器在内部使用 InputSource,并从 InputSource 文档使用:

SAX 分析器将使用 InputSource 对象来确定如何读取 XML 输入。如果有可用的字符流,则分析器将直接读取该流,而不考虑在该流中找到的任何文本编码声明。如果没有字符流,但存在字节流,则分析器将使用该字节流,使用 InputSource 中指定的编码,否则(如果未指定编码)使用类似于 XML 规范中的算法自动检测字符编码。如果字符流和字节流都不可用,则分析器将尝试打开与系统标识符标识的资源的 URI 连接。

因此,基本上您需要将字符流传递给解析器,以便它获得正确的编码。请参阅下面的解决方案:

SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
FeedHandler handler = new FeedHandler();
Reader isr = new InputStreamReader(getInputStream());
InputSource is = new InputSource();
is.setCharacterStream(isr);
parser.parse(is, handler);

推荐