jaxp是java api for xml processing的缩写。jaxp api主要的部分在javax.xml.parsers 这个包中。在这个包中,向用户提供了两个最重要的工厂类,saxparserfactory 和documentbuilderfactory,相应地,提供了saxparser 和documentbuilder两个类。
sax是由xml-dev定义的;dom是由w3c定义的。让我们来看看这些api库。
- javax.xml.parsers
jaxp api, 定义个sax和dom的一个通用接口 - org.w3c.dom
定义了dom中的所有组件 - org.xml.sax
定义了sax的所有api - javax.xml.transform
定义了xslt api,使用它,你可以将xml转化为一般的可视的页面。
sax指一种"事件驱动"的处理方式,他对xml文件连续地一个对象一个对象地操作,由于它的这个特点,所以它可以用于服务器端或者对速度有特殊要求的地方。
相比较而言dom是个使用起来更简单些。他是将所有个xml数据全部读到内存里面,然后使用"树"结构将这些数据组织起来,用户可以对xml的数据进行任意的操作。
至于xslt,我们在这里就不介绍太多,如果感兴趣请参考相应的资料。我们还是先看看sax。
sax
sax的框架轮廓

系统是从saxparserfactory产生parser的实例开始的。一个parser中包含了一个saxreader对象,当这个parser调用parse方法的时候,这个reader就调用回调方法已实现这个应用;而这些方法呢?是定义在contenthandler,errorhandler,dtdhandler and entityresolver接口中的。
以下是对sax api库的概述:
- saxparserfactory
saxparserfactory是一个根据系统属性生成parser实例的一个对象。 - saxparser
saxparser是一个定义了不同种类的parser()方法的接口。一般而言,你向parser传xml数据后,使用defaulthandler再来处理,系统就会调用一些合适的方法来处理xml文件,这样的一种处理方法是最为简单的。 - saxreader
saxparser包含了一个saxreader,通常你是不需要关心它的,但是当你要使用saxreader的getxmlreader()方法的时候,你就需要配置他。简言之,saxparser就是一个与sax事件通讯的处理器,这样,你就可以使用自定义的handler。 - defaulthandler
defaulthandler 实现了 contenthandler, errorhandler, dtdhandler, 和entityresolver 接口 (当然其中有一些null方法), 如果你感兴趣的话,你可以在你的程序中重载它。 - contenthandler
当读到xml的tag时,就会调用到这个接口中的startdocument, enddocument, startelement, 和 endelement 方法。同时,这个接口还定义了characters 和processinginstruction,方法,分别地,当parser遇到xml的element或者inline processing instruction的时候调用。 - errorhandler
当遇到不同类型的错误的时候分别调用相应的"错误"方法,这些方法包括:error,fatalerror和warning。 - dtdhandler
该接口所定义的方法只用在处理dtd信息的时候。 - entityresolver
给接口中的resolveentity方法只在parser遇到uri标识数据的时候才调用。
更详细地api介绍,请参看sax的官方api文档。
例子:
在我们这个例子中,我们处理一个xml文件,然后将其值set到对象中。这是一个非常常用的使用情况。以下就是我们需要处理的xml文件。
test.xml<?xml version="1.0" ?> <customers> <customer> <id>#001</id> <name>micke</name> <address>najing</address> </customer> <customer> <id>#002</id> <name>car</name> <address>suzhou</address> </customer> <customer> <id>#003</id> <name>jimmy</name> <address>chengdu</address> </customer> <customer> <id>#004</id> <name>henry</name> <address>xi'an</address> </customer></customers>
这是一个非常简单的xml文件,customers中间有数个customer,每一个customer中包含三个属性id, name, address。
根据这个xml文件,我们将date object设置如下。
/* * customers.java * create @ 2004-4-27 22:04:45 * by jiabo */import java.util.*;/** * customers * create @ 2004-4-27 22:04:45 * by jiabo */public class customers { private vector customers; public customers() { customers = new vector(); } public void addcustomer(customer customer) { customers.add(customer); } public string tostring() { string newline = system.getproperty("line.separator"); stringbuffer buf = new stringbuffer(); for (int i = 0; i < customers.size(); i++) { buf.append(customers.elementat(i)).append(newline); } return buf.tostring(); }}class customer { private string id; private string name; private string address; /** * @return */ public string getaddress() { return address; } /** * @return */ public string getid() { return id; } /** * @return */ public string getname() { return name; } /** * @param string */ public void setaddress(string string) { address = string; } /** * @param string */ public void setid(string string) { id = string; } /** * @param string */ public void setname(string string) { name = string; } public string tostring(){ return "customer: id='" + id + "' name='" + name + "' address='" + address + "'"; }}接下来是xml的处理器。
/* * test.java * created on 2004-4-10 * by jiabo */import java.util.*;import org.xml.sax.*;import org.xml.sax.helpers.defaulthandler;/** * test * create on 2004-4-10 19:20:27 * by jiabo */public class unmarshaller extends defaulthandler { private customers customers; private stack stack; private boolean isstackreadyfortext; private locator locator; /** * init */ public unmarshaller() { stack = new stack(); isstackreadyfortext = false; } /** * @return customers */ public customers getcustomers() { return customers; } /** * callbacks */ public void setdocumentlocator(locator rhs) { locator = rhs; } //========================================== // sax documenthandler methods //========================================== public void startelement( string uri, string sname, string qname, attributes attrs) { isstackreadyfortext = false; if (sname.equals("customers")) { stack.push(new customers()); } else if (sname.equals("customer")) { stack.push(new customer()); } else if ( sname.equals("id") || sname.equals("name") || sname.equals("address")) { stack.push(new stringbuffer()); isstackreadyfortext = true; } else { } } public void endelement(string namespaceuri, string sname, string qname){ isstackreadyfortext = false; object temp = stack.pop(); if (sname.equals("customers")) { customers = (customers) temp; } else if (sname.equals("customer")) { ((customers) stack.peek()).addcustomer((customer) temp); } else if (sname.equals("id")) { ((customer) stack.peek()).setid(temp.tostring()); } else if (sname.equals("name")) { ((customer) stack.peek()).setname(temp.tostring()); } else if (sname.equals("address")) { ((customer) stack.peek()).setaddress(temp.tostring()); } } public void characters(char[] data, int start, int length) { if (isstackreadyfortext == true) { ((stringbuffer) stack.peek()).append(data, start, length); } else { } }}在这里我们处理xml文件的思路非常简单,就是使用一个栈,遇到"<"表示element的开始,然后就看与我们既定的data object的名字是否相符合,符合就new一个该对象,并将其压栈;不符合就什么都不做,sax的处理框架就会自己去处理下一个element。而当遇到"/>"的时候我们还是看的他名字与dataobject的名字是否相符,相符合的话就出栈,然后set进对象里面。如此循环,就处理完了我们上面那个简单得xml文件。
我们需要做的事情就只有这些。其他如何处理的,handler回自己调用相应的startelement,endelement等方法去处理。
以下是程序的入口:
/* * main.java * create @ 2004-4-27 22:18:41 * by jiabo */import java.io.*;import javax.xml.parsers.*;import org.xml.sax.*;/** * main * create @ 2004-4-27 22:18:41 * by jiabo */public class main { public static void main(string args[]) { customers customers = null; if (args.length != 1) { system.err.println("usage: cmd filename"); system.exit(1); } try { unmarshaller handler = new unmarshaller(); saxparserfactory factory = saxparserfactory.newinstance(); saxparser saxparser = factory.newsaxparser(); file file = new file(args[0]); inputsource src = new inputsource(new fileinputstream(file)); saxparser.parse( src ,handler); customers = handler.getcustomers(); } catch (throwable t) { t.printstacktrace(); } system.out.println(customers); }}如前面所述,通过一个工厂方法得到一个saxparser的实例,然后就可以编译这个xml文件了。这样你就可以得到如下结果:
customer: id ='#001' name='micke' address='najing' customer: id ='#002' name='car' address='suzhou' customer: id ='#003' name='jimmy' address='chengdu' customer: id ='#004' name='henry' address='xi'an'
sax的系统框架中还有其他得好些方法,读者不妨试试他们是如何使用的,这对以后实战处理xml文件会有很大的方便。
dom
dom的框架轮廓

dom的api概述
一般而言,我们使用javax.xml.parsers.documentbuilderfactory来得到documentbuilder的一个实例。当然你也可以documentbuilder newdocument()方法来得到一个实现了org.w3c.dom.document接口的空的document对象。
- documentbuilderfactory
它可以根据系统属性生成一个builder实例。 - documentbuilder
用于处理生成document。
更详细地api介绍,请参看dom的官方api文档。
所以我们可以简单地这样:documentbuilderfactory factory =documentbuilderfactory.newinstance();documentbuilder builder = factory.newdocumentbuilder();document document = builder.parse("test.xml");就可以出得到一个document。实例:
我们依然处理test.xml。和sax一样,也需要有paser。其实思路是非常简单而明晰的,上面我们已经说过,dom是将所有的xml读入内存,以树的结构来处理的,所以呢,对节点的分析就是解决问题的关键,如下。
代码如下:
/* * test.java * created on 2004-4-10 * by jiabo */import org.w3c.dom.*;/** * test * create on 2004-4-10 19:20:27 * by jiabo */public class unmarshaller { public unmarshaller() { } public customers unmarshallcustomers(node rootnode) { customers customers = new customers(); node n; nodelist nodes = rootnode.getchildnodes(); for (int i = 0; i < nodes.getlength(); i++) { n = nodes.item(i); if (n.getnodetype() == node.element_node) { if ("customer".equals(n.getnodename())) { customers.addcustomer(unmarshallcustomer(n)); } else { } } } return customers; } public customer unmarshallcustomer(node customernode) { customer customer = new customer(); node n; nodelist nodes = customernode.getchildnodes(); for (int i = 0; i < nodes.getlength(); i++) { n = nodes.item(i); if ("id".equals(n.getnodename())) { customer.setid(unmarshalltext(n)); } else if ("name".equals(n.getnodename())) { customer.setname(unmarshalltext(n)); } else if ("address".equals(n.getnodename())) { customer.setaddress(unmarshalltext(n)); } } return customer; } public string unmarshalltext(node textnode) { stringbuffer buf = new stringbuffer(); node n; nodelist nodes = textnode.getchildnodes(); for (int i = 0; i < nodes.getlength(); i++) { n = nodes.item(i); if (n.getnodetype() == node.text_node) { buf.append(n.getnodevalue()); } else { } } return buf.tostring(); }}下面是如何驱动dom去处理xml文件部分。还是先得到一个documentbuilderfactory工厂,在用他生成一个documentbuilder一个实例,在调用parse方法就可以分析这个xml文件了。
/* * main.java * create @ 2004-4-27 22:18:41 * by jiabo */import java.io.*;import org.w3c.dom.*;import javax.xml.parsers.*;/** * main * create @ 2004-4-27 22:18:41 * by jiabo */public class main { public static void main(string args[]) { customers customers = null; document doc = null; if (args.length != 1) { system.err.println("usage: cmd filename"); system.exit(1); } try { unmarshaller handler = new unmarshaller(); documentbuilderfactory factory = documentbuilderfactory.newinstance(); documentbuilder builder = factory.newdocumentbuilder(); doc = builder.parse( new file(args[0]) ); customers = handler.unmarshallcustomers(doc.getdocumentelement()); } catch (throwable t) { t.printstacktrace(); } system.out.println(customers); }}总结:
这里是对xml处理的一个简介,力求简介,明了,以最快的速度帮助读者入门,所以,没有完整地使用库中的方法。
xml文件的处理,对于webservice是基础的基础。而sax和dom又是xml处理中基础的基础。浊文请读者笑纳。
参考:
http://java.sun.com/xml/jaxp/docs.html
:
? -->
闽公网安备 35060202000074号