用dom或者sax解析xml運行出現錯誤Content is not allowed in prolog.html
緣由及其解決辦法:java
1.xml編碼錯誤程序員
該xml是UTF-8編碼的,若是該文件經過UltraEdit編輯後,會在無BOM頭的UTF-8文件中加入BOM,可是DOM4j不認這個BOM(dom4j1.3),解決的辦法能夠經過升級dom4j到1.6解決www.dom4j.orgweb
什麼是BOM?http://www.unicode.org/faq/utf_bom.html#22spring
Unicode規範中有一個BOM的概念。BOM——Byte Order Mark,就是字節序標記。在這裏找到一段關於BOM的說明:sql
在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編碼了。apache
Windows就是使用BOM來標記文本文件的編碼方式的。windows
2.xml文件存在非法字符服務器
把xml 動手敲一遍,刪除不應有的間隔符:好比空格,製表符(TAB)等。
轉載:
前兩天剛發了一篇關於Resin3下Spring的啓動問題的文章(在Resin3下配置SpringSide的HelloWorld示例程序碰到的問題和解決方法),我把持久層框架換成iBATIS後又出現瞭解析SqlMap文件的新問題,而且花了很長時間才找到解決方法(也多是我瞭解的太少,還要增強修煉,呵呵),無論怎麼樣仍是寫出來和你們分享,但願對你們有所幫助。
Struts+Spring+Hibernate是目前J2EE企業級開發絕對Killer級的框架組合,至關輕量,優雅,但絕不影響它的強大。雖然由於如今各類表示層框架發展異常活躍,Struts受到了史無前例的挑戰和衝擊,可是就目前使用面而言這三種框架的組合是JAVA程序員不得不深刻的經典。他們相關的資料也比較多,實際運用中也最成熟。可是諸如JSF,iBATIS等後起之秀(說他們後起並不表明他們的歷史,只是流行程度)也漸漸的佔據本身的一席之地成爲某些場合下開發的不二選擇。在web服務器方面也是同樣,除了Tomcat咱們還有了更多好的選擇(Resin ,Jetty等)。雖然各類框架都聲稱本身能夠無縫集成各類其餘框架,不須要任何修改運行在各類服務器上面,可是我在我最近的一些經驗發現把一些平時比較少組合在一塊兒的東西放在一塊兒後確實存在不少想不到的意外,排除起來也頗費一些周折。這可能也是開源和商業的差距,不完善的文檔,沒有足夠覆蓋面和嚴格的測試等,不過咱們都要以一個寬容的態度對待開源,由於開源須要咱們每一個人的參與和貢獻,從而真正達到Richard. M. Stallman心中的軟件自由。
我會不斷的把在各類很是用的組合使用中遇到的的問題貼出來與你們分享,總有人會須要,呵呵。
言歸正傳,今天的主題是在Resin3下使用Spring和iBATIS的組合開發時碰到的SqlMap文件解析問題,和開頭提到的個人另外一篇文章同樣,也是一個xml配置文件的解析問題。使用的仍然是SpringSide的HelloWorld示例,這裏順便說個題外話SpringSide是一個我比較欣賞和推薦的國人本身打造的企業級快速開發框架,特別是他的wiki真是一個很是好的各類相關技術的學習資料,可是他發佈的示例中含有很多的錯誤,特別是「非主流的」(非Tomcat下,iBATIS等)模式下有不少問題,但願SpringSide的大俠們可以更加完善。我是大家忠實的支持者。
上篇文章 中提到了Resin3下使用Spring必需要更換默認的xml解析器,換成xerces後就能夠正常啓動了,而後把持久層框架由Hibernate換爲iBATIS後又出現了新的問題,啓動時一切正常,Spring和Struts的初始化都沒有問題,可是當第一次須要鏈接數據庫時就出現了問題,由於這個時候須要解析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的論壇裏看到一個帖子也提到xerces的BOM問題,回帖是說換掉xerces用其餘解析器,但是我不能換,換了Spring還期望它呢,我也不知道換成什麼比它更好。。。,還有的說給xerces的若是是stream就能夠接受BOM,若是是reader就不行(我默認你們都對JAVA的IO有必定了解可以理解stream和reader啊),難道我跑去把iBATIS裏的源代碼改了,而後從新編譯???這樣也很差吧,總有簡單點的方式解決吧。
因而繼續google,隨着對BOM進一步的瞭解發現把SqlMap文件裏的BOM給刪除調應該是最快最方便的方式,由於BOM在UTF-8裏面並不起什麼做用,原本是無關緊要的。下面先讓你們對BOM有個大概的認識(細節能夠參考官方網站 ),而後告訴你們怎麼樣快捷的刪掉文件裏的BOM。
咱們這裏提到的BOM並非製造業管理中料表(Bill of Material)的概念,而是UCS(Unicode的學名是"Universal Multiple-Octet Coded Character Set",簡稱爲UCS)編碼中有一個叫作"ZERO WIDTH NO-BREAK SPACE"的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,因此不該該出如今實際傳輸中。UCS規範建議咱們在傳輸字節流前,先傳輸字符"ZERO WIDTH NO-BREAK SPACE"。這樣若是接收者收到FEFF,就代表這個字節流是Big-Endian(big endian和little endian是CPU處理多字節數的不一樣方式。例如「漢」字的Unicode編碼是6C49。那麼寫到文件裏時,到底是將6C寫在前面,仍是將49寫在前面?若是將6C寫在前面,就是big endian。仍是將49寫在前面,就是little endian。咱們通常將endian翻譯成「字節序」,將big endian和little 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-8(Unicode編輯)」,這個時候文件會被轉回爲UTF-8編碼,由於咱們上面選了不自動加BOM,因此這個時候的文件是不帶BOM的,而後保存文件。整個操做過程就完畢了。