欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SAX解析XML

程序员文章站 2022-05-28 08:31:37
...

下面是SAX解析XML的示例,包括三个文件employee.xml、Employee.java、SaxEmployee.java

1.被解析的employee.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE employees [
	<!ELEMENT employees (employee*)>
	<!ELEMENT employee (name,age,gender,email,salary)>
	<!ATTLIST employee id  CDATA #IMPLIED> 
	<!ATTLIST employee depName CDATA #IMPLIED> 
	<!ELEMENT name (#PCDATA)>
	<!ELEMENT age (#PCDATA)>
	<!ELEMENT gender (#PCDATA)>
	<!ELEMENT email (#PCDATA)>
	<!ELEMENT salary (#PCDATA)>
]>
<employees>
	<employee id="1" depName="教学部">
		<name>tom</name>
		<age>20</age>
		<gender>male</gender>
		<email>[email protected]</email>
		<salary>10k</salary>
	</employee>
	<employee id="2" depName="教学部">
		<name>jack</name>
		<age>30</age>
		<gender>female</gender>
		<email>[email protected]</email>
		<salary>8k</salary>
	</employee>
	<employee id="3" depName="市场部">
		<name>rose</name>
		<age>25</age>
		<gender>female</gender>
		<email>[email protected]</email>
		<salary>5k</salary>
	</employee>
	<employee id="4" depName="教学管理部">
		<name>mark</name>
		<age>30</age>
		<gender>male</gender>
		<email>[email protected]</email>
		<salary>5k</salary>
	</employee>
</employees>

2.Employee.java文件

 

package exercise;

public class Employee {

	private int id;
	private String depName;
	private String name;
	private int age;
	private String gender;
	private String email;
	private String salary;
	
	public Employee() {
	}
	
	public Employee(int id, String depName, String name, int age, String gender, String email, String salary) {
		super();
		this.id = id;
		this.depName = depName;
		this.name = name;
		this.age = age;
		this.gender = gender;
		this.email = email;
		this.salary = salary;
	}
	
	@Override
	public String toString() {
		return "Employee [id=" + id + ", depName=" + depName + ", name=" + name + ", age=" + age + ", gender=" + gender
				+ ", email=" + email + ", salary=" + salary + "]";
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getDepName() {
		return depName;
	}
	public void setDepName(String depName) {
		this.depName = depName;
	}
	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;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getSalary() {
		return salary;
	}
	public void setSalary(String salary) {
		this.salary = salary;
	}
	
	
}

3.SaxEmployee.java实现解析

 

package exercise;

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

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;



/**
 * 利用SAX解析,将employee.xml中的employee对象存放到list中
 * @author Attention
 *
 */
public class SaxEmployee {

	public static void main(String[] args) throws Exception {
		//1.先创建解析器工厂
		SAXParserFactory factory = SAXParserFactory.newInstance();
		//2.利用工厂创建一个解析器
		SAXParser parser = factory.newSAXParser();
		//3.调用解析方法,解析文件,该方法有两个参数,第一个参数是你要解析的文件,第二个参数是处理类
		File file = new File("src/exercise/employee.xml");
		Handler handler = new Handler();
		parser.parse(file, handler);
	}
}

/**
 * 创建一个类继承默认处理类,实现里面具体的解析方法
 * 前面说过SAX是基于事件的解析,遇到开始标签、结束标签、文本,空文本会触发事件
 * 我们就是要写触发事件后具体的执行过程,这也是SAX比较复杂的地方
 * 里面有几个很关键的方法:
 * 1.startDocument()
 * 2.endDocument()
 * 3.startElement()
 * 4.endElement()
 * 5.characters()
 * 实现这几个方法就可以对xml文件进行解析了,当然1和2两个方法可以不实现
 */
class Handler extends DefaultHandler{

	//首先我们先创建一个List容器用来存放Employee对象,我们在startDocument()方法中进行初始化
	private List<Employee> list = null;
	//用来存放当前的标签名
	private String tagName = null;
	//定义一个Employee对象
	private Employee employee = null;
	@Override
	public void startDocument() throws SAXException {
		System.out.println("============开始解析文档============");
		list = new ArrayList<>();
	}

	@Override
	public void endDocument() throws SAXException {
		System.out.println("============解析文档结束============");
		//执行到这个方法,说明文档已经解析完毕,我们在这里将list容器中的内容打印出来,测试一下我们方法是否有误
		//当前也可以给List提供get()函数,在外面拿取
		for(Employee e : list) {
			System.out.println(e);
		}
	}

	//开始标签,当遇到开始标签会触发该方法
	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		if(qName.equals("employee")) {                 //说明拿到一个Employee对象
			employee = new Employee();                 //我们就创建一个对象
			String id = attributes.getValue("id");     //获取到两个属性值
			String depName = attributes.getValue("depName");
			employee.setId(Integer.parseInt(id));      //将当前取到的值赋给当前对象
			employee.setDepName(depName);
		}else {
			tagName = qName;
		}
	}

	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		
		if(qName.equals("employee")) {    //此时说明一个对象已经解析完,我们就将当前对象存放到容器中
			list.add(employee);
		}else {
			//因为SAX解析也会识别空文本,所以每次遇到尾标签,需要将tagName值空,避免,将当前的值被空文本给覆盖掉
			tagName = null;
		}
	}
	//当前文本内容
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		//构建当前读取到文本内容
		String msg = new String(ch,start,length);
		//tagName存放这当前的qName,判断当前拿取到的是那个值
		if(tagName.equals("name")) {
			employee.setName(msg);
		}else if(tagName.equals("age")) {
			employee.setAge(Integer.parseInt(msg));
		}else if(tagName.equals("gender")) {
			employee.setGender(msg);
		}else if(tagName.equals("email")) {
			employee.setEmail(msg);
		}else if(tagName.equals("salary")) {
			employee.setSalary(msg);
		}
	}
	
}