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

1. 简介

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

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

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

对应方法:


public void startDocument() throws SAXException {

}

public void endDocument() throws SAXException {

}

public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

}

public void endElement(String uri, String localName, String qName) throws SAXException {

}

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


public void characters(char[] ch, int start, int length) throws SAXException {

}

2. 解析

解析步骤:

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


SAXParserFactory factory = SAXParserFactory.newInstance();

(2)通过SAXParserFactory实例的newSAXParser()方法返回SAXParser实例parser


SAXParser parser = factory.newSAXParser();

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


package com.qunar.handler;

import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;

public class SAXParserHandler extends DefaultHandler{

	

	// 用来标示解析开始

	@Override

	public void startDocument() throws SAXException {

		

	}

	// 用来标示解析结束

	@Override

	public void endDocument() throws SAXException {

		

	}

	// 用来遍历XML文件的开始标签

	@Override

	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

		super.startElement(uri, localName, qName, attributes);

	}

	// 用来遍历XML文件的结束标签

	@Override

	public void endElement(String uri, String localName, String qName) throws SAXException {

		super.endElement(uri, localName, qName);

	}

	@Override

	public void characters(char[] ch, int start, int length) throws SAXException {

		super.characters(ch, start, length);

	}

}

(4)创建Handler类对象实例


// 定义SAXParserHandler对象

SAXParserHandler handler = new SAXParserHandler();

(5)解析XML文档


saxParser.parse(path, handler);

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


<?xml version="1.0" encoding="utf-8"?><bookstore>

	<book category="Java">

		<title lang="chi">Java多线程编程核心技术</title> 

		<author>高洪岩</author> 

		<year>2015</year> 

		<price>69.00</price> 

	</book>

	<book category="C++">

		<title lang="en">Effective C++: 55 Specific Ways to Improve Your Programs and Designs</title> 

		<author>Scott Meyers</author> 

		<year>2006</year> 

		<price>58.00</price> 

	</book>

	<book category="Web">

		<title lang="en">Learning XML</title> 

		<author>Erik T. Ray</author> 

		<year>2016</year>

		<price>39.95</price> 

	</book>

</bookstore>

3. 具体实例:


package com.qunar.handler;

 

import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;

 

 

public class SAXParserHandler extends DefaultHandler{

	private int bookIndex = 0;

	

	// 用来标示解析开始

	@Override

	public void startDocument() throws SAXException {

		System.out.println("SAX解析开始...");

	}

	// 用来标示解析结束

	@Override

	public void endDocument() throws SAXException {

		System.out.println("SAX解析结束...");

	}

	// 用来遍历XML文件的开始标签

	@Override

	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

		// 调用DefaultHandler类的startElement方法

		super.startElement(uri, localName, qName, attributes);

		// 开始解析book元素节点

		if(qName.equals("book")){

			++ bookIndex;

			System.out.println("开始解析第" + bookIndex + "本书...");

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

			/*String value = attributes.getValue("category");

			System.out.println("value->"+value);*/

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

			int size = attributes.getLength();

			for(int i = 0;i < size;++i){

				System.out.println(attributes.getQName(i) + ":" + attributes.getValue(i));

			}//for

		}//if

		else if(!qName.equals("bookstore")){

			System.out.print(qName + ":");

		}//else

	}

	// 用来遍历XML文件的结束标签

	@Override

	public void endElement(String uri, String localName, String qName) throws SAXException {

		super.endElement(uri, localName, qName);

		// 判断一本书是否解析完

		if(qName.equals("book")){

			System.out.println("结束解析第" + bookIndex + "本书...");

		}//if

	}

	@Override

	public void characters(char[] ch, int start, int length) throws SAXException {

		super.characters(ch, start, length);

		String text = new String(ch, start, length);

		if(!text.trim().equals("")){

			System.out.println(text);

		}//if

	}

}

package com.qunar.xml;

 

import java.io.IOException;

 

import javax.xml.parsers.ParserConfigurationException;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;

 

import org.xml.sax.SAXException;

 

import com.qunar.handler.SAXParserHandler;

 

 

/**

 * SAX方式解析XML文档

 * @author sjf0115

 *

 */

public class SAXXMLCode {

 

	public static void main(String[] args) {

		String path = "D:\\bookstore.xml";

		try {

			// 通过SAXParserFactory的静态方法newInstance()方法获取SAXParserFactory实例对象factory

			SAXParserFactory factory = SAXParserFactory.newInstance();

			// 通过SAXParserFactory实例的newSAXParser()方法返回SAXParser实例parser

			SAXParser saxParser = factory.newSAXParser();

			// 定义SAXParserHandler对象

			SAXParserHandler handler = new SAXParserHandler();

			// 解析XML文档

			saxParser.parse(path, handler);

		} catch (ParserConfigurationException e) {

			e.printStackTrace();

		} catch (SAXException e) {

			e.printStackTrace();

		} catch (IOException e) {

			e.printStackTrace();

		}

	}

}

