何为Sax解析
Java解析XML通常有两种方式,DOM和SAX。DOM虽然是W3C的标准,提供了标准的解析方式,但它的解析效率一直不尽如人意,因为使用DOM解析XML时,解析器读入整个文档并构建一个驻留内存的树结构(节点树),然后您的代码才可以使用DOM的标准接口来操作这个树结构。但大部分情况下我们只对文档的部分内容感兴趣,根本就不用先解析整个文档,并且从节点树的根节点来索引一些我们需要的数据也是非常耗时的。
SAX是一种XML解析的替代方法。相比于文档对象模型DOM,SAX是读取和操作XML数据的更快速、更轻量的方法。SAX允许您在读取文档时处理它,从而不必等待整个文档被存储之后才采取操作。它不涉及DOM所必需的开销和概念跳跃。
SAX解析XML文档采用事件驱动模式。什么是事件驱动模式?它将XML文档转换成一系列的事件,由单独的事件处理器来决定如何处理。
基于事件驱动的处理模式主要是基于事件源和事件处理器(或者叫监听器)来工作的。一个可以产生事件的对象叫做事件源,而一个可以针对事件做出响应的对象就被叫做事件处理器。
首先我们需要了解Sax节点的种类
一种是ElementNode,一种是TextNode
<?xml version="1.0" encoding="utf-8" ?>
<people>
<person id="1">
<name>张三</name>
<age>12</age>
<tel>1111111</tel>
</person>
<person>
<name>李四</name>
<age>11</age>
<tel>22222</tel>
</person>
<person>
<name>王五</name>
<age>10</age>
<tel>33333</tel>
</person>
</people>
其中像people person …就是ElementNode
张三 12则是TextNode
像Dom解析一样Sax解析也是分为固定的三个步骤
//1.获取解析器工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//当然也可以直接声明工厂的实现类
SAXParserFactory factory=new SAXParserFactoryImpl();
//2.获取解析器
SAXParser parser = factory.newSAXParser();
//3.解析XML
parser.parse(xmlStream,new DefaultHandler(){
});
注:Handler是解析时触发的事件,即事件源
在解析时Handler中需要注意的五个方法
//当读入XML时,会调用
public void startDocument()
//当读入一个节点时,会调用
public void startElement(String uri, String localName, String qName, Attributes attributes)
//当一个节点读取完毕时,会调用
public void endElement(String uri, String localName, String qName)
//当XML解析完毕时,会调用
public void endDocument()
//处理节点中的文本内容则会用到
public void characters(char[] ch, int start, int length)
注:五个方法均会抛出SAXException
import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SaxTest {
static List<Person> people=new ArrayList();
public static void main(String[] args)throws Exception {
//1 工厂
//SAXParserFactory spf=SAXParserFactory.newInstance();
SAXParserFactory spf=new SAXParserFactoryImpl();
//2 解析
SAXParser sp=spf.newSAXParser();
InputStream in=SaxTest.class.getClassLoader()
.getResourceAsStream("com/dsj101/people.xml");
sp.parse(in,/*3.解析事件*/new DefaultHandler(){
/* @Override
public void startDocument() throws SAXException {
System.out.println("开始解析文档内容了");
}
@Override
public void endDocument() throws SAXException {
System.out.println("已解析完成");
}*/
private Person person;
private String tag;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.println(qName+"开始了");
tag=qName;
if(qName.equals("person")){
person=new Person();
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.println(qName+"结束了");
if (qName.equals("person")){
people.add(person);
}
tag=null;
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.println("处理内容:"+new String(ch,start,length));
if("name".equals(tag)){
person.setName(new String(ch,start,length));
}
if("age".equals(tag)){
person.setAge(Integer.parseInt(new String(ch,start,length)));
}
if("tel".equals(tag)){
person.setTel(new String(ch,start,length));
}
}
});
Collections.sort(people,(o1, o2) -> o2.getName().compareTo(o1.getName()));
for (Person p :
people) {
System.out.println(p);
}
people=new ArrayList<>();
}
}
最后来一个Python版的
import xml.sax
class MyHandler(xml.sax.ContentHandler):
def __init__(self):
self.person=None
self.tag=None
def startElement(self,name, attrs):
self.tag=name
if name == 'person':
self.person = None
def endElement(self,name):
if name == 'person':
global people
people.append(self.person)
self.person=None
self.tag=None
def characters(self,content):
if "name" == self.tag:
self.person.name == content
if "age" == self.tag:
self.person.age == int(content)
if "tel" == self.tag:
self.person.tel == content
parser = xml.sax.make_parser() # 创建一个 XMLReader
# parser.setFeature(xml.sax.handler.feature_namespaces, 0) # turn off namepsaces
parser.setContentHandler(MyHandler()) #设置内容事件处理器
parser.parse('people.xml')
最后的最后:
sax解析为流解析.顾名思义即遇到什么东西 执行某个方法(函数)