1.编程理念:基于事件编程的原理
2.(1)SAX解析的特点:读取一点,处理一点,解析一点
(2)DOM解析的特点:将整个xml文件加载完毕之后,才开始进行解析(一次性解析)
DOM解析的弊端:使用DOM解析的xml文件内容不能太大,否则会造成内存溢出
3.SAX解析的优点:占用内存小,从占用内从角度考虑SAX解析优于DOM解析
4.SAX解析图解:
(1)创建SAX解析器对象:实例:SAXParser(一个抽象类)
SAXParser parser = SAXParserFactory.newIntance().newSAXParser() ;
注:<1>protected SAXParserFactory() 受保护构造方法,以强制使用 newInstance()
<2>public abstract SAXParser newSAXParser() 使用当前配置的工厂参数创建 SAXParser 的一个新实例
(2)创建一个事件处理程序:自定义一个类,继承自DefaultHandler,并且重写几个方法:
<1>startElement(….String qName,Attributes attributes){} 读到开始标签触发这个方法
<2>characters(char[] ch,int start,int length){} SAX解析器解析xml文件解析到文本内容的时候,就会触发这个方法
<3>endElement(..String qName){} 读到结束标签的时候触发这个方法
(3)读取xml文件
parser.parse(new File(“contact.xml”),基于事件处理程序的对象)
练习1:
/*
* SAX解析
* */
import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class SaxTest1 {
public static void main(String[] args) throws Exception {
// 创建一个SAX解析器,相当于事件源
SAXParser parser = SAXParserFactory.newInstance().newSAXParser() ;
// 绑定事件处理程序
// 参数1:通过解析器读取到的xml文件 参数2:编写事件处理程序
parser.parse(new File("./src/contact.xml"), new MyDefaultHandler1());
}
}
/*
* 事件处理程序(编写监听器)
* */
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MyDefaultHandler1 extends DefaultHandler {
// xml文件文档开始时就会触发此方法
@Override
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("开始读取xml文件");
}
/*
* 开始标签
* qName:标签名称
* attribute:属性列表
* */
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
System.out.println("MyDefaultHandler.startElement():"+qName);
}
/*
* 文本内容:
* ch:字符数组
* start:从某个位置处开始读取
* length:读取的实际字符数
* */
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String textContent = new String(ch, start, length) ;
System.out.println("MyDefaultHandler.characters():"+textContent);
}
/*
* 结束标签
* qName:标签名称
* */
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
System.out.println("MyDefaultHandler.endElement():"+qName);
}
// xml文件读取结束之后就会触发此方法
@Override
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("xml文件读取完毕");
}
}
结果:
练习2:将解析的xml文件,原样输出
import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class SaxTest2 {
public static void main(String[] args) {
try {
// 1)创建一个SAX解析器对象
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
// 2)创建事件处理程序
MyDefaultHandler2 handler2 = new MyDefaultHandler2();
// 3)进行解析contact.xml文件
parser.parse(new File("./src/contact.xml"), handler2);
// 返回内容
System.out.println(handler2.getContent());
} catch (Exception e) {
e.printStackTrace();
}
}
}
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MyDefaultHandler2 extends DefaultHandler {
// 目的:使用MyDefaultHandler2事件处理程序,将xml文件的内容打印出来
// 定义一个字符串缓冲区
private StringBuffer sb = new StringBuffer();
// 定义一个成员方法,获得文本内容
public String getContent() {
return sb.toString();
}
/**
* 开始标签 qName:标签名称 attributes:属性列表
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
// 1)拼接左尖括号+标签名称
sb.append("<" + qName);
// 2)拼接属性名称+属性值——Attribytes:属性列表里面包含了很多 标签对应的属性
// 多个属性,进行遍历
for (int i = 0; i < attributes.getLength(); i++) {
// 获取到每一个属性属性,通过属性对象获取属性值和属性名称
String name = attributes.getQName(i); // 属性名称
String value = attributes.getValue(i); // 属性值
sb.append(" " + name + "=\"" + value + "\"");
}
// 3) 拼接右尖括号
sb.append(">");
}
/**
* 文本内容
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// length:读取当前实际的字符数
// 将字符数组的一部分转换成字符串,然后在进行拼接
String content = new String(ch, start, length);
sb.append(content);
}
/**
* 结束标签
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// 拼接结束标签
sb.append("" + qName + ">");
}
}