SAX解析xml文档

时间:2022-10-31 13:21:51

  上一篇文章中,我们使用了DOM方式解析xml文档,该方式比较符合我们日常思维方式,但是它直接把文档调入内存中,比较耗内存。在这里我们可以用另外一种方式解析xml,这个就是SAX方式。

  SAX即是:Simple API for XML。SAX在概念上与DOM完全不同。它不同于DOM的文档驱动,它是事件驱动的,它并不需要读入整个文档,而文档的读入过程也就是SAX的解析过程。所谓事件驱动,是指一种基于回调(callback)机制的程序运行方法。

  SAX的工作原理:简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。

 
 

  在用SAX解析xml文档时候,在读取到文档开始和结束标签时候就会回调一个事件在读取到其他节点与内容时候也会回调一个事件既然涉及到事件,就有事件源,事件处理器。在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parser()方法来解析XML文档,并产生事件。事件处理器是org.xml.sax包中ContentHander、DTDHander、ErrorHandler,以及EntityResolver这4个接口

  XMLReader通过相应事件处理器注册方法setXXXX()来完成的与ContentHander、DTDHander、ErrorHandler,以及EntityResolver这4个接口的连接,详细介绍请见下表:

SAX解析xml文档

 

  实际上,我们并不需要都继承这4个接口,SDK提供了DefaultHandler类来处理,DefaultHandler类的一些主要事件回调方法如下:

SAX解析xml文档

 

由以上可知,我们需要XmlReader 以及DefaultHandler来配合解析xml。

  SAX解析xml的步骤是:

  1. 首先,实例化一个SAXParserFactory对象:

       SAXParserFactory factory = SAXParserFactory.newInstance();

  2. 然后,通过factory对象获得一个SAXParser对象,该对象就称做SAX 解析器:

    SAXParser saxParser = factory.newSAXParser();

  3. 最后,saxParser对象调用parse方法解析XML文件:

 

    saxParser.parse(File file,DefaultHandler dh) 

 

实例:

books.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <bookstore>
 3 <book category="COOKING">
 4     <title lang="en">Everyday Italian</title>
 5     <author>Giada De Laurentiis</author>
 6     <year>2005</year>
 7     <price>30.0</price>
 8 </book>
 9 <book category="CHILDREN">
10     <title lang="en">Harry Potter</title>
11     <author>J K. Rowling</author>
12     <year>2005</year>
13     <price>29.99</price>
14 </book>
15 <book category="WEB">
16     <title lang="en">Learing XML</title>
17     <author>Erik T. Ray</author>
18     <year>2010</year>
19     <price>48.99</price>
20 </book>
21 </bookstore>

Books抽象类:

 1 package demo;
 2 
 3 /**
 4  * 根据xml “books”文档,新创建Books类
 5  * Created by luts on 2015/12/19.
 6  */
 7 public class Books {
 8     private String category;
 9     private String title;
10     private String language;
11     private String author;
12     private String year;
13     private String price;
14 
15     public String getCategory() {
16         return category;
17     }
18 
19     public void setCategory(String category) {
20         this.category = category;
21     }
22 
23     public String getTitle() {
24         return title;
25     }
26 
27     public void setTitle(String title) {
28         this.title = title;
29     }
30 
31     public String getLanguage() {
32         return language;
33     }
34 
35     public void setLanguage(String language) {
36         this.language = language;
37     }
38 
39     public String getAuthor() {
40         return author;
41     }
42 
43     public void setAuthor(String author) {
44         this.author = author;
45     }
46 
47     public String getYear() {
48         return year;
49     }
50 
51     public void setYear(String year) {
52         this.year = year;
53     }
54 
55     public String getPrice() {
56         return price;
57     }
58 
59     public void setPrice(String price) {
60         this.price = price;
61     }
62 }

