天天看点

[Java开发之路](11)SAX解析XML文档

1. 简介

dom解析功能强大,可增删改查,操作时会将xml文档读到内存,因此适用于小文档;

sax解析是从头到尾逐行逐个元素解析,修改较为不便,但适用于只读的大文档;

sax采用事件驱动的方式解析xml。套用网友的解释:如同在电影院看电影一样,从头到尾看一遍,不能回退(dom可来来回回读取),在看电影的过程中,每遇到一个情节,都会调用大脑去接收处理这些信息。sax也是相同的原理,每遇到一个元素节点,都会调用相应的方法来处理。在sax的解析过程中,读取到文档开头、文档结尾,元素的开头和元素结尾都会调用相应方法,我们可以在这些方法中进行相应事件处理。

对应方法:

<code>public void startdocument() throws saxexception {</code>

<code>}</code>

<code>public void enddocument() throws saxexception {</code>

<code>public void startelement(string uri, string localname, string qname, attributes attributes) throws saxexception {</code>

<code>public void endelement(string uri, string localname, string qname) throws saxexception {</code>

我们还需一个方法来处理元素节点中间的文本节点(我们常误以为元素节点的文本值)

<code>public void characters(char[] ch, int start, int length) throws saxexception {</code>

2. 解析

解析步骤:

(1)通过saxparserfactory的静态方法newinstance()方法获取saxparserfactory实例对象factory

<code>saxparserfactory factory = saxparserfactory.newinstance();</code>

(2)通过saxparserfactory实例的newsaxparser()方法返回saxparser实例parser

<code>saxparser parser = factory.newsaxparser();</code>

(3)创建一个类继承defaulthandler,重写其中的一些方法进行业务处理

<code>package com.qunar.handler;</code>

<code>import org.xml.sax.attributes;</code>

<code>import org.xml.sax.saxexception;</code>

<code>import org.xml.sax.helpers.defaulthandler;</code>

<code>public class saxparserhandler extends defaulthandler{</code>

<code></code>

<code>// 用来标示解析开始</code>

<code>@override</code>

<code>// 用来标示解析结束</code>

<code>// 用来遍历xml文件的开始标签</code>

<code>super.startelement(uri, localname, qname, attributes);</code>

<code>// 用来遍历xml文件的结束标签</code>

<code>super.endelement(uri, localname, qname);</code>

<code>super.characters(ch, start, length);</code>

(4)创建handler类对象实例

<code>// 定义saxparserhandler对象</code>

<code>saxparserhandler handler = new saxparserhandler();</code>

(5)解析xml文档

<code>saxparser.parse(path, handler);</code>

以下代码均使用本xml文档:

<code>&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;bookstore&gt;</code>

<code>&lt;book category="java"&gt;</code>

<code>&lt;title lang="chi"&gt;java多线程编程核心技术&lt;/title&gt;</code>

<code>&lt;author&gt;高洪岩&lt;/author&gt;</code>

<code>&lt;year&gt;2015&lt;/year&gt;</code>

<code>&lt;price&gt;69.00&lt;/price&gt;</code>

<code>&lt;/book&gt;</code>

<code>&lt;book category="c++"&gt;</code>

<code>&lt;title lang="en"&gt;effective c++: 55 specific ways to improve your programs and designs&lt;/title&gt;</code>

<code>&lt;author&gt;scott meyers&lt;/author&gt;</code>

<code>&lt;year&gt;2006&lt;/year&gt;</code>

<code>&lt;price&gt;58.00&lt;/price&gt;</code>

<code>&lt;book category="web"&gt;</code>

<code>&lt;title lang="en"&gt;learning xml&lt;/title&gt;</code>

<code>&lt;author&gt;erik t. ray&lt;/author&gt;</code>

<code>&lt;year&gt;2016&lt;/year&gt;</code>

<code>&lt;price&gt;39.95&lt;/price&gt;</code>

<code>&lt;/bookstore&gt;</code>

3. 具体实例:

<code> </code>

<code>private int bookindex = 0;</code>

<code>system.out.println("sax解析开始...");</code>

<code>system.out.println("sax解析结束...");</code>

<code>// 调用defaulthandler类的startelement方法</code>

<code>// 开始解析book元素节点</code>

<code>if(qname.equals("book")){</code>

<code>++ bookindex;</code>

<code>system.out.println("开始解析第" + bookindex + "本书...");</code>

<code>// 已知book元素节点下的属性名称,根据属性名称获取属性值</code>

<code>/*string value = attributes.getvalue("category");</code>

<code>system.out.println("value-&gt;"+value);*/</code>

<code>// 不知道book元素节点下的属性名称以及个数</code>

<code>int size = attributes.getlength();</code>

<code>for(int i = 0;i &lt; size;++i){</code>

<code>system.out.println(attributes.getqname(i) + ":" + attributes.getvalue(i));</code>

<code>}//for</code>

<code>}//if</code>

<code>else if(!qname.equals("bookstore")){</code>

<code>system.out.print(qname + ":");</code>

<code>}//else</code>

<code>// 判断一本书是否解析完</code>

<code>system.out.println("结束解析第" + bookindex + "本书...");</code>

<code>string text = new string(ch, start, length);</code>

<code>if(!text.trim().equals("")){</code>

<code>system.out.println(text);</code>

<code>package com.qunar.xml;</code>

<code>import java.io.ioexception;</code>

<code>import javax.xml.parsers.parserconfigurationexception;</code>

<code>import javax.xml.parsers.saxparser;</code>

<code>import javax.xml.parsers.saxparserfactory;</code>

<code>import com.qunar.handler.saxparserhandler;</code>

<code>/**</code>

<code>* sax方式解析xml文档</code>

<code>* @author sjf0115</code>

<code>*</code>

<code>*/</code>

<code>public class saxxmlcode {</code>

<code>public static void main(string[] args) {</code>

<code>string path = "d:\\bookstore.xml";</code>

<code>try {</code>

<code>// 通过saxparserfactory的静态方法newinstance()方法获取saxparserfactory实例对象factory</code>

<code>// 通过saxparserfactory实例的newsaxparser()方法返回saxparser实例parser</code>

<code>saxparser saxparser = factory.newsaxparser();</code>

<code>// 解析xml文档</code>

<code>} catch (parserconfigurationexception e) {</code>

<code>e.printstacktrace();</code>

<code>} catch (saxexception e) {</code>

<code>} catch (ioexception e) {</code>

运行结果:

sax解析开始...

开始解析第1本书...

category:java

title:java多线程编程核心技术

author:高洪岩

year:2015

price:69.00

结束解析第1本书...

开始解析第2本书...

category:c++

title:effective c++: 55 specific ways to improve your programs and designs

author:scott meyers

year:2006

price:58.00

结束解析第2本书...

开始解析第3本书...

category:web

title:learning xml

author:erik t. ray

year:2016

price:39.95

结束解析第3本书...

sax解析结束...

4. 解析并储存于对象中

<code>package com.qunar.bean;</code>

<code>* book实体类</code>

<code>public class book {</code>

<code>private string category;</code>

<code>private string title;</code>

<code>private string author;</code>

<code>private string year;</code>

<code>private string price;</code>

<code>private string lang;</code>

<code>public string getcategory() {</code>

<code>return category;</code>

<code>public void setcategory(string category) {</code>

<code>this.category = category;</code>

<code>public string gettitle() {</code>

<code>return title;</code>

<code>public void settitle(string title) {</code>

<code>this.title = title;</code>

<code>public string getauthor() {</code>

<code>return author;</code>

<code>public void setauthor(string author) {</code>

<code>this.author = author;</code>

<code>public string getyear() {</code>

<code>return year;</code>

<code>public void setyear(string year) {</code>

<code>this.year = year;</code>

<code>public string getprice() {</code>

<code>return price;</code>

<code>public void setprice(string price) {</code>

<code>this.price = price;</code>

<code>public string getlang() {</code>

<code>return lang;</code>

<code>public void setlang(string lang) {</code>

<code>this.lang = lang;</code>

<code>public string tostring() {</code>

<code>return "category:" + category + " lang:" + lang + " title:" + title + " author:" + author + " year:" + year + " price:" + price;</code>

<code>import java.util.arraylist;</code>

<code>import java.util.list;</code>

<code>import com.qunar.bean.book;</code>

<code>private book book;</code>

<code>// 节点文本内容</code>

<code>private string text;</code>

<code>private list&lt;book&gt; booklist = new arraylist&lt;book&gt;();</code>

<code>public list&lt;book&gt; getbooklist() {</code>

<code>return booklist;</code>

<code>// 创建一个book对象</code>

<code>book = new book();</code>

<code>string attr = attributes.getqname(i);</code>

<code>// 属性category</code>

<code>if(attr.equals("category")){</code>

<code>book.setcategory(attributes.getvalue(i));</code>

<code>// 用于遍历title节点中的属性</code>

<code>else if(qname.equals("title")){</code>

<code>if(attr.equals("lang")){</code>

<code>book.setlang(attributes.getvalue(i));</code>

<code>booklist.add(book);</code>

<code>book = null;</code>

<code>book.settitle(text);</code>

<code>else if(qname.equals("author")){</code>

<code>book.setauthor(text);</code>

<code>else if(qname.equals("year")){</code>

<code>book.setyear(text);</code>

<code>else if(qname.equals("price")){</code>

<code>book.setprice(text);</code>

<code>// 文本值</code>

<code>text = new string(ch, start, length);</code>

<code>// 得到遍历结果</code>

<code>list&lt;book&gt; booklist = handler.getbooklist();</code>

<code>system.out.println("遍历结果:");</code>

<code>for (book book : booklist) {</code>

<code>system.out.println(book);</code>

遍历结果:

category:java  lang:chi   title:java多线程编程核心技术   author:高洪岩   year:2015   price:69.00

category:c++  lang:en   title:effective c++: 55 specific ways to improve your programs and designs   author:scott meyers   year:2006   price:58.00

category:web  lang:en   title:learning xml   author:erik t. ray   year:2016   price:39.95