xml文件的sax解析

       sax解析xml,採用事件處理方法,它的解析不需要完全加載完文件,可以避免了當xml文件過大時導致內存溢出的情況。sax解析主要包含兩部分:解析器與事件處理器。
       java api中已經提供了創建sax解析器的方式。解析器只要解析到xml文檔中的一個部分,就會調用事件處理器的某個方法。如下面的person.xml方件,當讀到xml的開始,會觸發事件處理器的startDocument()方法,當讀到<persons>標籤時,又會觸發事件處理器的startElement()方法。事件處理器是由我們來完成的,都過不同的事件,執行不同的方法,就可以完成對xml文件的解析。
<?xml version="1.0" encoding="UTF-8"?>
<persons>
	<person id="328">
		<name>zhangsan</name>
		<age>23</age>
	</person>
	<person id="303">
		<name>lisi</name>
		<age>22</age>
	</person>
</persons>

如何獲取解析器?
     1、得到解析工廠。
     2、得到解析器。
     3、解析xml文件

如何獲取事件處理器?
     方法1、實現ContentHandler接口,這個方法要實現很多事件處理方法,不是很方便。
     方法2、繼承DefaultHandler類,查看源碼可以看到,DefaultHandler實現了ContentHandler接口,只是對其方法空實現,所以我們只需要重寫我們要處理的事件。
     
     常用事件:
     1、startDocument() 讀到文檔開始時觸發事件。
     2、endDocument() 讀到文檔結束時觸發事件。
     3、startElement() 讀到標籤開始時觸發事件。
     4、endElement() 讀到標籤結束時觸發事件。
     5、characters() 讀到文檔字符數據時觸發事件。哪怕是空白區域,也會觸發這個方法。

下面看一個例子,將上述person.xml保存項目src目錄下,並讀取後將內容封裝成Person對象。
Person類:
public class Person {
	private int id;
	private String name;
	private int age;

	public int getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public int getAge() {
		return age;
	}

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

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
	}

	public Person(int id, String name, int age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}

	public Person() {
		super();
	}
}

sax解析:
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SaxTest {

	public static void main(String[] args) {
		try {
			//解析器的獲取
			//1、獲取sax解析工廠
			SAXParserFactory  sf = SAXParserFactory.newInstance();
			//2、獲取解析器
			SAXParser sp = sf.newSAXParser();
			
			//創建xml文件的輸入流
			InputStream inStream = SaxTest.class.getClassLoader()
					.getResourceAsStream("person.xml");
			//3、解析xml文件,將事件處理器傳入。
			sp.parse(inStream, new PersonHandler());
		} catch (ParserConfigurationException | SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

//事件處理器。
class PersonHandler extends DefaultHandler {
	private String currentTag;
	private List<Person> persons = null;
	private Person person = null;
	
	//讀到文檔開始時觸發的事件
	public void startDocument() throws SAXException {
		persons = new ArrayList<Person>();
	}

	//讀到文檔開始標籤時觸發的事件
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		currentTag = qName;
		System.out.println(qName);
		if ("person".equals(qName)) {
			person = new Person();
			String id = attributes.getValue("id");
			person.setId(Integer.parseInt(id));
		}
	}
	//讀到字符數據時觸發的事件。
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		// if(currentTag.equals("name")) { 容易拋空指針異常
		if ("name".equals(currentTag)) {
			person.setName(new String(ch, start, length));
		}
		if ("age".equals(currentTag)) {
			String age = new String(ch, start, length);
			person.setAge(Integer.parseInt(age));
		}
	}
	//讀到結束標籤時觸發的事件。
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		System.out.println(qName);
		if ("person".equals(qName)) {
			persons.add(person);
			person = null;
		}
		currentTag = null;
	}

	public void endDocument() throws SAXException {
		for (Person p : persons) {
			System.out.println(p);
		}
	}
}

此處再介紹一下XMLReader的用法:
獲取解釋器之後,我們也可以獲取它的XMLReader對象,該對象
  1. 增加了查詢和設置功能和屬性的標準方法;
  2. 增加了對名稱空間的支持,這是許多高層的 XML 標準所必需的。 
具體方法如下。
			//解析器的獲取
			//1、獲取sax解析工廠
			SAXParserFactory  sf = SAXParserFactory.newInstance();
			//2、獲取解析器
			SAXParser sp = sf.newSAXParser();
			//得到讀取器
			XMLReader reader = sp.getXMLReader();
			//設置讀取器的事件處理器對象。
			reader.setContentHandler(new PersonHandler());
			//開始解析
			reader.parse("src/person.xml");




發佈了41 篇原創文章 · 獲贊 198 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章