SAX方式读取XML文件

  • Post author:
  • Post category:其他




简介

SAX




simple API for XML


)是一种


XML


解析的替代方法




不需要从外界导入包,它属于


JAVA

类库中类。



相比于

DOM




SAX


是一种


速度更快


,更有效的方法。它逐行扫描文档,一边扫描一边解析。而且相比于

DOM




SAX

可以在解析文档的任意时刻停止解析


,但任何事物都有其相反的一面,


对于

SAX

来说就是操作复杂。


在使用

DOM

解析


XML


文档时,需要读取整个


XML


文档,在内存中构架代表整个


DOM


树的


Doucment


对象,从而再对


XML


文档进行操作。此种情况下,如果


XML


文档特别大,就会消耗计算机的大量内存,并且


容易导致内存溢出

SAX

解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。





SAX

解析的运行机制


SAX

采用事件处理的方式解析


XML


文件,利用


SAX


解析


XML


文档,涉及两个部分:



解析器和事件处理器:


解析器可以使用

JAXP




API


创建,创建出


SAX


解析器后,就可以指定解析器去解析某个


XML


文档。


解析器采用

SAX

方式在解析某个


XML


文档时,它只要解析到


XML


文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的


xml


文件内容作为方法的参数传递给事件处理器。


事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到

sax

解析器解析到的数据,从而可以决定如何对数据进行处理。





sax解释方式的步骤:


1. 先要创建sax解释器的工厂对象。


2. 可以使用sax解释器的工厂对象生产一个sax解释器。


3.


创建事件处理器类,编写对应的读取方式


4.



使用

sax解释器解释xml文件

下面通介绍下相关方法的使用和说明

package demo1;

import java.io.File;

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

public class Demo1 {
	public static void main(String[] args) throws Exception {
		//创建sax解释器的工厂对象
		SAXParserFactory parserFactory = SAXParserFactory.newInstance();
		
		//使用sax解释器的工厂对象生产一个sax解释器
		SAXParser saxParser = parserFactory.newSAXParser();
		
		//使用sax解释器解释xml文件了。
		saxParser.parse(new File("person.xml"), new MyHandler());
	}
}
package demo1;

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

/**
 * 定义事件处理器,需要继承DefaultHandler类
 * 需要重写startElement、characters、endElement 3个方法。
 * 
 * @author mChenys
 * 
 */
public class MyHandler extends DefaultHandler {
	/**
	 * 当sax解释器读到了开始标签的时候会调用该方法。 
	 * localName:当前的标签名字 
	 * attributes:把这个标签的所有属性存储到这个集合中。
	 */
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {

		System.out.println("startElement->"+localName);
	}

	/**
	 * 当sax解释器读到了文本内容的时候会调用该方法 ch: 读取到的字符存储到了这个字符数组中。 
	 * start :从字符串数组中的指定索引值开始存储内容。 
	 * length : 存储了多少个字符到字符数组中。 
	 * 注意的细节: 
	 * 	1.如果标签体文本有很多的文本数据,那么这时候有可能调用一次characters方法无法读取完毕。这时候就会调用多次的characters方法。 
	 *  2.如果标签体内容出现了实体字符,那么这时候也会分多次读取。
	 */
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		System.out.println("characters->"+new String(ch,start,length));
	}

	/**
	 * 当sax解释器读到结束标签的时候会调用该方法。 
	 * localName : 结束标签名字
	 */
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		System.out.println("endElement->"+localName);
	}
}


下面做一个例子,通过demo读取如下xml文件

<?xml version="1.0" encoding="gbk"?>

<person-list>
	<person id="100">
		<name>张三</name>
		<age>19</age>
		<email>123454@qq.com</email>
		<address>广州天河</address>
	</person>

	<person id="200">
		<name>李四</name>
		<age>20</age>
		<email>22222@qq.com</email>
		<address>广州番禺</address>
	</person>

	<person id="1000">
		<name>王五</name>
		<age>19</age>
		<email>123454@qq.com</email>
		<address>广州天河</address>
	</person>

	<person id="2000">
		<name>赵六</name>
		<age>20</age>
		<email>22222@qq.com</email>
		<address>广州番禺</address>
	</person>
