DocumentBuilder.parse的问题。死活想不通!

elseif 2005-04-25 08:31:16
写了一个工具类,其中一个方法。目的是从XML字符串得到一个Document对象。
public static Document getDocumentByXMLString(String xmlString){
try{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
builder = factory.newDocumentBuilder();
Document doc = null;
doc = builder.parse( new InputSource( new StringReader( xmlString ) ) );
doc.normalize(); // 删除非XML数据

return doc;
}
catch(Exception e){
e.printStackTrace();
return null;
}
}

在该类的main方法中测试此方法能成功产生Document对象。可我在一个sevelet中调用此方法,死活就是产生一个null!
...全文
6331 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
elseif 2005-04-29
  • 打赏
  • 举报
回复
恭喜 ruby_cn(__ http://www.ruby-cn.org/ __) 升两角!哈哈
elseif 2005-04-29
  • 打赏
  • 举报
回复 3
首先感谢 ruby_cn(__ http://www.ruby-cn.org/ __)的blog!
按你说的,我删除了项目中和xml相关的所有包,一切如故。我干脆删了所有的包,除了jre和j2ee,还是如故。我将DocumentBuilderFactory对象打印出:System.out.println(factory);令人惊讶的结果出现了:org.apache.xerces.jaxp.DocumentBuilderFactoryImpl@1ad086a。我本来也猜测一定是某个第三方的包的类继承了javax.xml.parsers.DocumentBuilderFactory,发现javax.xml.parsers.DocumentBuilderFactory是一个抽象类,所以的确很有可能,因为抽象类是不能产生对象的。但是也留下一个疑问,程序里并没有产生继承了javax.xml.parsers.DocumentBuilderFactory的类的对象,运行时怎么会自动产生它的子类对象。难道是sevlet容器干的好事?因为抽象类不能产生对象,自动产生继承这个抽象类的对象?类似于EJB容器产生实现home、remote接口的对象?可是现在我把第三方的包全部删除了,怎么还会输出“apache”这个字眼?这时回想起用main方法不是一切正常的吗?于是跑了一下main,又是令人惊讶的结果:org.apache.crimson.jaxp.DocumentBuilderFactoryImpl@15601ea还是“apache”的实现,但是不同的类,这个类能完好的工作。不用说,一应定是jre或j2ee里有apache的东西。结果发现在jre/lib/rt.jar里有相当多的apache的包。这个类也在这里。我才刚刚知道原来jre里不全是sun的东西。现在的问题是为什么到了sevlet就会产生org.apache.xerces.jaxp.DocumentBuilderFactoryImpl的对象。我找org.apache.xerces.jaxp.DocumentBuilderFactoryImpl类,找了很久发现他在xercesImpl包里。这个包在jboss-4.0.1sp1\lib\endorsed目录下。我把xercesImpl包倒入了那个工具类所在的项目。运行main方法,果然,输出了org.apache.xerces.jaxp.DocumentBuilderFactoryImpl。看来很清楚了,和sevlet容器没关系,只要这两个类被包含在同一个项目里,就会优先产生org.apache.xerces.jaxp.DocumentBuilderFactoryImpl对象。这是怎么回事呢,我猜想一定在DocumentBuilderFactory的产生对象的方法有个选择逻辑。这时想到jdk是有源代码的,哈哈,太好了!察看DocumentBuilderFactoryImpl的newInstance()方法:
return (DocumentBuilderFactory) FactoryFinder.find(
/* The default property name according to the JAXP spec */
"javax.xml.parsers.DocumentBuilderFactory",
/* The fallback implementation class name */
"org.apache.crimson.jaxp.DocumentBuilderFactoryImpl");
他调用了FactoryFinder.find()方法。注意在这里已经看到了"org.apache.crimson.jaxp.DocumentBuilderFactoryImpl"是的,字面意思这是作为一个后备的选择,也就是找不到其他实现了javax.xml.parsers.DocumentBuilderFactory的类,那么就返回org.apache.crimson.jaxp.DocumentBuilderFactoryImpl的对象。赶紧去看FactoryFinder.find()方法:三段注释揭露了一切:
// Use the system property first
// try to read from $java.home/lib/jaxp.properties
// try to find services in CLASSPATH
最后都找不到当然是返回后备的org.apache.crimson.jaxp.DocumentBuilderFactoryImpl啦。
String serviceId = "META-INF/services/" + factoryId;
打开xercesImpl包看看,果然有\META-INF\services目录。里面果然有个javax.xml.parsers.DocumentBuilderFactory文件。打开一看文件内容果然是org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
。看来疑团都揭开啦。但是还有一点sevlet运行的classpath怎么会有endorsed\。打开run.bat看见:"%JAVA%" %JAVA_OPTS% "-Djava.endorsed.dirs=%JBOSS_ENDORSED_DIRS%" -classpath "%JBOSS_CLASSPATH%" org.jboss.Main % 看来endorsed是作为了一个java参数。好了,一切都明白了。现在要怎么解决呢。删除xercesImpl包是一定可以的但是关于endorsed我也不懂,好像websvice要用到。关于endorsed:http://java.sun.com/j2se/1.4.2/docs/guide/standards/ 所以我不敢删。想到的办法只有System.setProperty( "javax.xml.parsers.DocumentBuilderFactory","org.apache.crimson.jaxp.DocumentBuilderFactoryImpl" );因为// Use the system property first。好了,用完以后赶快System.setProperty( "javax.xml.parsers.DocumentBuilderFactory","org.apache.xerces.jaxp.DocumentBuilderFactoryImpl" );因为不知道jboss的那些类会用到org.apache.xerces.jaxp.DocumentBuilderFactoryImpl,所以还是要恢复过来的。好了,问题虽然解决了,但是感受到了不优雅的java。
elseif 2005-04-28
  • 打赏
  • 举报
回复 1
死活要把它顶起来!哪位朋友有空可以试试
ruby_cn 2005-04-28
  • 打赏
  • 举报
回复
看看http://blog.csdn.net/ruby_cn/archive/2005/04/28/366919.aspx
ruby_cn 2005-04-28
  • 打赏
  • 举报
回复
ding !
我在servlet中调用解析xml的程序也有问题。
elseif 2005-04-28
  • 打赏
  • 举报
回复
dinnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnng
guage 2005-04-27
  • 打赏
  • 举报
回复
mark
guage 2005-04-27
  • 打赏
  • 举报
回复
mark
guage 2005-04-27
  • 打赏
  • 举报
回复
remark
dj0517 2005-04-27
  • 打赏
  • 举报
回复
up
guage 2005-04-27
  • 打赏
  • 举报
回复
mark
elseif 2005-04-26
  • 打赏
  • 举报
回复
大家可以试一下阿。
还有InputSource里有一个setSystemID方法,是不是和systemID有关呢?systemID又是什么呢?
elseif 2005-04-25
  • 打赏
  • 举报
回复
对了,还是把程序原封不动的贴出来吧
public static Document getDocumentByXMLString(String xmlString){
try{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
builder = factory.newDocumentBuilder();
Document doc = null;
System.out.println(xmlString);
doc = builder.parse( new InputSource( new StringReader( xmlString ) ) );

System.out.println(doc);
doc.normalize(); // 删除非XML数据

return doc;
}
catch(Exception e){
e.printStackTrace();
return null;
}
}


这是输出:
23:09:38,974 INFO [STDOUT] <root name="test"><checkbox value="checkbox1" checked="false"></checkbox><checkbox value="checkbox2" checked="false"></checkbox><checkbox value="checkbox3" checked="false"></checkbox><checkbox value="checkbox4" checked="false"></checkbox><checkbox value="checkbox5" checked="false"></checkbox><checkbox value="checkbox6" checked="false"></checkbox><checkbox value="checkbox7" checked="false"></checkbox><checkbox value="checkbox8" checked="false"></checkbox><checkbox value="checkbox9" checked="false"></checkbox><checkbox value="checkbox10" checked="false"></checkbox><checkbox value="checkbox11" checked="false"></checkbox><checkbox value="checkbox12" checked="false"></checkbox><checkbox value="checkbox13" checked="false"></checkbox><checkbox value="checkbox14" checked="false"></checkbox><checkbox value="checkbox15" checked="false"></checkbox><checkbox value="checkbox16" checked="true"></checkbox></root>
23:09:38,984 INFO [STDOUT] [#document: null]
elseif 2005-04-25
  • 打赏
  • 举报
回复
可是e.printStackTrace();没有打印呀
飞行的兔子 2005-04-25
  • 打赏
  • 举报
回复
如果抱了sax,dom找不到或者SAXParseException等时,就肯定是null啊!
jFresH_MaN 2005-04-25
  • 打赏
  • 举报
回复
呵呵!看到你的
catch(Exception e){
e.printStackTrace();
return null;
}
这个代码我就觉得不奇怪了!

同样的代码,同样的字符串,那么可能发生了异常,异常的原因可能是SAX和DOM的包没有找到

67,518

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