【XML】SAX 解析

来源:互联网 发布:编程之魂 闫怀志 编辑:程序博客网 时间:2024/06/01 09:14

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());        }    }}

运行结果:

这里写图片描述

0 0