一:解析思想
SAX: Simple API for XML :读文档时候就能操作
解析原理:通过读取器读取XML文档,当读取到文档的某一部分时,(文档的开始,元素的开始,元素的结束,文档的结束), 都会调用事件处理器的对应方法,读取的数据,以形参的方式传递给相应的方法
二:SAX解析优缺点
优点:1:不需要像DOM解析方式将整个文档加载进内存中,减小系统内存消耗。
2:当解析到某个标签内容时可以自动触发相应的方法进行处理,效率高
缺点:1:只能执行查找动作,不能增删改
2:每次解析只能处理一次,要想再次处理需要再次解析
三:示例代码
例如解析如下XML文档:city.xml
(注意文档在工程中的位置,直接放在工程根目录下,否则在查找文档时候需要加载绝对路径)
<pre name="code" class="html"><span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?>
<county>
<province name="江苏">
<capital>南京</capital>
<city>苏州</city>
</province>
<province name="山东">
<capital>济南</capital>
<city>青岛</city>
</province>
</county></span>
解析分为5个步骤: 1:获取解析工厂
2:获取解析器
3:获取读取器
4:注册事件处理器
5:开始解析
<span style="font-size:18px;">public class SaxDemo1 {
public static void main(String[] args) throws Exception{
//获取解析工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//获取解析器
SAXParser parser = factory.newSAXParser();
//获取读取器
XMLReader reader = parser.getXMLReader();
//注册事件处理器
reader.setContentHandler(new MyHandler());
//开始解析
reader.parse("city.xml");
}
}</span>
<span style="font-size:18px;">class MyHandler implements org.xml.sax.ContentHandler{
@Override
public void startDocument() throws SAXException {
System.out.println("文档解析开始了");
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
System.out.println("解析到标签"+qName);
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//打印
System.out.println(new String(ch,start,length));
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
System.out.println("解析到结束标签"+qName);
}
@Override
public void endDocument() throws SAXException {
System.out.println("文档解析结束");
}
@Override
public void setDocumentLocator(Locator locator) {
}
@Override
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
}
@Override
public void endPrefixMapping(String prefix) throws SAXException {
// TODO Auto-generated method stub
}
@Override
public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
}
@Override
public void processingInstruction(String target, String data)
throws SAXException {
// TODO Auto-generated method stub
}
@Override
public void skippedEntity(String name) throws SAXException {
// TODO Auto-generated method stub
}
}</span>
此处简单地打印出标签和内容,但是可以看到继承ContentHandler要复写很多方法,较为繁琐
那有木有好的方法呢 当然是有的,就是适配器设计模式,何为适配器设计模式?简单的说就是这个类已经实现了
ContentHandler接口,我们使用这个类时不需要复写所有的方法,只将自己需要的方法复写即可
<span style="font-size:18px;">//适配器设计模式
class MyHandler extends DefaultHandler{
//定义一字符串,用于保存标签名称
private String eleName = null;
//如果只想打印第二个符合条件的标签主体内容,可以加上计数器
private int iNum = 0;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
//将开始标签名称保存
eleName = qName;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//判断是哪一个标签,并采取相应的动作
// if("capital".equals(eleName))
// System.out.println(new String(ch,start,length));
//如果只想打印第二个符合条件的标签主体内容,可以加上计数器
if("capital".equals(eleName) && iNum++ == 1)
System.out.println(new String(ch,start,length));
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
//结束标签后要将字符串初始化,否则会打印结束标签到下一开始标签前的空格内容
eleName = null;
}
}</span>