用jdom处理xml文档
关键词:java、jdom、xml、jaxb
欢迎与我讨论(boyofjava@sina.com)
(一)jdom的介绍以及与jaxb的比较
java + xml = jdom !
这就是jdom设计者的目标。如果你曾经使用过烦人的sax或是dom来处理xml,你就会知道为什么要有jdom或者是jaxb。在今年(2002)的javaone会议上jdom的主要创始人jason hunter有一篇精彩的演讲介绍了jdom技术,题目就是jdom makes xml easy。
在那篇文档里,jdom被拿来与dom比较,而我更愿意拿它同jaxb比较。因为jaxb和jdom都是为了在java中提供比dom和sax更为方便的xml处理接口而开发的,并且通过完全不同的途径来解决这个问题。jdom的处理方式是与dom类似的树操作。而jaxb通过dtd和绑定模式来生成访问xml文档的java代码,将xml映射成了java对象来操作。你可以根据项目的需要和个人喜好来决定采用哪一个。
jdom与jaxb的比较,从本身的特点来看:
1) jdom比jaxb更容易上手。使用jaxb首先要会编写dtd,然后还要会编写绑定模式。jdom没有这样的要求,如果你会java和xml,甚至可以说光是看jdom的javadoc文档就能够使用jdom。
2) jaxb编写好dtd和绑定模式以后,xml文档被映射成了java对象,其数据就是java对象的属性,连数据类型都做好了转换,因此,访问xml文档比jdom要简便,可以说是一劳永逸。
3) jaxb由某个dtd和绑定模式生成的代码只能访问该dtd所约束的文档。如果想要访问其他xml文档,需要再编写dtd和绑定模式。jdom可以处理任何xml文档,包括受约束的和不受约束的。
目前jdom和jaxb都没有正式版本。jdom的最新版本是beta8,jaxb是1.0 early access,其规范版本是0.21。相对而言,jdom更成熟一些。例如jaxb不支持名字空间、不能向xml文档写入处理指令,有时我们需要保留的换行符和首尾空格在jaxb中自动过滤掉了,就连放在<![cdata[ 和 ]]>里面也不能幸免。jdom就没有这些限制。如果说以上的3点比较是jdom和jaxb本身的特点所决定的,几乎不可能改变,那么这里表明,jaxb还需要更多的工作。
(二)获得并安装jdom
在http://jdom.org可以下载jdom的最新版本。以jdom beta8的2进制版本为例。下载后解压缩,jdom的jar文件就是build目录下的文件jdom.jar,将之加入类路径。另外jdom还需要lib目录下那些jar文件如xerces.jar的支持。如果在使用中出现以下错误:
java.lang.nosuchmethoderror
或
java.lang.noclassdeffounderror: org/xml/sax/saxnotrecognizedexception
你需要保证xerces.jar文件在classpath中位于其他xml类,如jaxp或crimson之前,这些类文件,包括以前老版本的xerces,可能不支持sax2.0或dom level 2。于是导致了上面的错误。
(三)一个简单的例子
jdom的处理方式有些类似于dom,但它主要是用sax实现的,你不必担心处理速度和内存的问题。另外,jdom中几乎没有接口,的类全部是实实在在的类,没有类工厂类的。其最重要的一个包org.jdom中主要有以下类:
? attribute
? cdata
? comment
? doctype
? document
? element
? entityref
? namespace
? processinginstruction
? text
数据输入要用到xml文档要通过org.jdom.input包,反过来需要org.jdom.output。如前面所说,关是看api文档就能够使用。
我们的例子读入xml文件examplea.xml,加入一条处理指令,修改第一本书的价格和作者,并添加一条属性,然后写入文件exampleb.xml:
//examplea.xml
<?xml version="1.0" encoding="gbk"?>
<booklist>
<book>
<name>java编程入门</name>
<author>张三</author>
<publishdate>2002-6-6</publishdate>
<price>35.0</price>
</book>
<book>
<name>xml在java中的应用</name>
<author>李四</author>
<publishdate>2002-9-16</publishdate>
<price>92.0</price>
</book>
</booklist>
//testjdom.java
import org.jdom.*;
import org.jdom.output.*;
import org.jdom.input.*;
import java.io.*;
public class testjdom{
public static void main(string args[])throws exception{
saxbuilder sb = new saxbuilder();
//从文件构造一个document,因为xml文件中已经指定了编码,所以这里不必了
document doc = sb.build(new fileinputstream("examplea.xml"));
//加入一条处理指令\
processinginstruction pi = new processinginstruction
("xml-stylesheet","href=\"booklist.html.xsl\" type=\"text/xsl\"");
doc.addcontent(pi);
element root = doc.getrootelement(); //得到根元素
java.util.list books = root.getchildren(); //得到根元素所有子元素的集合
element book = (element)books.get(0); //得到第一个book元素
//为第一本书添加一条属性
attribute a = new attribute("hot","true");
book.setattribute(a);
element author = book.getchild("author"); //得到指定的字元素
author.settext("王五\\"); //将作者改为王五\r
//或 text t = new text("王五\\");book.addcontent(t);
element price = book.getchild("price"); //得到指定的字元素
//修改价格,比较郁闷的是我们必须自己转换数据类型,而这正是jaxb的优势
author.settext(float.tostring(50.0f));
string indent = " ";
boolean newlines = true;
xmloutputter outp = new xmloutputter(indent,newlines,"gbk");
outp.output(doc, new fileoutputstream("exampleb.xml"));
}
};
执行结果exampleb.xml:
<?xml version="1.0" encoding="gbk"?>
<booklist>
<book hot=”true”>
<name>java编程入门</name>
<author>50.0</author>
<publishdate>2002-6-6</publishdate>
<price>35.0</price>
</book>
<book>
<name>xml在java中的应用</name>
<author>李四</author>
<publishdate>2002-9-16</publishdate>
<price>92.0</price>
</book>
</booklist>
<?xml-stylesheet href="booklist.html.xsl" type="text/xsl"?>
在默认情况下,jdom的element类的gettext()这类的方法不会过滤空白字符,如果你需要过滤,用settexttrim() 。
(四)参考文档
1) jdom makes xml easy (http://www.servlets.com/speaking/jdom-javaone.pdf)
2) the java ™ architecture for xml binding user’s guide (http://java.sun.com/xml/jaxb/jaxb-docs.pdf)
3) web services made easier. the java tm apis and architectures for xml, a technical white paper (http://java.sun.com/xml/webservices.pdf )