解析XML专题之SAX方式
SAX和DOM解析的不同原理
DOM解析: 是一次性加载文件所有内容到内存中,并构建一个驻留在内存的树状结构(节点数),如果需要解析的xml文档过大,或我们只需要对文档部分内容感兴趣,会引起性能问题
SAX解析: 是逐行扫描文档,一边扫描,一边解析。
与DOM相比, SAX方法更快速,更有效,可以在解析的任何时刻停止解析,但是它的缺点就是实现太复杂。
SAX实现步骤
- 首先SAXParseFactory 来创建一个SAXParserFactory实例
SAXParserFactory factory = SAXParserFactory.newInstance();
- 根据SAXParserFactory实例来创建SAXParser
SAXParserHandler hanlder = new SAXParserHandler();
parser.parse("test.xml", hanlder);
在入口代码处如下:
// 获取SAXParserFactory实例
SAXParserFactory factory = SAXParserFactory.newInstance();
// 获取SAXParser 实例
SAXParser parser;
try {
parser = factory.newSAXParser();
SAXParserHandler hanlder = new SAXParserHandler();
parser.parse("test.xml", hanlder);
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e1) {
e1.printStackTrace();
}
- 在解析过程中触发相对于接口中的事件处理程序
创建自定义Handler类继承DefaultHanlder, 通过下面的方法重写来进行事件处理
如下代码所示:
public class SAXParserHandler extends DefaultHandler {
int studentsIndex=0;
/*
* 当遇到开始标记时调用
* qName 表示扫描的开始标记的名字
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if(qName.equals("student")) {
studentsIndex++ ;
System.out.println("开始遍历 第 "+studentsIndex + "个 student ");
//已知student标记下的属性个数以及属性名,可以通过如下方法获取属性值
String value = attributes.getValue("id");
System.out.println("开始标记 " + qName + "的属性值" + value);
//如果不确定属性个数和属性名,采用下面的方法来遍历
int num = attributes.getLength();
for(int i = 0 ; i < num ; i++) {
System.out.print("开始遍历第" + (i + 1 ) + "个属性 : " + attributes.getQName(i) );
System.out.println(" = " + attributes.getValue(i));
}
}else {
System.out.print ("节点名:"+qName);
}
}
/*
* 获取节点值的方法 (当分析器遇到无法识别为标记或者指令类型字符时调用)
* ch所有文档内容除了节点之外
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
String value = new String(ch, start, length);
if(!value.trim().equals("")) {
System.out.println(" = " + value);
}
}
/*
* 当遇到节点结束时调用
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
if(qName .equals("student")) {
System.out.println("--------------------结束扫描标记第" + studentsIndex +" student-----------------");
}
}
/*
* 文件打开时调用
*/
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
System.out.println("xml文档解析开始");
}
/*
* 当到文档的末尾调用
*/
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
System.out.println("xml文档解析结束");
}
}
运行结果如下:
xml文档解析开始
节点名:students开始遍历 第 1个 student
开始标记 student的属性值1
开始遍历第1个属性 : id = 1
节点名:name = zhangsan
节点名:age = 20
--------------------结束扫描标记第1 student-----------------
开始遍历 第 2个 student
开始标记 student的属性值2
开始遍历第1个属性 : id = 2
节点名:name = lisi
节点名:age = 25
--------------------结束扫描标记第2 student-----------------
xml文档解析结束