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

All*_*lan 25 java xml encoding sax xml-parsing

我正在尝试解析来自不同来源的xml文件(我无法控制).其中大多数都是用UTF-8编码的,并且使用以下代码段不会导致任何问题:

SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
FeedHandler handler = new FeedHandler();
InputSource is = new InputSource(getInputStream());
parser.parse(is, handler);
Run Code Online (Sandbox Code Playgroud)

由于SAX默认为UTF-8,这很好.但是有些文件声明:

<?xml version="1.0" encoding="ISO-8859-1"?>
Run Code Online (Sandbox Code Playgroud)

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

is.setEncoding("ISO-8859-1");
Run Code Online (Sandbox Code Playgroud)

SAX会使用正确的编码吗?

如何在没有专门设置的情况下让SAX自动检测xml声明中的正确编码?我需要这个,因为我事先不知道文件的编码是什么.

艾琳,提前谢谢

Jar*_*zek 14

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

如果要设置特定编码,请使用具有指定编码或setEncoding方法的Reader.

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

主题中的问题是:如何让SAX解析器从xml声明中确定编码?我发现Allan对这个问题的回答是误导性的,我根据JörnHorstmann的评论和我后来的经验提供了另一种选择.

  • 是的:_key point_是SAX将检测`<?xml encoding =''?>`PI _only_的编码,如果`InputSource`是从`InputStream`实例构造的; 如果用`Reader`构造它将无法工作(因为'读者`的意思是它的输出是'后解码').那就是:`new InputSource(getInputStream())`是正确的. (2认同)

All*_*lan 9

我自己找到了答案.

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);
Run Code Online (Sandbox Code Playgroud)

  • 在不指定字符集的情况下构造InputStreamReader将使用您的机器的默认字符集,可能是iso-8859-1.正如您所引用的,当使用字符流时,将忽略xml中的编码decl,因此此代码仅适用于iso-8859-1文档.您的原始代码实际上应该有效,也许您可​​以添加异常或您在问题中看到的确切问题.当使用字节流而不在InputSource上设置编码时,xml解析器应自动检测编码,如http://www.w3.org/TR/REC-xml/#sec-guessing中所述. (14认同)
  • 这可能对你有用,但Jörn是对的.您引用的文档是相关且正确的.它告诉你使用InputStream的原始代码是正确的.错误在文档本身.如果您使用重写编码或使用除XML规范之外的其他方式自动检测的解决方法,就像使用InputStreamReader一样,您应该记录这一事实. (4认同)