一、什么是SAX方式
-SAX: Simple API for XML。属于开源社区XML-DEV,几乎所有的XML解析器都支持它。
-相比于DOM方式,SAX方式更为迅速,占用内存资源更少。
二、Java中使用SAX方式解析XML的原理
-DOM方式与SAX方式的区别:DOM方式解析之前要将整个XML文档读入,在内存中产生一个DOM树;而SAX方式解析是逐行扫描文档,边扫描边进行解析,不必等到整个文档装载完才进行操作。
-Java中SAX解析XML的方式:SAX解析方式是基于事件驱动(一种基于回调(callback)机制的程序运行方法)的,利用SAX解析XML涉及解析器和事件处理器两个部分。
a.解析器:对XML文档逐行进行解析,只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的XML文件内容作为方法的参数传递给事件处理器。
b.事件处理器:由程序员编写,决定对从解析器解析到的数据如何做处理。
-解析原理:
XML文档——解析器逐行解析——>解析到元素——-调用相应的时间处理方法——>处理解析到的数据——-继续解析下一行——>……
三、具体的Java代码实现
1.创建解析器,处理器,加载XML文档;2.内容处理的几个主要方法;3.取出特定元素的内容;4.将XML中的信息全部输出
待解析的XML代码:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><联系人列表>
<联系人>
<姓名>张三</姓名>
<EMAIL>[email protected]</EMAIL>
<年龄>30</年龄>
</联系人>
<联系人>
<姓名>李四</姓名>
<EMAIL>[email protected]</EMAIL>
<年龄>31</年龄>
</联系人>
</联系人列表>
1.创建解析器,处理器,加载XML文档
//创建sax解析器
SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
//获取内容读取器
XMLReader xml = sax.getXMLReader();
//注册一个内容处理器
xml.setContentHandler(new DefaultHandler(){});//重写DefaultHandler接口中的方法来处理解析到的内容
//加载XML文档
xml.parse("src/j2ee/dom/linkman.xml");
2.内容处理用到的几个主要方法(DefaultHandler 接口中)
i.startDocument()
方法说明:在解析整个文档开始时自动调用,重写此方法可以在解析文档开始时做特定处理。
ii.endDocument()
方法说明:在解析整个文档结束时自动调用,重写此方法可以在解析整个文档结束时做处理。
iii.startElement(String uri, String localName, String qName, Attributes attributes)
参数说明:URL,本地名称,当前解析到的元素名称,元素附加的属性
方法说明:在解析到元素节点时自动调用,重写此方法可以在解析到元素节点时做相应处理。
iv.endElement(String uri, String localName, String qName)
参数说明:URL,本地名称,当前结束解析的元素名称
方法说明:在解析到元素节点结束标签时自动调用,重写此方法可以在解析元素节点结束时做相应处理。
v.characters(char[] ch, int start, int length)
参数说明:XML文档内容的字符数组,当前解析到的元素在字符数组的起始位置,当前解析到的元素所占长度
方法说明:在解析完元素标签方法结束后自动调用,重写此方法可以对在此元素内读取到的相应内容做处理。
解析时方法调用的流程:由startDocument开始,在endDocument结束,中间三个按顺序反复调用
startDocument()---->sartElement()---->characters()---->endElement()---->sartElement()---->characters()---->endElement()---->......--->endDocument()
3.取出特定元素的内容(取出XML中第二个联系人的姓名,运行结果输出“李四”)
//创建sax解析器
SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
//获取内容读取器
XMLReader xml = sax.getXMLReader();
//注册一个内容处理器
xml.setContentHandler(new DefaultHandler(){
String curname = "";//记录当前的元素名
int count = 0;//记录当前取到的是第几个联系人
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName.equals("姓名")){
curname = "姓名";//只关注“姓名”元素
count++;
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
curname="";//一个元素解析结束后应清空记录的当前元素名
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if("姓名".equals(curname)&&count==2){ //拿到了第二个联系人的姓名
System.out.println(new String(ch,start,length));
}
}
});
//加载XML文档
xml.parse("src/j2ee/dom/linkman.xml");
4.将XML中的信息全部输出(定义一个linkman类封装信息,此处忽略linkman类的代码之关注主要代码)
List<Linkman> men = new ArrayList<Linkman>();//定义一个容器来存放解析到的联系人对象
//创建sax解析器
SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
//获取内容读取器
XMLReader xml = sax.getXMLReader();
//注册一个内容处理器
xml.setContentHandler(new DefaultHandler(){
Linkman man;//联系人对象
String curname = "";//记录当前解析的元素名
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName.equals("联系人")){
man = new Linkman();//当解析到联系人元素时new一个新的联系人对象
}
curname = qName;
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if(qName.equals("联系人")){ //当一个联系人元素解析完成时,将这个联系人对象添加到容器中
men.add(man);
}
curname="";
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if("姓名".equals(curname)){
man.setName(new String(ch,start,length));//若当前解析的是姓名元素,则将姓名的内容添加给联系人对象
}
if("EMAIL".equals(curname)){
man.setEmail(new String(ch,start,length));//若当前解析的是EMAIL元素,则将Email内容添加给联系人对象
}
if("年龄".equals(curname)){
man.setAge(Integer.parseInt(new String(ch,start,length)));//若当前解析的是年龄元素,则将年龄内容添加给联系人对象
}
}
});
//加载XML文档
xml.parse("src/j2ee/dom/book.xml");
for (Linkman tmp: men ) {
System.out.println(tmp.toString());
}
输出结果如下:(成功将XML中全部信息解析)
张三--zhang3@gmail.com--30
李四--li4@163.com--31