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

<?xml version="1.0" encoding="UTF-8"?>
<Employees>
<Employee id="1">
<age>29</age>
<name>Pankaj</name>
<gender>Male</gender>
<role>Java Developer</role>
</Employee>
<Employee id="2">
<age>35</age>
<name>Lisa</name>
<gender>Female</gender>
<role>CEO</role>
</Employee>
<Employee id="3">
<age>40</age>
<name>Tom</name>
<gender>Male</gender>
<role>Manager</role>
</Employee>
<Employee id="4">
<age>25</age>
<name>Meghna</name>
<gender>Female</gender>
<role>Manager</role>
</Employee>
</Employees>

该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<Employee> empList = null;
private Employee emp = null; //getter method for employee list
public List<Employee> 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<Employee> 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解析提供了更有效的解析机制。

原文地址:http://www.journaldev.com/1198/java-sax-parser-example-tutorial-to-parse-xml-to-list-of-objects

Java&Xml教程(五)使用SAX方式解析XML文件的更多相关文章

  1. Android网络之数据解析----SAX方式解析XML数据

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  2. (四)SAX方式解析XML数据

    SAX方式解析XML数据 ​文章来源:http://www.cnblogs.com/smyhvae/p/4044170.html 一.XML和Json数据的引入: 通常情况下,每个需要访问网络的应用程 ...

  3. 网络相关系列之四:数据解析之SAX方式解析XML数据

    一.XML和Json数据的引入: 通常情况下.每一个须要訪问网络的应用程序都会有一个自己的server.我们能够向server提交数据,也能够从server获取数据.只是这个时候就有一个问题,这些数据 ...

  4. Java眼中的XML--文件读取--2 应用SAX方式解析XML

    1.获取一个SAXParserFactory的实例.2.通过factory获取SAXParser实例.  3.新建一个包和继承自DefaultHandler的类.  因为SAX遍历方式,比如便利一个节 ...

  5. 用JAXP的SAX方式解析XML文件

    简单用JAXP的SAX方式(事件驱动)解析XML文件: 文件(1.XML) <?xml version="1.0" encoding="UTF-8" st ...

  6. SAX方式解析XML文件实例

    books.XML文件: 书籍book.java实体类: public class Book { private String id; private String name; private Str ...

  7. SAX方式解析XML

    sax解析分为以下几步: 1 获取一个saxparserfactory 2 获取一个解析器 3 创建handler对象,这个myHandler是继承了DefaultHandler的一个类,这个实现类里 ...

  8. sax方式解析XML学习笔记

    原理:对文档进行顺序扫描,当扫描到文档(document)开始与结束,元素开始与结束.文档结束等地方 通知事件处理函数,由事件处理函数相应动作然后继续同样的扫描,直至文档结束. 优点:消耗资源比较少: ...

  9. 使用SAX方式解析XML文件

    package com.pingyijinren.test; import android.util.Log; import org.xml.sax.Attributes; import org.xm ...

随机推荐

  1. java json数据转List对象的集合-----阿里巴巴插件---及原生json---JSON 与 对象 、集合 之间的转换 JSON字符串和java对象的互转【json-lib】

    List<RunfastFullLess> list=(List<RunfastFullLess>)JSONArray.parseObject(activity.getFull ...

  2. noip模拟赛 蒜头君救人

    分析:之前的一道模拟赛题是dp+dfs,这道题是dp+bfs. 我们设f[stu][i][j]为当前状态为stu,走到(i,j)的答案,考虑怎么设计stu,每个人的状态有3种:要么在原地,要么被背着, ...

  3. 转载 - C++ - placement new

    出处:http://www.cnblogs.com/wanghetao/archive/2011/11/21/2257403.html 有关placement new                  ...

  4. JAVA之中出现无法加载主类的情况解决方法

    j今天打代码的时候出现了无法加载主类的情况,我就收集了一些,java无法加载主类的方法 ava无法加载主类解决办法 今天启动项目,又遇到找不到或无法加载主类的情况,清除项目后无法编译,class文件下 ...

  5. - > 贪心基础入门讲解三——活动安排问题二

    有若干个活动,第i个开始时间和结束时间是[Si,fi),活动之间不能交叠,要把活动都安排完,至少需要几个教室?   分析:能否按照之一问题的解法,每个教室安排尽可能多的活动,即按结束时间排序,再贪心选 ...

  6. Oops, 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine error

    环境: Win7 64位 + VS2005 + Office2013 64位 现象:程序为一个Excel导入程序,导入时报「'Microsoft.ACE.OLEDB.12.0' provider is ...

  7. Canopy算法计算聚类的簇数

    Kmeans算是是聚类中的经典算法.步骤例如以下: 选择K个点作为初始质心 repeat 将每一个点指派到近期的质心,形成K个簇 又一次计算每一个簇的质心 until 簇不发生变化或达到最大迭代次数 ...

  8. 对Socket CAN的理解(4)——【Socket CAN接收数据流程】

    转载请注明出处:http://blog.csdn.net/Righthek 谢谢! 如今我们来分析一下CAN总线的接收数据流程,对于网络设备.数据接收大体上採用中断+NAPI机制进行数据的接收.相同. ...

  9. MySQL hash分区(四)

    具体描写叙述总结请看MySQL分区(一) 样例:该样例为本人个人学习总结分享->具体说明-->有问题欢迎前来交流 watermark/2/text/aHR0cDovL2Jsb2cuY3Nk ...

  10. .net连接MySQL数据库的方案与实例演示

    以下的文章主要是向大家描述的是.net连接MySQL数据库的实际操作方法与其实例的演示.net连接MySQL数据库的实际操作方案我们主要是将其分成三部分,以下的文章就有其详细内容的描述. http:/ ...