DOM和SAX的XML解析

Posted on 2007-04-17 23:33 与心牵手 阅读(3314) 评论(0)  编辑  收藏 所属分类: java学习
     解析xml有四种方法:DOM,SAX,DOM4j,JDOM.
     我们主要学了两种:DOM和SAX.
     DOM适于解析比较简单的XML而SAX则适于解析较复杂的XML文件。各有各的好。

     DOM和SAX的不同:
     1. DOM是基于内存的,不管文件有多大,都会将所有的内容预先装载到内存中。从而消耗很大的内存空间。而SAX是基于事件的。当某个事件被触发时,才获取相应的XML的部分数据,从而不管XML文件有多大,都只占用了少量的内存空间。
     2. DOM可以读取XML也可以向XML文件中插入数据,而SAX却只能对XML进行读取,而不能在文件中插入数据。这也是SAX的一个缺点。
     3.SAX的另一个缺点:DOM我们可以指定要访问的元素进行随机访问,而SAX则不行。SAX是从文档开始执行遍历的。并且只能遍历一次。也就是说我们不能随机的访问XML文件,只能从头到尾的将XML文件遍历一次(当然也可以中间截断遍历)。

     DOM和SAX对XML文件的解析:
     1.  在使用DOM解析XML时,我们首先需要通过DocumentBuilderFactory这个类得到一个工厂的API,使应用程序能够从XML文档获取 生成对象树的解析器。通过此类的 newinstance() 方法我们可以获得此类的一个新实例。然后通过创建DocumentBuilder的实例使其从XML文档中获取DOM文档实例。 DocumentBuilder的实例我们可以通过DocumentBuilderFactory类的newDocumentBuilder()方法得 到。之后就通过DocumentBuilder类的parse(InputStream is)方法将给定文件的内容解析为一个XML文档,并且返回一个新的DOM Document 对象。具体步骤如下:

        File file = new File("D:\\编码\\xml\\domxml.xml");
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document dt = db.parse(file);
        } catch (Exception e) {
            // TODO 自动生成 catch 块
            e.printStackTrace();
        }

这 时我们就可以开始解析文档了。通过NodeList,Node分别可以得到节点列表和节点了。NodeList可以由Document对象的 getElementsByTagName("元素名称");来得到你想得到的哪个元素的节点列表。由NodeList的item(整形参数)方法来得到 节点。通过Node的getFirstChild().getNodeValue()方法可以得到文本节点值。方法如下:

        NodeList nl = dt.getElementsByTagName("star");//star为一个元素名称
        Node nd = nl.item(0);//得到节点列表 nl 的第一个节点。

此外我们可以通过循环来取得节点列表中所有的节点。
当一个元素有子元素时我们可以通过父节点列表取得子节点列表。方法如下:

       NodeList nlF = dt.getElementsByTagName("star"); //star为一个元素名称
       Node ndF = nl.item(0); //得到节点列表 nl 的第一个节点。
       for(int i = 0; i < nlF.getLength(); i ++)
        {
            Node ndF = nlF.item(i); //取得元素的所有节点
            NodeList nlC = ndF.getChildNodes(); //取得子元素的节点列表
            for(int j = 0; j < nlC.getLength(); j ++)
            {
                Node ndC = nlC.item(j);
                if(ndC.getNodeType()==ndC.ELEMENT_NODE){
                    String str = ndC.getFirstChild().getNodeValue(); //取得文本节点
                    System.out.println(str); //打印出文本节点
                    }
                }
            }
        }
/** 注意*/ 由于通过父节点列表得到子节点列表而得到的子元素节点包含了空格所占有的节点,所以这里需要用if(ndC.getNodeType()== ndC.ELEMENT_NODE)来做判断是否取得的是元素节点(ndC.getNodeType()为节点类型,ndC.ELEMENT_NODE节 点类型为元素节点(注:文本节点是元素节点的一个子节点))。

     2. 最常用的SAX解析器是JAXP。JAXP是作为javax.xml包提供的,包括SAX和DIM的Java接口以及Java XML解析器必须是实现的基本接口和类。通过继承DefaultHandle类实现此类方法则可以遍历XML文档:

         void startDocument()
         //接收文档开始的通知
         void endDocument()
         //接收文档结束的通知
         void startElement(String uri,String localName,String qName, Attributes attributes)
         //接收元素开始的通知
         void endElement(String uri,String localName, String qName)
         //接收元素结束的通知
         void characters(char[] ch,int start, int length)
         //接收字符数据的通知

     获取SAX解析器的方法和DOM相似。获取SAX解析器的方法如下:
         
         SAXParserFactory spf = SAXParserFactory.newInstance(); //得到工厂的一个新实例
        try {
           
            SAXParser sp = spf.newSAXParser(); //得到SAXParser类的实例
            File file = new File("E:\\yuxin_document\\xml\\mytest.xml"); //XML文件
            SaxHandle handle = new SaxHandle(); //SaxHandle 这是一个继承了DefaultHandle的实现了XML遍历                                                             的一个自定义的类
            sp.parse(file, handle); //解析一个XML文档
        } catch (ParserConfigurationException e) {
            // TODO 自动生成 catch 块
            e.printStackTrace();
        } catch (SAXException e) {
            // TODO 自动生成 catch 块
            e.printStackTrace();
        } catch (IOException e) {
            // TODO 自动生成 catch 块
            e.printStackTrace();
        }

    ** 为了能够清晰的显示出XML中的内容,我们还需要将解析后取得的内容显示在GUI上。一般用表格来实现。
    
     SAX和DOM的合用
     我们可以用SAX来解析XML再用DOM来将解析后的数据写成一个XML文件.
     使用DOM创建一个XML文件的方法如下:
    首先,需要得到一个写入XML文件的Document对象:
        Document doc = DocumentHelper.createDocument();
    然后就可以在这个文档中添加内容了,如:
        Element root = doc.addElement("root");  //写入一个根元素"root"
        Element el = root.addElement("子元素"); //在根元素中写入一个子元素

    当将所有信息写入文档后则可以将Document写入XML文件中了,方法如下:

            FileWriter file = new FileWriter("D:\\doc.xml"); //得到一个文件输出流对象
        document.write(file); //将文档内容写入文件中(document是上面所得到的Document
对象)
    这是一种简单的写入方式
    如果你想格式化XML文件则可以这样做:

        FileOutputStream fos = new FileOutputStream("D:\\doc.xml"); //

得到一个文件输出流对象
        OutputFormat format = OutputFormat.createPrettyPrint();  //得到OutputFormat

格式化类的对象
        XMLWriter xw = new XMLWriter(fos,format);  //得到XML输出流XMLWriter接口的一

个实例
        xw.write(doc);  //将文档写入XML
        fos.close();  //关闭输出流
        xw.close();