分享

使用JAXP处理XML文件

 bluecrystal 2006-07-26

使用JAXP处理XML文件

作者:贾波

作者简介

贾波,程序员,您可以通过mosaic@hotmail.com与他联系。

简介

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./xml/jaxp/docs.html

技术论坛
 >>  Java 论坛
 >>  Solaris 论坛
 >>  Sun Java Enterprise System 论坛
培训中心
 >>  考前自测
 >>  技术培训服务
 >>  技术认证方案
技术专题
 >>  Java 专题
 >>  Solaris 专题
 >>  Sun Java Enterprise System 专题
资源中心
 >>  参考文献
 >>  共享代码
 >>  成功案例
 >>  白皮书
 >>  常见问答
 >>  下载中心
 >>  产品简介
 >>  编程技巧

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多