需要两个组件:解析器和事件处理器
解析器逐行扫描文档,每次扫描都会触发事件处理器中的方法。
优点:不需要等待整个xml加载到内存,当解析到某一部分时,自动触发对应的方法去处理;不需要将整个文档加载到内存中;无论多大的xml,理论上都可以解析。
缺点:每次解析都只能处理一次, 下次再想处理还要重新解析;只能进行查询,不能进行删改查的操作。
xml文件
<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<书架>
<书>
<书名>JAVA教程</书名>
<作者>boucher</作者>
<售价>39.90</售价>
</书>
<书>
<书名>数据结构</书名>
<作者>joaner</作者>
<售价>40.00</售价>
</书>
</书架></span>
解析过程
第1-3步:
<span style="font-size:18px;"> //1、获取解析器工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//2、通过工厂获取sax解析器
SAXParser parser = factory.newSAXParser();
//3、获取读取器
XMLReader reader = parser.getXMLReader();</span>
第4步:
<span style="font-size:18px;">reader.setContentHandler(/*自己选择*/);</span>
注册事件处理器,可以自己编写一个类实现ContentHandler接口,也可以直接new出来。
该接口中的主要方法有
<span style="font-size:18px;"> @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("开始标签");
}
@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("结束标签");
}
@Override
public void endDocument() throws SAXException {
System.out.println("结束解析");
}</span>
实例
打印上述xml文件的第二本书的书名
<span style="font-size:18px;"> private String name = null;
private int count = 0;
@Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
this.name = qName;
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
this.name = null;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if("书名".equals(name)&&++count==2){
System.out.println(new String(ch,start,length));
}
}
</span>
其中在endElement方法中将name置为null,是为了防止打印出结束标签</书名>后面的回车换行制表符。