运行结果:

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. 解析并储存于对象中


package com.qunar.bean;

 

/**

 * book实体类

 * @author sjf0115

 *

 */

public class Book {

	private String category;

	private String title;

	private String author;

	private String year;

	private String price;

	private String lang;

	

	public String getCategory() {

		return category;

	}

	public void setCategory(String category) {

		this.category = category;

	}

	public String getTitle() {

		return title;

	}

	public void setTitle(String title) {

		this.title = title;

	}

	public String getAuthor() {

		return author;

	}

	public void setAuthor(String author) {

		this.author = author;

	}

	public String getYear() {

		return year;

	}

	public void setYear(String year) {

		this.year = year;

	}

	public String getPrice() {

		return price;

	}

	public void setPrice(String price) {

		this.price = price;

	}

	public String getLang() {

		return lang;

	}

	public void setLang(String lang) {

		this.lang = lang;

	}

	@Override

	public String toString() {

		return "category:" + category + "  lang:" + lang + "   title:" + title + "   author:" + author + "   year:" + year + "   price:"  + price;

	}

}

package com.qunar.handler;

 

import java.util.ArrayList;

import java.util.List;

 

import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;

 

import com.qunar.bean.Book;

 

 

public class SAXParserHandler extends DefaultHandler{

	private Book book;

	private int bookIndex = 0;

	// 节点文本内容

	private String text;

	private List<Book> bookList = new ArrayList<Book>();

	

	public List<Book> getBookList() {

		return bookList;

	}

	// 用来标示解析开始

	@Override

	public void startDocument() throws SAXException {

		System.out.println("SAX解析开始...");

	}

	// 用来标示解析结束

	@Override

	public void endDocument() throws SAXException {

		System.out.println("SAX解析结束...");

	}

	// 用来遍历XML文件的开始标签

	@Override

	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

		// 调用DefaultHandler类的startElement方法

		super.startElement(uri, localName, qName, attributes);

		// 开始解析book元素节点

		if(qName.equals("book")){

			// 创建一个book对象

			book = new Book();

			++ bookIndex;

			System.out.println("开始解析第" + bookIndex + "本书...");

			int size = attributes.getLength();

			for(int i = 0;i < size;++i){

				String attr = attributes.getQName(i);

				// 属性category

				if(attr.equals("category")){

					book.setCategory(attributes.getValue(i));

				}//if

			}//for

		}//if

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

		else if(qName.equals("title")){

			int size = attributes.getLength();

			for(int i = 0;i < size;++i){

				String attr = attributes.getQName(i);

				// 属性category

				if(attr.equals("lang")){

					book.setLang(attributes.getValue(i));

				}//if

			}//for

		}//else

	}

	// 用来遍历XML文件的结束标签

	@Override

	public void endElement(String uri, String localName, String qName) throws SAXException {

		super.endElement(uri, localName, qName);

		// 判断一本书是否解析完

		if(qName.equals("book")){

			bookList.add(book);

			book = null;

			System.out.println("结束解析第" + bookIndex + "本书...");

		}//if

		else if(qName.equals("title")){

			book.setTitle(text);

		}//else

		else if(qName.equals("author")){

			book.setAuthor(text);

		}//else

		else if(qName.equals("year")){

			book.setYear(text);

		}//else

		else if(qName.equals("price")){

			book.setPrice(text);

		}//else

	}

	// 文本值

	@Override

	public void characters(char[] ch, int start, int length) throws SAXException {

		super.characters(ch, start, length);

		text = new String(ch, start, length);

	}

}

package com.qunar.xml;

 

import java.io.IOException;

import java.util.List;

 

import javax.xml.parsers.ParserConfigurationException;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;

 

import org.xml.sax.SAXException;

 

import com.qunar.bean.Book;

import com.qunar.handler.SAXParserHandler;

 

 

/**

 * SAX方式解析XML文档

 * @author sjf0115

 *

 */

public class SAXXMLCode {

 

	public static void main(String[] args) {

		String path = "D:\\bookstore.xml";

		try {

			// 通过SAXParserFactory的静态方法newInstance()方法获取SAXParserFactory实例对象factory

			SAXParserFactory factory = SAXParserFactory.newInstance();

			// 通过SAXParserFactory实例的newSAXParser()方法返回SAXParser实例parser

			SAXParser saxParser = factory.newSAXParser();

			// 定义SAXParserHandler对象

			SAXParserHandler handler = new SAXParserHandler();

			// 解析XML文档

			saxParser.parse(path, handler);

			// 得到遍历结果

			List<Book> bookList = handler.getBookList();

			System.out.println("遍历结果:");

			for (Book book : bookList) {

				System.out.println(book);

			}//for

		} catch (ParserConfigurationException e) {

			e.printStackTrace();

		} catch (SAXException e) {

			e.printStackTrace();

		} catch (IOException e) {

			e.printStackTrace();

		}

	}

}

