SAX方式读取XML文件

简介

SAXsimple API for XML)是一种XML解析的替代方法不需要从外界导入包,它属于JAVA类库中类。

相比于DOMSAX是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。而且相比于DOMSAX可以在解析文档的任意时刻停止解析,但任何事物都有其相反的一面,对于SAX来说就是操作复杂。

 在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出

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


SAX解析的运行机制

SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器:

解析器可以使用JAXPAPI创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。

解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。

事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。


扫描二维码关注公众号,回复: 2133746 查看本文章

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>[email protected]</email>
		<address>广州天河</address>
	</person>

	<person id="200">
		<name>李四</name>
		<age>20</age>
		<email>[email protected]</email>
		<address>广州番禺</address>
	</person>

	<person id="1000">
		<name>王五</name>
		<age>19</age>
		<email>[email protected]</email>
		<address>广州天河</address>
	</person>

	<person id="2000">
		<name>赵六</name>
		<age>20</age>
		<email>[email protected]</email>
		<address>广州番禺</address>
	</person>
</person-list>

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

{编号:100 姓名:张三 年龄:19 邮箱:[email protected] 地址:广州天河}
{编号:200 姓名:李四 年龄:20 邮箱:[email protected] 地址:广州番禺}
{编号:1000 姓名:王五 年龄:19 邮箱:[email protected] 地址:广州天河}
{编号:2000 姓名:赵六 年龄:20 邮箱:[email protected] 地址:广州番禺}

项目工程如下:


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文件

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

3Dom解析可以增删改查

解析工具: DOM4j

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

1)适合读取大容量的xml文件

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

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




猜你喜欢

转载自blog.csdn.net/mchenys/article/details/80519504