BooksSAXHandle:

  1 package demo;
  2 
  3 
  4 
  5 import java.util.ArrayList;
  6 
  7 import org.xml.sax.Attributes;
  8 import org.xml.sax.SAXException;
  9 import org.xml.sax.helpers.DefaultHandler;
 10 
 11 
 12 
 13 public class BookSAXHandler extends DefaultHandler {
 14     String value = null;
 15     Books book = null;
 16     private ArrayList<Books> bookList = new ArrayList<Books>();
 17     public ArrayList<Books> getBookList() {
 18         return bookList;
 19     }
 20 
 21     int bookIndex = 0;
 22     
 23      //用来标识解析开始
 24     @Override
 25     public void startDocument() throws SAXException {
 26         // TODO Auto-generated method stub
 27         super.startDocument();
 28         System.out.println("SAX解析开始");
 29     }
 30     
 31     //用来标识解析结束
 32     @Override
 33     public void endDocument() throws SAXException {
 34         // TODO Auto-generated method stub
 35         super.endDocument();
 36         System.out.println("SAX解析结束");
 37     }
 38     
 39     // 解析xml元素
 40     @Override
 41     public void startElement(String uri, String localName, String qName,
 42             Attributes attributes) throws SAXException {
 43         //调用DefaultHandler类的startElement方法
 44         super.startElement(uri, localName, qName, attributes);
 45         if (qName.equals("book")) {
 46             bookIndex++;
 47             //创建一个book对象
 48             book = new Books();
 49             //开始解析book元素的属性
 50             System.out.println("======================开始遍历某一本书的内容=================");
 51             
 52 //            //已知book元素下属性的名称,根据属性名称获取属性值
 53 //            String value = attributes.getValue("id");
 54 //            System.out.println("book的属性值是:" + value);
 55             //不知道book元素下属性的名称以及个数,如何获取属性名以及属性值
 56             int num = attributes.getLength();
 57             for(int i = 0; i < num; i++){
 58                 System.out.print("book元素的第" + (i + 1) +  "个属性名是:"
 59                         + attributes.getQName(i));
 60                 System.out.println("---属性值是:" + attributes.getValue(i));
 61                 if (attributes.getQName(i).equals("category")) {
 62                     book.setCategory(attributes.getValue(i));
 63                 }    
 64             }
 65         }
 66         
 67         if (qName.equals("title")){
 68             // 已知title元素下属性的名称,根据属性名获取属性值
 69             String lang = attributes.getValue("lang");
 70             System.out.println( "Title的属性值是" + lang);
 71             book.setLanguage(lang);
 72         }
 73         
 74         else if (!qName.equals("title") && !qName.equals("bookstore")) {
 75             System.out.print("节点名是:" + qName + "---");
 76         }
 77     }
 78     
 79     @Override
 80     public void endElement(String uri, String localName, String qName)
 81             throws SAXException {
 82         //调用DefaultHandler类的endElement方法
 83         super.endElement(uri, localName, qName);
 84         //判断是否针对一本书已经遍历结束
 85         if (qName.equals("book")) {
 86             bookList.add(book);
 87             book = null;
 88             System.out.println("======================结束遍历某一本书的内容=================");
 89         }
 90         else if (qName.equals("title")) {
 91             book.setTitle(value);
 92             
 93         }
 94         else if (qName.equals("author")) {
 95             book.setAuthor(value);
 96         }
 97         else if (qName.equals("year")) {
 98             book.setYear(value);
 99         }
100         else if (qName.equals("price")) {
101             book.setPrice(value);
102         }
103         else if (qName.equals("lang")) {
104             book.setLanguage(value);
105         }
106     }
107     
108     
109     @Override
110     public void characters(char[] ch, int start, int length)
111             throws SAXException {
112         // TODO Auto-generated method stub
113         super.characters(ch, start, length);
114         value = new String(ch, start, length);
115         if (!value.trim().equals("")) {
116             System.out.println("节点值是:" + value);
117         }
118     }
119 }

测试解析

 1 package demo;
 2 /**
 3  * 使用SAX解析xml文档
 4  * Created by luts on 2015/12/19.
 5  */
 6 
 7 import java.io.IOException;
 8 import javax.xml.parsers.ParserConfigurationException;
 9 import javax.xml.parsers.SAXParser;
10 import javax.xml.parsers.SAXParserFactory;
11 import org.xml.sax.SAXException;
12 
13 public class SAXTest {
14     public static void main(String[] args){
15         //创建SAXParserFactory实例、
16         SAXParserFactory factory = SAXParserFactory.newInstance();
17        // String xmlPath = "books.xml";
18         try {
19             SAXParser SAXparser = factory.newSAXParser();
20 
21             //获取事件源
22            // XMLReader xmlReader = SAXparser.getXMLReader();
23             //设置处理器,创建一个SAXParserHandler
24             BookSAXHandler handler = new BookSAXHandler();
25 
26            // InputStream inputStream = new FileInputStream(new File(xmlPath));
27 
28             SAXparser.parse("books.xml", handler);
29             System.out.println("----开始解析某一本书的" + handler.getBookList().size()
30                     + " 个属性-------");
31             for (Books book : handler.getBookList()){
32                 System.out.println(book.getCategory());
33                 System.out.println(book.getTitle());
34                 System.out.println(book.getLanguage());
35                 System.out.println(book.getAuthor());
36                 System.out.println(book.getYear());
37                 System.out.println(book.getPrice());
38                 System.out.println("----结束属性解析-----");
39             }
40         }
41         catch (ParserConfigurationException e){
42             e.printStackTrace();
43         }
44         catch (SAXException e){
45             e.printStackTrace();
46         }
47         catch (IOException e){
48             e.printStackTrace();
49         }
50     }
51 }
SAX解析开始
======================开始遍历某一本书的内容=================
book元素的第1个属性名是:category---属性值是:COOKING
节点名是:book---Title的属性值是en
节点值是:Everyday Italian
节点名是:author---节点值是:Giada De Laurentiis
节点名是:year---节点值是:2005
节点名是:price---节点值是:30.0
======================结束遍历某一本书的内容=================
======================开始遍历某一本书的内容=================
book元素的第1个属性名是:category---属性值是:CHILDREN
节点名是:book---Title的属性值是en
节点值是:Harry Potter
节点名是:author---节点值是:J K. Rowling
节点名是:year---节点值是:2005
节点名是:price---节点值是:29.99
======================结束遍历某一本书的内容=================
======================开始遍历某一本书的内容=================
book元素的第1个属性名是:category---属性值是:WEB
节点名是:book---Title的属性值是en
节点值是:Learing XML
节点名是:author---节点值是:Erik T. Ray
节点名是:year---节点值是:2010
节点名是:price---节点值是:48.99
======================结束遍历某一本书的内容=================
SAX解析结束
----开始解析某一本书的3 个属性-------
COOKING
Everyday Italian
en
Giada De Laurentiis
2005
30.0
----结束属性解析-----
CHILDREN
Harry Potter
en
J K. Rowling
2005
29.99
----结束属性解析-----
WEB
Learing XML
en
Erik T. Ray
2010
48.99
----结束属性解析-----