java SAX解析XML

引入SAX

相当于DOM解析来说,DOM一次会将所有的内容全部加载到内存中然后去解析内容到集合中去查找,如果对于较大的XML文件,则会非常影响内存的使用,同时对于大文件DOM解析效率非常低。所以引入SAX(流读取的机制)解析的方法。

SAX基本概念

流读取的机制是只负责读取,不进行存储,但是会给出一定的关键的事件,提示你进行相应的保存操作。流机制(SAX)是引导你进行提取自己关注的信息(私人订制)。就个人的理解而言非常类似于顺序查找,找到符合要求的存入list,不符合的直接跳过,依次从头开始查找。

SAX提供了哪些回调事件

  当读到文档开始处触发事件:startDocument

  当读到文档结束处触发事件:endDocument

  当读到元素开始处触发事件:startElement

  当读到元素结束处触发事件:endElement

  读到内容时触发事件:characters


一个简单的例子说明一切(不懂的看注释)

1、在本地F://zztest/xiyouji.xml的位置定义一个xml文件

<?xml version="1.0" encoding="GB2312"?>
<bookstore>
   <book category="COOKING">
     <title lang="en">西游记</title>

     <author>吴承恩</author>

     <year>2005</year>

     <price>30.00</price>

  </book>

 
  <book category="COOKING">

     <title lang="en">水浒传</title>

     <author>施耐庵</author>

     <year>2003</year>

     <price>29.00</price>

   </book>

</bookstore>
2、定义一个继承DefaultHandler类的Handler类

package saxdemo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

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

public class Myhandler extends DefaultHandler {
	//该map相当于一个中间变量
	private Map<String, String> map;
	//list用于接收要检索标签的全部内容
	private ArrayList<Map<String, String>> list;
	//当前检索的标签名
	private String currentTag;
	//当前检索标签名对应的值
	private String currentValue;
	//要检索的标签名
	private String nodeName;

	public Myhandler() {

	}

	public Myhandler(String name) {
		this.nodeName = name;
	}

	public ArrayList<Map<String, String>> getList() {
		return this.list;
	}

	@Override
	public void startDocument() throws SAXException {

		System.out.println("******start document******");

		list = new ArrayList<Map<String, String>>();
	}

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

		System.out.println("******start element******");

		// qName为当前的标签名,nodeName为要检索的标签名,外部通过构造方法传入
		if (qName.equals(nodeName)) {
			map = new HashMap<String, String>();
		}

		// 当前的节点存在属性列表 && 当前的标签名和要检索的标签名一致
		if (attributes != null && map != null) {
			// 循环获取所有的属性名和对应的值放到map中
			for (int i = 0; i < attributes.getLength(); i++) {
				map.put(attributes.getQName(i), attributes.getValue(i));
			}
		}

		// 正在解析的元素
		currentTag = qName;
	}

	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		System.out.println("******characters******");

		// currentTag为当前检索的标签名,currnetValue为currentTag标签名对应的值
		if (currentTag != null && map != null) {
			//ch为当前检索的标签名对应的值,即刚好赋值给currentValue
			currentValue = new String(ch, start, length);
			if (currentValue != null && !currentValue.trim().equals("") && !currentValue.trim().equals("\n")) {
				map.put(currentTag, currentValue);
				System.out.println("-----" + currentTag + " " + currentValue);
			}
		}
	}

	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		System.out.println("******end element******");

		//element结束的时候向list中添加内容
		if (qName == nodeName) {
			list.add(map);
		}
	}

	@Override
	public void endDocument() throws SAXException {
		System.out.println("******end document******");

		super.endDocument();
	}
}
3、定义测试类

package saxdemo;

import java.io.File;
import java.util.ArrayList;
import java.util.Map;

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

public class SaxDemo {

	public static void main(String[] args) {
		File file = new File("F:" + File.separator + "zztest" + File.separator + "xiyouji.xml");
		ArrayList<Map<String, String>> list = readXML(file, "bookstore");
		System.out.println(list);
	}

	private static ArrayList<Map<String, String>> readXML(File file, String string) {
		Myhandler myhandler = new Myhandler("book");
		try {
			SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
			SAXParser saxParser = saxParserFactory.newSAXParser();
			saxParser.parse(file, myhandler);
			return myhandler.getList();
		} catch (Exception e) {

		}
		return null;
	}
}

测试结果: 

******start document******
******start element******
******characters******
******start element******
******characters******
******start element******
******characters******
-----title 西游记
******end element******
******characters******
******start element******
******characters******
-----author 吴承恩
******end element******
******characters******
******start element******
******characters******
-----year 2005
******end element******
******characters******
******start element******
******characters******
-----price 30.00
******end element******
******characters******
******end element******
******characters******
******start element******
******characters******
******start element******
******characters******
-----title 水浒传
******end element******
******characters******
******start element******
******characters******
-----author 施耐庵
******end element******
******characters******
******start element******
******characters******
-----year 2003
******end element******
******characters******
******start element******
******characters******
-----price 29.00
******end element******
******characters******
******end element******
******characters******
******end element******
******end document******

[{year=2005, author=吴承恩, price=30.00, category=COOKING, lang=en, title=西游记}, {year=2003, author=施耐庵, price=29.00, category=COOKING, lang=en, title=水浒传}]
结果翻译: 前部分带*的部分可以看出SAX的解析过程是顺序的,最后一行为检索到的结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值