服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

使用jaxp处理xml文件

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的框架轮廓

使用jaxp处理xml文件(图一)

系统是从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的框架轮廓

使用jaxp处理xml文件(图二)

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


:
?

-->

扫描关注微信公众号