运行结果:

SAX解析开始...

开始解析第1本书...

结束解析第1本书...

开始解析第2本书...

结束解析第2本书...

开始解析第3本书...

结束解析第3本书...

SAX解析结束...

遍历结果:

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

时间: 2024-10-05 05:31:58

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

Java高级特性 第14节 解析XML文档(2) - SAX 技术

一.SAX解析XML文档 SAX的全称是Simple APIs for XML,也即XML简单应用程序接口.与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式.当使用SAX分析器对XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件驱动接口. 1. SAX解析原理: 加载一点,读取一点,处理一点.对内存要求比较低. SAX解析工具内置在jdk中:org.xml.sax.*

cocos2d-x 3.0 使用Sax解析xml文档(解决中文显示问题)

今天是个好日子,心想的事儿都能成,明天是个好日子,打开了家门儿迎春风... 恩,听着歌写文档生活就是这么享受. 今天以前的邻居大神突然在qq上赞了我一下,这让我异常激动啊..这还要从前前前几天说起,那会无意间看到cocos微信上的一个实话实说活动,反正就是参加了可以抽奖这样子啦,没错,我就是本着那官方T恤去的,本着分子越大分母越大抽奖几率越大的原则,然后就连着发了一番感慨,而且还都是比较罗嗦,没想到隔天cocos君竟然给我回复了,中奖了有木有,cocos2dx的官方T恤,哈哈..然后就是以前的大

编写一个属于自己的sax解析xml文档

首先需要一个xml文档 <?xml version="1.0" encoding="UTF-8"?> <书架> <书> <书名>Hack36计</书名> <价格>78</价格> <作者>老死不相往来</作者> </书> <书> <书名>android高级程序设计</书名> <价格>89</价格&

Sax解析xml文档

测试的xml数据: <?xml version="1.0" encoding="utf-8" ?> <note> <to>George</to> <from>John</from> <heading>Reminder</heading> <body>Don't forget the meeting!</body> </note> 新建S

浅谈用java解析xml文档(二)

上一文中总结了dom解析xml文档的方式,本文开始总结使用SAX解析xml 的方式及它的优缺点! SAX(Simple API for XML),是指一种接口,或者一个软件包. 首先我们应该知道SAX解析和dom解析的区别: dom是树结构解析,易于理解和开发,它可以随意访问文件所在的节点位置,易于修改,删除和查询.但对于dom文档过大时,则会解析较慢. 而SAX解析是事件推动型,顺序读取文件的节点,且只能读取文档的内容,不能对文档的内容进行修噶,对文档的大小没有过多的限制,但开大复杂度较高,

四种生成和解析XML文档的方法详解(介绍+优缺点比较+示例)

四种生成和解析XML文档的方法详解(介绍+优缺点比较+示例) 众所周知,现在解析XML的方法越来越多,但主流的方法也就四种,即:DOM.SAX.JDOM和DOM4J 下面首先给出这四种方法的jar包下载地址 DOM:在现在的Java JDK里都自带了,在xml-apis.jar包里 SAX:http://sourceforge.net/projects/sax/ JDOM:http://jdom.org/downloads/index.html DOM4J:http://sourceforge.

四种生成和解析XML文档的方法详解

众所周知,现在解析XML的方法越来越多,但主流的方法也就四种,即:DOM.SAX.JDOM和DOM4J 一.介绍及优缺点分析 1. DOM(Document Object Model) DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作.由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的. [优点]      ①允许应用

艺多不压身 -- 四种生成和解析XML文档的方法详解

众所周知,现在解析XML的方法越来越多,但主流的方法也就四种,即:DOM.SAX.JDOM和DOM4J DOM:在现在的Java JDK里都自带了,在xml-apis.jar包里 SAX: JDOM: DOM4J: 一.介绍及优缺点分析 1. DOM(Document Object Model) DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然

Android解析XML文档的两种方式的简单对比

Android之所以会用到解析XML文档,不仅与JAVA对XML的解析比较简单,而且还因为XML是Android在网络间传递信息的主要存储方式.下面我简单谈谈Android对XML文档解析的两种方式:dom和sax.dom解析方式是,解析方法将一个XML文件看成是一棵树.由数据结构的知识我们知道对树的处理比较简单,就是对树的节点进行增,删,改,查,这也是dom的一个最大优点.但是,dom方式在解析的时候是一次性就将整个XML文档读进内存,这坏处不用我说了吧,我宝贵的内存是禁不起这么折腾的. sa