用dom或者sax解析xml运行出现错误Content is not allowed in prol

用dom或者sax解析xml运行出现错误Content is not allowed in prolog.

原因及其解决办法:

1.xml编码错误

该xml是UTF-8编码的,如果该文件通过UltraEdit编辑后,会在无BOM头的UTF-8文件中加入BOM,但是DOM4j不认这个BOM(dom4j1.3),解决的办法可以通过升级dom4j到1.6解决www.dom4j.org

什么是BOM?http://www.unicode.org/faq/utf_bom.html#22

Unicode规范中有一个BOM的概念。BOM——Byte Order Mark,就是字节序标记。在这里找到一段关于BOM的说明:

在UCS 编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。

UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。

Windows就是使用BOM来标记文本文件的编码方式的。

2.xml文件存在非法字符

把xml 动手敲一遍,删除不该有的间隔符:比如空格,制表符(TAB)等。

 

转载:

   前两天刚发了一篇关于Resin3Spring的启动问题的文章(Resin3下配置SpringSideHelloWorld示例程序碰到的问题和解决方法),我把持久层框架换成iBATIS后又出现了解析SqlMap文件的新问题,并且花了很长时间才找到解决方法(也可能是我了解的太少,还要加强修炼,呵呵),不管怎么样还是写出来和大家分享,希望对大家有所帮助。

      Struts+Spring+Hibernate是目前J2EE企业级开发绝对Killer级的框架组合,相当轻量,优雅,但毫不影响它的强大。虽然因为现在各种表示层框架发展异常活跃,Struts受到了前所未有的挑战和冲击,但是就目前使用面而言这三种框架的组合是JAVA程序员不得不深入的经典。他们相关的资料也比较多,实际运用中也最成熟。但是诸如JSF,iBATIS等后起之秀(说他们后起并不代表他们的历史,只是流行程度)也渐渐的占据自己的一席之地成为某些场合下开发的不二选择。在web服务器方面也是一样,除了Tomcat我们还有了更多好的选择(Resin Jetty等)。虽然各种框架都声称自己可以无缝集成各种其他框架,不需要任何修改运行在各种服务器上面,但是我在我最近的一些经验发现把一些平时比较少组合在一起的东西放在一起后确实存在很多想不到的意外,排除起来也颇费一些周折。这可能也是开源和商业的差距,不完善的文档,没有足够覆盖面和严格的测试等,不过我们都要以一个宽容的态度对待开源,因为开源需要我们每个人的参与和贡献,从而真正达到Richard. M. Stallman心中的软件自由。

      我会不断的把在各种非常用的组合使用中遇到的的问题贴出来与大家分享,总有人会需要,呵呵。

      言归正传,今天的主题是在Resin3下使用SpringiBATIS的组合开发时碰到的SqlMap文件解析问题,和开头提到的我的另一篇文章一样,也是一个xml配置文件的解析问题。使用的仍然是SpringSideHelloWorld示例,这里顺便说个题外话SpringSide是一个我比较欣赏和推荐的国人自己打造的企业级快速开发框架,特别是他的wiki真是一个非常好的各种相关技术的学习资料,但是他发布的示例中含有不少的错误,特别是非主流的(非Tomcat下,iBATIS等)模式下有很多问题,希望SpringSide的大侠们能够更加完善。我是你们忠实的支持者。

      上篇文章  中提到了Resin3下使用Spring必须要更换默认的xml解析器,换成xerces后就可以正常启动了,然后把持久层框架由Hibernate换为iBATIS后又出现了新的问题,启动时一切正常,SpringStruts的初始化都没有问题,但是当第一次需要连接数据库时就出现了问题,因为这个时候需要解析SqlMap文件来提供对应的Sql语句进行查询RDB,从异常信息来判断问题出在文件解析的时候,错误信息如下(因为很长,所以只贴了最底层的异常):

 1Caused by: 
 2org.xml.sax.SAXParseException: Content is not allowed in prolog.
 3    at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
 4    at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(Unknown Source)
 5    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
 6    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
 7    at org.apache.xerces.impl.XMLScanner.reportFatalError(Unknown Source)
 8    at org.apache.xerces.impl.XMLDocumentScannerImpl$PrologDispatcher.dispatch(Unknown Source)
 9    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
