【XML】SAX 解析

1. XML SAX解析

1.1 SAX解析器

SAX(Simple API for XML)是一种XML文档解析标准

  • 是一个公共的基于事件的解析器
  • SAX作为接口,是事件驱动型XML解析的标准接口,对文档进行顺序扫描,当扫描到document开始,element开始与结束,document结束等地方时,通知事件处理函数作出相应的动作。
  • 与DOM相比,SAX占用的系统资源更少

1.2 SAX API

事件类型:
  1. 文档处理事件
  2. 元素处理事件
  3. 元数据通常有单独的的事件处理
解析步骤:
  1. 创建事件处理程序:编写ContenHandler实现类,继承DefaultHandler,采用adapter模式
  2. 创建SAX解析器
  3. 将事件处理程序分配到解析器
  4. 对文档进行解析,将每个事件发送给事件处理程序
关键代码:

常用接口ContentHandler:
- 常用的SAX事件处理的方法:
- void startDocument()
- void endDucument()
- void startElement(String uri,String localName.StringqName,Attibutes atts)
- void endElement(String uri,String localName,StringqName)
- void characters(char[] ch, int start, int length)
- 当XML解析器开始解析文档时,会调用ContentHandler接口中的相应方法来响应事件,这些方法被称为回调方法。

工厂类:SAXParserFactory
- 定义了工厂API接口,供其他程序配置和获取基于SAX的解析器。
- factory=SAXParserFactory.newInstance(): 创建工厂实例
- SAXHandler=factory.newSAXParser():创建SAX解析器。

抽象类:SAXParser
- 该类的实例对象需要同过工厂类SAXParserFactory获取
- 定义了不同参数列表的parse方法将xml文件通过定义好的事件处理器解析成标签元素对象。

类图关系:

这里写图片描述

Book类是对XML元素面向对象的映射,SAX解析之后,将把元素内容放在Book类的对象book中去。

MySaxHandler是事件处理器,用来识别XML文档中的标签,通过定义标签的事件触发动作完成识别。识别得到的book对象放在List容器中以便管理调用

MySaxParser是对SAX解析器的定制:需要的步骤是:
1. 创建SAXParserFactory工厂类
2. 用工厂对象实例化SAXParse对象parser
3. 将要处理的XML文档和事件处理器交给parser完成XML解析。
上述步骤可以接口的抽象方法parseXML。
4. 编写程序入口:实例化MySaxParser对象,执行其中的parseXml实现方法。

2. 实践分析

我们以bookStore的场景建立一个XML文档,通过SAX解析读取文档内容。

XML文档:

<?xml version="1.0" standalone="yes" encoding="UTF-8"?>
<bookStore>
    <book bookNo="001">
        <title>Java Coding Language</title>
        <author>Jack</author>
        <price>40</price>
    </book>
        <book bookNo="002">
        <title>Android Coding Language</title>
        <author>Jack</author>
        <price>70</price>
    </book>
</bookStore>

XML映射的元素类

package xmlSAXDemo;

//从BookStore.xml解析得到的信息会创建成本类的实例对象。
public class Book {
    private String bookNo;
    private String title;
    private String auther;
    private double price;
    @Override
    public String toString() {
        return "Book [bookNo=" + bookNo + ", title=" + title + ", auther="
                + auther + ", price=" + price + "]";
    }

    public Book() {
        super();
    }

    public Book(String bookNo, String title, String auther, double price) {
        super();
        this.bookNo = bookNo;
        this.title = title;
        this.auther = auther;
        this.price = price;
    }

    public String getBookNo() {
        return bookNo;
    }

    public void setBookNo(String bookNo) {
        this.bookNo = bookNo;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuther() {
        return auther;
    }

    public void setAuther(String auther) {
        this.auther = auther;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

}

创建事件处理程序

package xmlSAXDemo;

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MySaxHandler extends DefaultHandler {
    private String tag;
    private Book book;
    private List<Book> bookList;

    public List<Book> dump(){
        return bookList;
    }

    /*
     * 回调方法的改写
     * @see org.xml.sax.helpers.DefaultHandler#startDocument()
     */
    @Override
    public void startDocument() throws SAXException {
        // TODO Auto-generated method stub
        super.startDocument();
        bookList=new ArrayList<Book>();
    }

    @Override
    public void endDocument() throws SAXException {
        // TODO Auto-generated method stub
        super.endDocument();
    }

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        // TODO Auto-generated method stub
        super.startElement(uri, localName, qName, attributes);
        //tag内容初始化
        tag=qName;
        //book对象初始化
        if(qName.equals("book")){
            book=new Book();
            String bookNo=attributes.getValue("bookNo");
            book.setBookNo(bookNo);
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        // TODO Auto-generated method stub
        super.endElement(uri, localName, qName);
        if(qName.equals("book")){
            bookList.add(book);
            book=null;//book对象格式化
        }
        tag=null;//tag内容格式化
    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        // TODO Auto-generated method stub
        super.characters(ch, start, length);
        //这些内容的标签解析放在startElement中去做也是可以的。
        if(tag!=null){
            String str=new String(ch,start,length).trim();
            if(tag.equals("title")){
                book.setTitle(str);
            }if(tag.equals("author")){
                book.setTitle(str);
            }if(tag.equals("price")){
                book.setPrice(Double.parseDouble(str));
            }   
        }
    }

}

创建SAX解析器,并将事件处理程序分配到解析器

package xmlSAXDemo;

import java.util.List;

public interface XmlParse {
    //从指定的XML文件中返回书的列表
    public List<Book> parseXml(String fileName);
}
package xmlSAXDemo;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

public class MyParser implements XmlParse {

    public List<Book> parseXml(String fileName) {
        List<Book> list=new ArrayList<Book>();
        SAXParserFactory factory=SAXParserFactory.newInstance();
        MySaxHandler handler=null;
        //将事件处理程序分配到解析器
        try {
            SAXParser parser=factory.newSAXParser();
            InputStream is=new FileInputStream(fileName);
            handler=new MySaxHandler();
            parser.parse(is,handler);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        list=handler.dump();
        return list;

    }

    public static void main(String[] args){
        XmlParse parser=new MyParser();//接口的引用变量
        List<Book> list=parser.parseXml("books.xml");//调用接口实现方法,XML文档要放在当前项目的根目录下。
        for(Book book:list){
            System.out.println(book.toString());
        }
    }

}

运行结果:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值