java sax 教程_Java&Xml教程(五)使用SAX方式解析XML文件

Java SAX解析机制为我们提供了一系列的API来处理XML文件,SAX解析和DOM解析方式不太一样,它并不是將XML文件内容一次性全部加载,而是连续的部分加载。

javax.xml.parsers.SAXParser类提供了一些函数,采用事件处理方式解析XML文档,这个类实现了XMLReader接口,提供了重载的parse()方法从File,InputStream,SAX InputSource和URI字符串中读取XML文档。

实际的XML解析工作由Handler类来完成,我们需要创建自己的Handler类,这就需要我们实现org.xml.sax.ContentHandler接口。这个接口中包含当事件发生时接收通知的回调方法,例如 StartDocument, EndDocument, StartElement, EndElement, CharacterData等等。

org.xml.sax.helpers.DefaultHandler提供了ContentHandler接口的默认实现,因此我们可以继承该类实现自己的处理类。继承这个类是明智的选择,因为我们可能只需要实现一些方法。继承这个类可以保证代码的简洁和可维护性。

下面是我们要解析的XML文档:

employees.xml

29

Pankaj

Male

Java Developer

35

Lisa

Female

CEO

40

Tom

Male

Manager

25

Meghna

Female

Manager

该XML文件内容存放一些员工的信息,每个员工包含id属性和age, name, gender,role字段。

我们將使用SAX解析机制处理XML文件并创建员工对象列表。

我们使用Employee类抽象员工的信息:Employee.java

package com.journaldev.xml;

public class Employee {

private int id;

private String name;

private String gender;

private int age;

private String role;

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 String getGender() {

return gender;

}

public void setGender(String gender) {

this.gender = gender;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String getRole() {

return role;

}

public void setRole(String role) {

this.role = role;

}

@Override

public String toString() {

return "Employee:: ID="+this.id+" Name=" + this.name + " Age=" + this.age + " Gender=" + this.gender +

" Role=" + this.role;

}

}

接着继承DefaultHandler类创建自己的Handler类MyHandler.java

package com.journaldev.xml.sax;

import java.util.ArrayList;

import java.util.List;

import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;

import com.journaldev.xml.Employee;

public class MyHandler extends DefaultHandler {

//List to hold Employees object

private List empList = null;

private Employee emp = null;

//getter method for employee list

public List getEmpList() {

return empList;

}

boolean bAge = false;

boolean bName = false;

boolean bGender = false;

boolean bRole = false;

@Override

public void startElement(String uri, String localName, String qName, Attributes attributes)

throws SAXException {

if (qName.equalsIgnoreCase("Employee")) {

//create a new Employee and put it in Map

String id = attributes.getValue("id");

//initialize Employee object and set id attribute

emp = new Employee();

emp.setId(Integer.parseInt(id));

//initialize list

if (empList == null)

empList = new ArrayList<>();

} else if (qName.equalsIgnoreCase("name")) {

//set boolean values for fields, will be used in setting Employee variables

bName = true;

} else if (qName.equalsIgnoreCase("age")) {

bAge = true;

} else if (qName.equalsIgnoreCase("gender")) {

bGender = true;

} else if (qName.equalsIgnoreCase("role")) {

bRole = true;

}

}

@Override

public void endElement(String uri, String localName, String qName) throws SAXException {

if (qName.equalsIgnoreCase("Employee")) {

//add Employee object to list

empList.add(emp);

}

}

@Override

public void characters(char ch[], int start, int length) throws SAXException {

if (bAge) {

//age element, set Employee age

emp.setAge(Integer.parseInt(new String(ch, start, length)));

bAge = false;

} else if (bName) {

emp.setName(new String(ch, start, length));

bName = false;

} else if (bRole) {

emp.setRole(new String(ch, start, length));

bRole = false;

} else if (bGender) {

emp.setGender(new String(ch, start, length));

bGender = false;

}

}

}

MyHandler类持有一个存放Employee对象的List引用,它只有一个对应的getter方法。Employee对象在事件处理函数中被添加到List对象,在MyHandler类中还定义了Employee对象和它的几个字段相关的boolean类型变量用于创建Employee对象,当Employee对象的所有属性都被设置时,它就会被添加到list中。

我们重写了几个重要的方法startElement(), endElement() 和characters().

当SAXParser 开始解析文档时遇到元素的开始标签时,startElement() 方法就会被调用,我们重写了这个方法,使用boolean类型变量来区分元素类别。我们也是在该方法中,当Employee 标签开始时创建Employee 对象。

当SAXParser遇到元素中的字符串数据时characters()方法会被调用,我们使用boolean类型字段为Employee对象的属性进行赋值。

endElement()方法则会在SAXParser 遇到XML结束标签时会被调用,在这里我们將Employee对象添加到List对象中。

在下面的测试程序中,我们使用MyHandler解析XML文档生成存放Employee 对象List。

XMLParserSAX.java

package com.journaldev.xml.sax;

import java.io.File;

import java.io.IOException;

import java.util.List;

import javax.xml.parsers.ParserConfigurationException;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

import com.journaldev.xml.Employee;

public class XMLParserSAX {

public static void main(String[] args) {

SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();

try {

SAXParser saxParser = saxParserFactory.newSAXParser();

MyHandler handler = new MyHandler();

saxParser.parse(new File("/Users/pankaj/employees.xml"), handler);

//Get Employees list

List empList = handler.getEmpList();

//print employee information

for(Employee emp : empList)

System.out.println(emp);

} catch (ParserConfigurationException | SAXException | IOException e) {

e.printStackTrace();

}

}

}

运行程序输出:

Employee:: ID=1 Name=Pankaj Age=29 Gender=Male Role=Java Developer

Employee:: ID=2 Name=Lisa Age=35 Gender=Female Role=CEO

Employee:: ID=3 Name=Tom Age=40 Gender=Male Role=Manager

Employee:: ID=4 Name=Meghna Age=25 Gender=Female Role=Manager

SAXParserFactory 类提供了工厂方法来获取SAXParser 实例,在调用 SAXParser对象的parse方法时传入Handler对象来处理回调事件。SAXParser解析机制刚开始接触时有点复杂,但是当你致力于处理大型的XML文档时,它比DOM解析提供了更有效的解析机制。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值