新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论Java, J2SE, J2ME, J2EE, 以及Eclipse, NetBeans, JBuilder等Java开发环境,还有JSP, JavaServlet, JavaBean, EJB以及struts, hibernate, spring, webwork2, Java 3D, JOGL等相关技术。
    [返回] 计算机科学论坛计算机技术与应用『 Java/Eclipse 』 → 使用JAXP处理XML文件(转贴) 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 7931 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 使用JAXP处理XML文件(转贴) 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     mfc42d 帅哥哟,离线,有人找我吗?
      
      
      等级:大三暑假(ITELS考了6.5分!)(版主)
      文章:65
      积分:882
      门派:XML.ORG.CN
      注册:2004/6/13

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给mfc42d发送一个短消息 把mfc42d加入好友 查看mfc42d的个人资料 搜索mfc42d在『 Java/Eclipse 』的所有贴子 引用回复这个贴子 回复这个贴子 查看mfc42d的博客楼主
    发贴心情 使用JAXP处理XML文件(转贴)

    使用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处理中基础的基础。浊文请读者笑纳。


       收藏   分享  
    顶(0)
      




    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/7/13 20:10:00
     
     antaoran 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:0
      积分:57
      门派:XML.ORG.CN
      注册:2004/4/2

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给antaoran发送一个短消息 把antaoran加入好友 查看antaoran的个人资料 搜索antaoran在『 Java/Eclipse 』的所有贴子 引用回复这个贴子 回复这个贴子 查看antaoran的博客2
    发贴心情 
    谢谢搂主了!给了我很清晰的思路。
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/7/14 0:01:00
     
     javaboy 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:0
      积分:54
      门派:XML.ORG.CN
      注册:2004/7/27

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给javaboy发送一个短消息 把javaboy加入好友 查看javaboy的个人资料 搜索javaboy在『 Java/Eclipse 』的所有贴子 引用回复这个贴子 回复这个贴子 查看javaboy的博客3
    发贴心情 
    收藏
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/7/27 19:55:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 Java/Eclipse 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/9/21 10:49:23

    本主题贴数3,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    93.750ms