背景:
解析本地的一个XML文件,文件编码GBK,XML文件头:xml version="1.0" encoding="GBK" ?>
可能的代码:
运行时抛出异常
SAXParseException: The encoding "GBK" is not supported。
按照网络上说的方法:检查xml的格式,utf-8 去BOM 诸如此类都没有办法解决。
原来是jar包惹的祸:
dom4j-1.6.1.jar 依赖于xerces 对xml解析的实现。
而一般使用的xerces-2.6.2.jar 并不支持GBK的编码格式。
为什么有些情况下又没问题呢?
关键jdk的版本,jdk6后的rt包实现了xml解析,支持gbk,故2种解决方案。
1. 升级xerces.jar
2. 升级jdk 或者(关掉1.4兼容API)
=====原因再分析==========
见 http://dom4j.sourceforge.net/dom4j-1.6.1/apidocs/org/dom4j/io/SAXReader.html
The actual SAX parser that is used by this class is configurable so you can use your favourite SAX parser if you wish. DOM4J comes configured with its own SAX parser so you do not need to worry about configuring the SAX parser.
To explicitly configure the SAX parser that is used via Java code you can use a constructor or use the setXMLReader(XMLReader)
or setXMLReaderClassName(String)
methods.
If the parser is not specified explicitly then the standard SAX policy of using the org.xml.sax.driver
system property is used to determine the implementation class of XMLReader
.
If the org.xml.sax.driver
system property is not defined then JAXP is used via reflection (so that DOM4J is not explicitly dependent on the JAXP classes) to load the JAXP configured SAXParser. If there is any error creating a JAXP SAXParser an informational message is output and then the default (Aelfred) SAX parser is used instead.
-------------call trace---------
org.dom4j.io.SAXReader.read(XXXX)
org.dom4j.io.SAXReader.read(InputSource in)
org.dom4j.io.SAXReader.getXMLReader(SAXReader.java:715)
org.dom4j.io.SAXReader.createXMLReader(SAXReader.java:894)
org.dom4j.io.SAXHelper.createXMLReader(SAXHelper.java:83)
org.xml.sax.helpers.XMLReaderFactory.createXMLReader()
先查找 property的值
private static final String property = "org.xml.sax.driver";
public static XMLReader createXMLReader ()
throws SAXException
{
String className = null;
ClassLoader loader = NewInstance.getClassLoader ();
// 1. try the JVM-instance-wide system property
try { className = System.getProperty (property); }
catch (RuntimeException e) { /* normally fails for applets */ }
// 2. if that fails, try META-INF/services/
if (className == null) {
try {
String service = "META-INF/services/" + property;
InputStream in;
BufferedReader reader;
if (loader == null)
in = ClassLoader.getSystemResourceAsStream (service);
else
in = loader.getResourceAsStream (service);
if (in != null) {
reader = new BufferedReader (
new InputStreamReader (in, "UTF8"));
className = reader.readLine ();
in.close ();
}
} catch (Exception e) {
}
}
// 3. Distro-specific fallback
if (className == null) {
// BEGIN DISTRIBUTION-SPECIFIC
// EXAMPLE:
// className = "com.example.sax.XmlReader";
// or a $JAVA_HOME/jre/lib/*properties setting...
className = "com.sun.org.apache.xerces.internal.parsers.SAXParser";
// END DISTRIBUTION-SPECIFIC
}
// do we know the XMLReader implementation class yet?
if (className != null)
return loadClass (loader, className);
// 4. panic -- adapt any SAX1 parser
try {
return new ParserAdapter (ParserFactory.makeParser ());
} catch (Exception e) {
throw new SAXException ("Can't create default XMLReader; "
+ "is system property org.xml.sax.driver set?");
}
}