10    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
11    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
12    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
13    at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
14    at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
15    at com.ibatis.common.xml.NodeletParser.createDocument(NodeletParser.java:150)
16    at com.ibatis.common.xml.NodeletParser.parse(NodeletParser.java:50)
17    at com.ibatis.sqlmap.engine.builder.xml.SqlMapParser.parse(SqlMapParser.java:45)
18    at com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser$11.process(SqlMapConfigParser.java:347)
19    at com.ibatis.common.xml.NodeletParser.processNodelet(NodeletParser.java:112)
20    at com.ibatis.common.xml.NodeletParser.process(NodeletParser.java:75)
21    at com.ibatis.common.xml.NodeletParser.process(NodeletParser.java:93)
22    at com.ibatis.common.xml.NodeletParser.parse(NodeletParser.java:63)
23    at com.ibatis.common.xml.NodeletParser.parse(NodeletParser.java:51)
24    at com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser.parse(SqlMapConfigParser.java:78)
25    at com.ibatis.sqlmap.client.SqlMapClientBuilder.buildSqlMapClient(SqlMapClientBuilder.java:62)
26    at org.springframework.orm.ibatis.SqlMapClientFactoryBean.afterPropertiesSet(SqlMapClientFactoryBean.java:255)
27    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1062)
28    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1029)
29    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:420)
30    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:245)
31    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:141)
32    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:242)
33    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:156)
34    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByName(AbstractAutowireCapableBeanFactory.java:749)
35    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:704)
36    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:416)
37    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:245)
38    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:141)
39    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:242)
40    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:223)
41    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:156)
42    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByName(AbstractAutowireCapableBeanFactory.java:749)
43    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:704)
44    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:416)
45    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:245)
46    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:141)
47    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:242)
48    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
49    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:646)
50    at org.springframework.web.struts.DelegatingRequestProcessor.getDelegateAction(DelegatingRequestProcessor.java:168)
51    at org.springframework.web.struts.DelegatingRequestProcessor.processActionCreate(DelegatingRequestProcessor.java:146)
52    at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:230)
53    at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
54    at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)
55    at javax.servlet.http.HttpServlet.service(HttpServlet.java:115)
56    at javax.servlet.http.HttpServlet.service(HttpServlet.java:92)
57    at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:106)
58    at org.extremecomponents.table.filter.AbstractExportFilter.doFilter(AbstractExportFilter.java:49)
59    at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
60    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:78)
61    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:77)
62    at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
63    at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:178)
64    at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:229)
65    at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:268)
66    at com.caucho.server.port.TcpConnection.run(TcpConnection.java:389)
67    at com.caucho.util.ThreadPool.runTasks(ThreadPool.java:507)
68    at com.caucho.util.ThreadPool.run(ThreadPool.java:433)
69    at java.lang.Thread.run(Thread.java:595)



      
异常提示是Content is not allowed in prolog.意思就是说文件开头的时候有问题。。。我E文不好不能解释的信,雅,达,见谅,呵呵。还是跟我为了Spring而换上的xerces有关。。。狂晕,google了一番发现是一个叫BOM的东西搞的鬼,而xerces确实有BOM的问题,在Apache的论坛里看到一个帖子也提到xercesBOM问题,回帖是说换掉xerces用其他解析器,可是我不能换,换了Spring还指望它呢,我也不知道换成什么比它更好。。。,还有的说给xerces的如果是stream就可以接受BOM,如果是reader就不行(我默认大家都对JAVAIO有一定了解能够理解streamreader啊),难道我跑去把iBATIS里的源代码改了,然后重新编译???这样也不好吧,总有简单点的方式解决吧。

      于是继续google,随着对BOM进一步的了解发现把SqlMap文件里的BOM给删除调应该是最快最方便的方式,因为BOMUTF-8里面并不起什么作用,本来是可有可无的。下面先让大家对BOM有个大概的认识(细节可以参考官方网站 ),然后告诉大家怎么样快捷的删掉文件里的BOM

      我们这里提到的BOM并不是制造业管理中料表(Bill of Material)的概念,而是UCSUnicode的学名是"Universal Multiple-Octet Coded Character Set",简称为UCS)编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFEUCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。这样如果接收者收到FEFF,就表明这个字节流是Big-Endianbig endianlittle endianCPU处理多字节数的不同方式。例如字的Unicode编码是6C49。那么写到文件里时,究竟是将6C写在前面,还是将49写在前面?如果将6C写在前面,就是big endian。还是将49写在前面,就是little endian。我们一般将endian翻译成字节序,将big endianlittle endian称作大尾小尾。)的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM

      UTF-8是以8位为单位来表示UCS,其实不存在什么尾序的问题,其实BOM是没有什么作用的,不过可以用BOM来表示编码方式,字符"ZERO WIDTH NO-BREAK SPACE"UTF-8编码是EF BB BF,所以如果接受到以EF BB BF开头的字节流就可以判断是UTF-8编码了。

      如果上面提到的一些名词你不是很清楚可以google一下,找到相关的解释。追根究底是个好习惯?。如果对BOM的概念还不清楚或者想了解更多也可以搜索相关资料来研究。

      下面重点来说一下怎么去掉BOM

      首先windows自带的记事本会在保存UTF-8编码的文件时不管是否含有BOM一律加上BOM,所以千万别用记事本。我的程序跑不起来也是因为用记事本打开过。。。有段时间非常流行的联通问题就是跟windows记事本处理BOM的机制有关,就是把联通两字写进记事本保存后再打开时就会是黑点如果你有兴趣可以到网上找到相关文章详细解释给你听,呵呵。

      比较新版本的UltraEdit(以下简称UE,大家都是这么叫的)都对BOM支持比较好,所以推荐使用新版本的UE来解决这个问题。我用的版本是UltraEdit-32 10.20d+中文版(网上可以下的到,如果你比较懒可以联系我,留下邮箱,呵呵)。首先打开UE,选择菜单栏高级配置,出现一个选项卡窗口,在常规选项卡中找到保存时对所有UTF-8文件头标记(BOM对在UltraEdit里创建的新文件写入UTF-8文件头标记(如上面),把它们的复选框都取消不选,然后确定。这个时候UE默认情况下就不会对没有BOM的文件加入BOM,注意如果不执行上述操作UE默认也是会加的!那已经含有BOM的文件如何清除BOM呢?下面演示给大家。首先打开文件,选择菜单栏文件格式转换“UTF-8  ASCII”,这样文件会被转为ASCII编码,BOM就不会存在了,因为上面说过BOM是在UCS编码的头部的,然后再选择菜单栏文件格式转换“ASCII  UTF-8Unicode编辑),这个时候文件会被转回为UTF-8编码,因为我们上面选了不自动加BOM,所以这个时候的文件是不带BOM的,然后保存文件。整个操作过程就完毕了。


你可能感兴趣的:(用dom或者sax解析xml运行出现错误Content is not allowed in prol)