[分享] sax解析xml文档_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 1683 | 回复: 0   主题: [分享] sax解析xml文档        下一篇 
nengqiang.wang
注册用户
等级:中校
经验:1658
发帖:34
精华:0
注册:1970-1-1
状态:离线
发送短消息息给nengqiang.wang 加好友    发送短消息息给nengqiang.wang 发消息
发表于: IP:您无权察看 2016-1-29 14:31:36 | [全部帖] [楼主帖] 楼主

1 sax 解析 xml

     SAX是Simple API for XML的缩写,它并不是由W3C官方所提出的标准,虽然如此,使用SAX的还是不少,几乎所有的XML解析器都会支持它。与DOM比较而言,SAX是一种轻量型的方法。我们知道,在处理DOM的时候,我们需要读入整个的XML文档,然后在内存中创建DOM树,生成DOM树上 的每个Node对象。当文档比较小的时候,这不会造成什么问题,但是一旦文档大起来,处理DOM就会变得相当费时费力。特别是其对于内存的需求,也将是成 倍的增长,以至于在某些应用中使用DOM是一件很不划算的事(比如在applet中)。这时候,一个较好的替代解决方法就是SAX。

2  事件驱动机制

      SAX 解析xml原理SAX在概念上与DOM完全不同。首先,不同于DOM的文档驱动,它是事件驱动的,也就是说,它并不需要读 入整个文档, 而文档的读入 过程也就 是SAX的解析过 程。所谓事件驱动,是指一种基于回调(callback)机制的程序运行方 法。在XMLReader接 受XML文档,在读 入XML文档的过程中 就进行解析,也就是 说读入文 档的过程 和解析 的过 程是同时进行的,这和DOM区别很大.解析开始之前,需要向XMLReader注册一ContentHandler,也就是相当于一个事件监听器,在ContentHandler中定义了很多方法,比如startDocument(),它定制了当在解析过程中,遇到文档开始时应该处理的事情。当XMLREADER读到合 适的内容,就会抛出相应的事件,并把这个事件的处理权代理给ContentHandler, 调用其相应的方法进行响应。xml文件被Sax解析器载入,由于Sax解析是按照xml文件的顺序来解析,当读入<?xml.....>时,会调用 startDocument()方法,当读入<books>的时候,由于它是个ElementNode,所以会调用 startElement(String uri, String localName, String qName, Attributes attributes) 方法,其中第二个参数就是节点的名称,注意:由于 有些环境不一样,有时候第二个参数有可能为空,所以可以使用第三个参数,因此在解析前,先调用一下看哪个参数能用,第4个参数是这个节点的属性。这里我们 不需要这个节点,所以从<book>这个节点开始,也就是图中1的位置,当读入时,调用startElement(....)方法,由于只有 一个属性category,可以通过attributes.getValue(0)来得到,然后在图中标明2的地方会调用characters(char[] ch, int start, int length)方法,不要以为那里是空白,Sax解析器可不那么认为,Sax解析器会把它认为是一个TextNode。但是这个空白不是我们想要的数据, 我们是想要<title>节点下的文本信息。这就要定义一个记录当上一节点的名称的TAG,在characters(.....)方法中,判断 当前节点是不是title,是再取值,才能取到Everyday Italian。

Java代码 

2.png

3 具体代码

Book.java类

package com.wnq.sk.saxXML01;

import java.util.Set;

public class Book
{
    // 与books.xml中的节点对应
    private String category;
    private String titleLang;
    private String title;
    
    private Set<String> author;// 用sax解析,auther是一个集合,因为一本书可能有读个作者

    private Integer year;
    private Double price;
    
    @Override
    public String toString()
    {
        return "Book [category=" + category + ", titleLang=" + titleLang + ", title=" + title + ", author=" + author
            + ", year=" + year + ", price=" + price + "]";
    }

    public Set<String> getAuthor()
    {
        return author;
    }
    
    public void setAuthor(Set<String> author)
    {
        this.author = author;
    }

    public String getCategory()
    {
        return category;
    }
    
    public void setCategory(String category)
    {
        this.category = category;
    }
    
    public String getTitleLang()
    {
        return titleLang;
    }
    
