??xml version="1.0" encoding="utf-8" standalone="yes"?> 在IBM的developerWorks上有两篇非常优秀的关?span style="COLOR: #cc0000">JavaXML API的评文章: 对这两篇文章我想说的是 吐血推荐 Java?span style="COLOR: #cc0000">XML APIq几文章该讲的都讲CQ我只想补充几点Q?/p>
Crimson来自于Sun捐赠lApache的ProjectX目QXerces来自IBM捐赠lApache?span style="COLOR: #cc0000">XML4J目Q结果Xerces胜出Q成了Apache XML组全力开发的XML APIQ而Crimon已经早就不做了,如今Xerces名满天下Q到处都是在用Xerces DOM和SAX解析器,只有Sun不服气,非要在JDK1.4里面使用q时的CrimsonQ让人感觉像是在赌气一P真是让h可怜又可气Q不qIBM发行JDK用的XML 解析器自然是Xerces?/p>
׃JDK的Class Loader的优先关系Q当你采用JAXP~写XMLE序的时候,即把Xerces包引入CLASSPATHQJDKq是会顽固的使用CrimsonQ这一炚w过打开JVM的verbose参数可以观察到。不qJDK也允怽采用其它的解析器Q因此我们可以通过在JRE\lib\目录下徏一个jaxp.properties的文Ӟ来替换解析器Qjaxp.properties内容如下Q?/p>
q样可以用XercesQ当然你必须q是要把Xerces包放到CLASSPATH下?/p>
Sun?span style="COLOR: #cc0000">XML领域L后知后觉Q等到Sun重视XML的时候,XML的API早就满天 飞了Q尤其是IBMh非常大的领先优势。不qSun是规范的制订者,于是参考W3C的标准制订了JAXP规范。JAXP不像Xerces和Crimon那样Q它只是一个specQ本w是不做M事情的,它的作用是提出一个统一的接口,让其它的XML API都来遵@JAXP~程Q那么用JAXP写出来的E序Q底层的API可以L切换?/p>
具体来说JAXP包括了几个工厂类Q这是JDK1.4里面?span style="COLOR: #cc0000">javax.xml.parsers 包,用来LW合DOM标准?span style="COLOR: #cc0000">XML API实现cȝ位置Q此外JAXPq包括一整套interfaceQ这是JDK1.4里面的org.w3c.dom那几个包。工厂类负责加蝲DOM的实现类。那么加载的规则是什么呢Q?/p>
我是通过阅读JAXP的源代码知道的,工厂c首先会Ҏjava命o行传入的参数q行LQ然后在ҎJRE\lib\jaxp.properties中定义的实现cd找,最后什么都找不到的话,qCrimson。注意Crimons是由Bootstrap Class Loader来load的,如果你不通过上面两个Ҏ来改变工厂的L序Q那么铁定用Crimson?:( 当你严格采用JAXP~程的时候,是遵循W3C的DOm标准的,那么在JAXP底层你实际上可以L切换不同的DOM实现Q例如XercesQ或者CrimonQ再或者其它,切换Ҏ是配置jaxp.properties。因此JAXP是一些标准接口而已?/p>
而Xerces和Crimon也不单单是一个DOM实现那么单,他们本n实际上也包含SAX解析器和DOM解析器。所以一个JAXPE序下面有如下层ơ: 只要你用JAXP~程Q那么你可以切换到Crimson上来 另外你也可以q样来做Q?/p>
不过如果你的E序不安装JAXP来写Q那么就没有办法切换不同的DOM实现了?/p>
W3C的DOM标准API隄的让人想撞墙Q于是有一帮h开?span style="COLOR: #cc0000">Java专用?span style="COLOR: #cc0000">XML API目的是ؓ了便于用,q就是jdom的由来,开发到一半的时候,另一部分人又分了出来Q他们有自己的想法,于是他们去开发dom4jQŞ成了今天q样两个APIQ至于他们之间的性能Q功能之比较看看上面我推荐的文章q道了Qjdom全面惨|?/p>
jdom 相当于上面的 JAXP接口 Q?Xerces DOM实现部分Q它本n没有解析器,它可以用Xerces或者Crimson的解析器Q就是这P dom4j 和jdomcMQ不q他自己l定了一个叫做Alfred2的解析器Q功能不是很全,但是速度很快Q当没有其它的解析器的时候,dom4j用Alfred2解析器,如下Q?/p>
或?/p>
你在SF上下载的dom4j.jar是不?Alfred2解析器的Q而dom4j-full.jar包含?Alfred2解析器,在这U情况下Q实际上你什么也不需要,光是一个dom4j-full.jar全部都包括了?/p>
因此可以看出采用dom4j/jdom~写的应用程序,已经不具备可UL性了?/p>
Sun是JAXP标准的制订者,甚至很执著的在JDK1.4里面l定Crimson DOM实现和解析器Q然后可W的是,Sun自己的JAXM RI竟然不是用JAXP写出来的Q而是dom4jQ制订标准让大家遵守Q自己却监守自盗Q这未免太说不过M吧! BTW: Hibernate也用的是dom4j来读?span style="COLOR: #cc0000">XML配置文gQ如今已l越来越多的E序UL采用dom4jQ如果你不是那么在乎可移植性,我强烈徏议你采用dom4j?/p>
获得q安装JDOM
在http://jdom.org可以下蝲JDOM的最新版本。以JDOM beta8?q制版本Z。下载后解压~,JDOM的jar文g是build目录下的文gjdom.jarQ将之加入类路径。另外JDOMq需要lib目录下那些jar文g如xerces.jar,jaxp.jar的支持。如果在使用中出C下错误:
java.lang.NoSuchMethodError
?nbsp;
java.lang.NoClassDefFoundError: org/xml/sax/SAXNotRecognizedException
你需要保证xerces.jar文g在CLASSPATH中位于其他XMLc,如JAXP或Crimson之前Q这些类文gQ包括以前老版本的xercesQ可能不支持SAX2.0或DOM Level 2。于是导致了上面的错误?nbsp;
一个简单的例子
JDOM的处理方式有些类gDOMQ但它主要是用SAX实现的,你不必担心处理速度和内存的问题。另外,JDOM中几乎没有接口,的类全部是实实在在的c,没有cd厂类的?br>
下面是实例用的XML文g:
<?xml version="1.0" encoding="GBK"?>
<书库>
<?gt;
<书名>Java~程入门</书名>
<作?gt;张三</作?gt;
<出版C?gt;电子出版C?lt;/出版C?gt;
<h>35.0</h>
<出版日期>2002-10-07</出版日期>
</?gt;
<?gt;
<书名>XML在Java中的应用</书名>
<作?gt;李四</作?gt;
<出版C?gt;希望出版C?lt;/出版C?gt;
<h>92.0</h>
<出版日期>2002-10-07</出版日期>
</?gt;
</书库>
下面是操作XML文g的Bean:
package xml;
/**
* XML的读写操作Bean
*/
import java.io.*;
import java.util.*;
import org.jdom.*;
import org.jdom.output.*;
import org.jdom.input.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class XmlBean{
private String bookname,author,pub,price,pubdate;
public String getbookname() { return bookname;}
public String getauthor() { return author;}
public String getpub() { return pub;}
public String getprice() { return price;}
public String getpubdate() { return pubdate;}
public void setbookname(String bookname) { this.bookname =bookname ; }
public void setauthor(String author) { this.author =author; }
public void setpub(String pub) { this.pub =pub ; }
public void setprice(String price) { this.price =price ; }
public void setpubdate(String pubdate) { this.pubdate =pubdate ; }
public XmlBean(){}
/**
* dXML文g所有信?br>*/
public Vector LoadXML(String path)throws Exception{
Vector xmlVector = null;
FileInputStream fi = null;
try{
fi = new FileInputStream(path);
xmlVector = new Vector();
SAXBuilder sb = new SAXBuilder();
Document doc = sb.build(fi);
Element root = doc.getRootElement(); //得到根元?br>List books = root.getChildren(); //得到根元素所有子元素的集?br>Element book =null;
XmlBean xml =null;
for(int i=0;i<books.size();i++){
xml = new XmlBean();
book = (Element)books.get(i ); //得到W一本书元素
xml.setbookname(book.getChild("书名").getText());
xml.setauthor(book.getChild("作?).getText());
xml.setpub(book.getChild("出版C?).getText());
xml.setprice(book.getChild("h").getText());
xml.setpubdate(book.getChild("出版日期").getText());
xmlVector.add(xml);
}
}
catch(Exception e){
System.err.println(e+"error");
}
finally{
try{
fi.close();
}
catch(Exception e){
e.printStackTrace();
}
}
return xmlVector;
}
/**
* 删除XML文g指定信息
*/
public static void DelXML(HttpServletRequest request)throws Exception{
FileInputStream fi = null;
FileOutputStream fo = null;
try{
String path=request.getParameter("path");
int xmlid=Integer.parseInt(request.getParameter("id"));
fi = new FileInputStream(path);
SAXBuilder sb = new SAXBuilder();
Document doc = sb.build(fi);
Element root = doc.getRootElement(); //得到根元?br>List books = root.getChildren(); //得到根元素所有子元素的集?br>books.remove(xmlid);//删除指定位置的子元素
String indent = " ";
boolean newLines = true;
XMLOutputter outp = new XMLOutputter(indent,newLines,"GBK");
fo=new FileOutputStream(path);
outp.output(doc,fo);
}
catch(Exception e){
System.err.println(e+"error");
}
finally{
try{
fi.close();
fo.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
/**
* dXML文g指定信息
*/
public static void AddXML(HttpServletRequest request)throws Exception{
FileInputStream fi = null;
FileOutputStream fo = null;
try{
String path=request.getParameter("path");
fi = new FileInputStream(path);
SAXBuilder sb = new SAXBuilder();
Document doc = sb.build(fi);
Element root = doc.getRootElement(); //得到根元?br>List books = root.getChildren(); //得到根元素所有子元素的集?br>String bookname=request.getParameter("bookname");
String author=request.getParameter("author");
String price=request.getParameter("price");
String pub=request.getParameter("pub");
String pubdate=request.getParameter("pubdate");
Text newtext;
Element newbook= new Element("?);
Element newname= new Element("书名");
newname.setText(bookname);
newbook.addContent(newname);
Element newauthor= new Element("作?);
newauthor.setText(author);
newbook.addContent(newauthor);
Element newpub= new Element("出版C?);
newpub.setText(pub);
newbook.addContent(newpub);
Element newprice= new Element("h");
newprice.setText(price);
newbook.addContent(newprice);
Element newdate= new Element("出版日期");
newdate.setText(pubdate);
newbook.addContent(newdate);
books.add(newbook);//增加子元?br>String indent = " ";
boolean newLines = true;
XMLOutputter outp = new XMLOutputter(indent,newLines,"GBK");
fo=new FileOutputStream(path);
outp.output(doc,fo);
}
catch(Exception e){
System.err.println(e+"error");
}
finally{
try{
fi.close();
fo.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
/**
* 修改XML文g指定信息
*/
public static void EditXML(HttpServletRequest request)throws Exception{
FileInputStream fi = null;
FileOutputStream fo = null;
try{
String path=request.getParameter("path");
int xmlid=Integer.parseInt(request.getParameter("id"));
fi = new FileInputStream(path);
SAXBuilder sb = new SAXBuilder();
Document doc = sb.build(fi);
Element root = doc.getRootElement(); //得到根元?br>List books = root.getChildren(); //得到根元素所有子元素的集?br>Element book=(Element)books.get(xmlid);
String bookname=request.getParameter("bookname");
String author=request.getParameter("author");
String price=request.getParameter("price");
String pub=request.getParameter("pub");
String pubdate=request.getParameter("pubdate");
Text newtext;
Element newname= book.getChild("书名");
newname.setText(bookname);//修改书名为新的书?br>Element newauthor= book.getChild("作?);
newauthor.setText(author);
Element newpub= book.getChild("出版C?);
newpub.setText(pub);
Element newprice= book.getChild("h");
newprice.setText(price);
Element newdate= book.getChild("出版日期");
newdate.setText(pubdate);
//books.set(xmlid,book);//修改子元?br>String indent = " ";
boolean newLines = true;
XMLOutputter outp = new XMLOutputter(indent,newLines,"GBK");
fo=new FileOutputStream(path);
outp.output(doc,fo);
}
catch(Exception e){
System.err.println(e+"error");
}
finally{
try{
fi.close();
fo.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
下面是操作的jsp文g:
<%@ page contentType="text/html;charset=GBK" %>
<%@ page language="java" import="java.util.*,xml.*"%>
<html>
<head>
<title>dXML文g资料</title>
</head>
<body>
<h3 align="center">JDOM操作XML文g</h3>
<p align="center">dXML文g中的所有资?lt;/p>
<center>
<table border="1" cellpadding="0" cellspacing="1" style="border-collapse: collapse" width="80%" id="AutoNumber1">
<tr>
<td align="center" width="92">书名</td>
<td align="center" width="92">作?lt;/td>
<td align="center" width="92">出版C?lt;/td>
<td align="center" width="92">h</td>
<td align="center" width="92">出版日期</td>
<td align="center" width="94">操作</td>
</tr>
</table>
<%
String path = application.getRealPath("/test/xml/")+"testC.xml";
XmlBean xml=new XmlBean();
Vector xmlall=xml.LoadXML(path);
for(int i=0;i<xmlall.size();i++){
xml=(XmlBean)xmlall.elementAt(i );
/**out.println("书名:"+xml.getbookname()+"<br>");
out.println("作?"+xml.getauthor()+"<br>");
out.println("出版C?"+xml.getpub()+"<br>");
out.println("h:"+xml.getprice()+"<br>");
out.println("出版日期:"+xml.getpubdate()+"<br><br>");
*/
%>
<table border="1" cellpadding="0" cellspacing="1" style="border-collapse: collapse" width="80%" id="AutoNumber2">
<tr>
<td align="center" width="92"><%=xml.getbookname()%></td>
<td align="center" width="92"><%=xml.getauthor()%></td>
<td align="center" width="92"><%=xml.getpub()%></td>
<td align="center" width="92"><%=xml.getprice()%></td>
<td align="center" width="92"><%=xml.getpubdate()%></td>
<td align="center" width="94"><a href="xmlok.jsp?act=del&id=<%=i%>&path=<%=path%>">删除</a></td>
</tr>
</table>
<%}%>
</center>
<form method="POST" action="xmlok.jsp">
<p align="center">
<input type="radio" value="add" checked name="act">d资料 <input type="radio" value="edit" name="act">~辑资料
?nbsp;?<select size="1" name="id">
<%for(int i=0;i<xmlall.size();i++){%>
<option value="<%=i%>">W?lt;%=i+1%>?lt;/option>
<%}%>
</select><br>
?nbsp;?<input type="text" name="bookname" size="20"><br>
?nbsp;?<input type="text" name="author" size="20"><br>
出版C?<input type="text" name="pub" size="20"><br>
?nbsp;?<input type="text" name="price" size="20"><br>
?nbsp;?<input type="text" name="pubdate" size="20"></p>
<input type="hidden" name="path" value="<%=path%>">
<p align="center"><input type="submit" value="提交" name="B1"><input type="reset" value="重置" name="B2"></p>
</form>
</body>
</html>
下面是处理上一文g提交的jsp文g:
<%@ page contentType="text/html;charset=GBK" %>
<%@ page language="java" import="xml.*"%>
<%if(request.getParameter("act")!=null && request.getParameter("act").equals("add")){
XmlBean.AddXML(request);
out.println("<p align=’center’><br><br>d成功<br><br><a href=’’>q回</a>");
}
else if(request.getParameter("act")!=null && request.getParameter("act").equals("del")){
XmlBean.DelXML(request);
out.println("<p align=’center’><br><br>删除成功<br><br><a href=’’>q回</a>");
}
else if(request.getParameter("act")!=null && request.getParameter("act").equals("edit")){
XmlBean.EditXML(request);
out.println("<p align=’center’><br><br>修改成功<br><br><a href=’’>q回</a>");
}
else{out.print("<p align=’center’><br><br>非法操作<br><br><a href=’’>q回</a>");}
]]>一、Crimson和Xerces恩仇?/h4>
javax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
javax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl
二、JAXP的姗姗来q?/h4>
三、DOM解析器和DOM API
JAXP应用E序 -> JAXP接口 -> Xerces DOM实现 -> Xerces DOM/SAX 解析?
JAXP应用E序 -> JAXP接口 -> Crimson DOM实现 -> Crimson DOM/SAX 解析?
JAXP应用E序 -> JAXP接口 -> Crimson DOM实现 -> Xerces DOM/SAX 解析?
四、不是标准的dom4j和jdom
jdom应用E序 -> jdom API -> Xerces/Crimson解析?
dom4j应用E序 -> dom4j API -> Xerces/Crimson解析?
dom4j应用E序 -> dom4j API -> Alfred2解析?
五、小插曲
]]>
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//System.out.print(new MD5().getMD5ofStr(""));
sampleJDom();
}
/*
* jdom
*/
public static void sampleJDom()
{
//新徏文档对象
Document doc = new Document();
//新徏根节?br> Element book = new Element("book");
book.setAttribute("title", "Programming with Ajax");
Element chapter1 = new Element("chapter");
chapter1.setAttribute("name", "Chapter1 About Ajax");
Element chapter2 = new Element("chapter");
chapter2.setAttribute("name", "Chapter2 B/S Structure");
Element section1 = new Element("section");
section1.addContent("What is Ajax?");
Element section2 = new Element("section");
section2.addContent("Definiens of Ajax");
Element section3 = new Element("section");
section3.addContent("HTTP Protocal");
Element section4 = new Element("section");
section4.addContent("Web Design");
//子节点加入到父节点
chapter1.addContent(section1);
chapter1.addContent(section2);
chapter2.addContent(section3);
chapter2.addContent(section4);
book.addContent(chapter1);
book.addContent(chapter2);
doc.addContent(book);
//文输出到控制?
XMLOutputter outputter = new XMLOutputter();
try
{
outputter.output(doc, new FileOutputStream(new File("c:/a.xml")));
System.out.println("输出到文件成?");
outputter.output(doc, System.out);
System.out.println("输出到控制台!");
}catch(IOException ex)
{}
}
}