</person-list>

并将其按如下格式输出到控制台

{编号:100 姓名:张三 年龄:19 邮箱:123454@qq.com 地址:广州天河}
{编号:200 姓名:李四 年龄:20 邮箱:22222@qq.com 地址:广州番禺}
{编号:1000 姓名:王五 年龄:19 邮箱:123454@qq.com 地址:广州天河}
{编号:2000 姓名:赵六 年龄:20 邮箱:22222@qq.com 地址:广州番禺}

项目工程如下:


demo2

package demo2;

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

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

public class Demo2 {

	/**
	 * @param args
	 * @throws Exception
	 * @throws
	 */
	public static void main(String[] args) throws Exception {
		// 创建sax解释器的工厂对象
		SAXParserFactory factory = SAXParserFactory.newInstance();
		// 通过释器工厂创建一个sax解释器
		SAXParser saxParser = factory.newSAXParser();
		// 创建事情处理器对象
		MyHandler2 handler2 = new MyHandler2();
		// 使用sax解释器解释xml文件
		saxParser.parse(new File("person.xml"), handler2);

		ArrayList<Person> list = handler2.list;
		for (Person p : list) {
			System.out.println(p);
		}

	}

}

MyHandler2

package demo2;

import java.util.ArrayList;

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

public class MyHandler2 extends DefaultHandler {

	ArrayList<Person> list = new ArrayList<Person>();

	Person p = null;

	StringBuilder sb = null;

	// 读取开始节点
	@Override
	public void startElement(String uri, String localName, String tagName,
			Attributes attributes) throws SAXException {
		if ("person".equals(tagName)) {
			p = new Person();// 创建一个person对象
			// 设置id
			String id = attributes.getValue("id");
			p.setId(id);
		}

		// 创建了一个字符串缓冲区
		sb = new StringBuilder();
	}

	// 读取文本内容
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		// 先获取到当前文本的所有内容 地址
		String text = new String(ch, start, length);
		if (sb != null) {
			sb.append(text);
		}
	}

	// 读取结束标签
	@Override
	public void endElement(String uri, String localName, String tagName)
			throws SAXException {
		if ("name".equals(tagName)) {
			p.setName(sb.toString());
		} else if ("age".equals(tagName)) {
			p.setAge(sb.toString());
		} else if ("email".equals(tagName)) {
			p.setEmail(sb.toString());
		} else if ("address".equals(tagName)) {
			p.setAddress(sb.toString());
		} else if ("person".equals(tagName)) {
			list.add(p); // 将读取到的包含所有信息的person对象存储到集合中
		}
		// 清空StringBuilder的内容
		sb = null;
	}
}

Person

package demo2;

public class Person {

	private String id;

	private String name;

	private String age;

	private String email;

	private String address;


	public void setId(String id) {
		this.id = id;
	}



	public void setName(String name) {
		this.name = name;
	}



	public void setAge(String age) {
		this.age = age;
	}



	public void setEmail(String email) {
		this.email = email;
	}



	public void setAddress(String address) {
		this.address = address;
	}



	@Override
	public String toString() {
		return "{编号:" + this.id + " 姓名:" + this.name + " 年龄:" + this.age
				+ " 邮箱:" + this.email + " 地址:" + this.address + "}";
	}
}

总结





DOM

解析:一次性把


xml


文档内容加载进内存,构建成


Document


树。

1

)不适合读取大容量的


xml


文件

2




Dom


解析可以随意读取,甚至往回读

3




Dom


解析可以增删改查


解析工具:

DOM4j

SAX

解析: 读取一点,解析一点。

1

)适合读取大容量的


xml


文件

2

)从上往下逐点读取,不能往回读

3




SAX


解析通常只读取文件,不修改文件





版权声明:本文为mChenys原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。