    public void setTitleLang(String titleLang)
    {
        this.titleLang = titleLang;
    }
    
    public String getTitle()
    {
        return title;
    }
    
    public void setTitle(String title)
    {
        this.title = title;
    }
    
    public Integer getYear()
    {
        return year;
    }
    
    public void setYear(Integer year)
    {
        this.year = year;
    }
    
    public Double getPrice()
    {
        return price;
    }
    
    public void setPrice(Double price)
    {
        this.price = price;
    }
}

解析xml类 SaxReadXMLFile.java

package com.wnq.sk.saxXML01;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SaxReadXMLFile extends DefaultHandler
{
    private List<Book> books = null;
    private Book book = null;
    private Set<String> authors = null;
    private String author = null;
    private String preTag = null;// 记录解析时的上一个节点名称    
    public List<Book> getBooks(String fileName)
        throws Exception
    {
        SAXParserFactory sParserFactory = SAXParserFactory.newInstance();
        SAXParser parser = sParserFactory.newSAXParser();
        SaxReadXMLFile saxReadXMLFile = new SaxReadXMLFile();
        parser.parse(fileName, saxReadXMLFile);
        return saxReadXMLFile.getBooks();
        
    }
    private List<Book> getBooks()
    {
        return books;
    }
    // 开始解析文档
    public void startDocument()
        throws SAXException
    {
        books = new ArrayList<Book>();
        authors = new HashSet<String>();

    }
    // 解析文档结束
    public void endDocument()
        throws SAXException
    {
        System.out.println("文档解析完毕!");
    }
    
    // 开始解析元素
    public void startElement(String uri, String localName, String qName, Attributes attributes)
        throws SAXException
    {
        if ("book".equals(qName))
        {
            book = new Book();
            book.setCategory(attributes.getValue(0));
        }
        if (book != null && "title".equals(qName))
        {
            book.setTitleLang(attributes.getValue("lang"));
        }
        preTag = qName;// 将正在解析的节点名称赋给preTag
    }   
    // 解析元素结束
    public void endElement(String uri, String localName, String qName)
        throws SAXException
    {
        if (book != null && "book".equals(qName))
        {
            books.add(book);
            book.setAuthor(authors);
            book = null;
            authors = new HashSet<String>();
        }
        if (author != null && "author".equals(qName))
        {
            authors.add(author);
            author = null;
        }
        preTag = null;
        /**
         * 当解析结束时置为空。这里很重要,例如,当图中画3的位置结束后,会调用这个方法 ,如果这里不把preTag置为null,根据startElement(....)方法,preTag的值还是book,当文档顺序读到图
         * 中标记4的位置时,会执行characters(char[] ch, int start, int length)这个方法,而characters(....)方
         * 法判断preTag!=null,会执行if判断的代码,这样就会把空值赋值给book,这不是我们想要的。
         */
    }  
    public void characters(char[] ch, int start, int length)
        throws SAXException
    {
        if (preTag != null)
        {
            String content = new String(ch, start, length);
            if ("title".equals(preTag))
            {
                book.setTitle(content);
            }
            
            else if ("author".equals(preTag))
            {
                author = content;
            }
            else if ("year".equals(preTag))
            {
                book.setYear(Integer.valueOf(content));
            }
            else if ("price".equals(preTag))
            {
                book.setPrice(Double.valueOf(content));
            }
        }
    }

}

测试类 SaxTest.java

package com.wnq.sk.saxXML01;
import java.util.List;
public class SaxTest
{   
    public static void main(String[] args)
        throws Throwable
    {
        SaxReadXMLFile sax = new SaxReadXMLFile();
        String fileName = "books.xml";
        List<Book> books = sax.getBooks(fileName);
        for (Book book : books)
        {
            System.out.println(book.toString());
        }
    }
}

4 运行结果


a.png


该贴被蜀山战纪编辑于2016-2-1 10:43:29


人们都向往和寻找快乐,其实快乐就是一种心情,秘密隐藏于人的心中。快乐从不曾远离我们,而是我们远离了快乐。原本单纯的心,一旦复杂起来,快乐和幸福就 会远离而去,烦恼和忧愁就会随之而来。






赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论