SAX的特点这里不再赘述,仅用一实例说明SAX解析XML文档的方式与原理
1.SAX常用的接口
ContentHandler
该接口封装了一些对事件处理的方法,比如文档的开始和结束、元素的开始和结束、以及元素中的字符数据等事件,当遇到这些事件时,XML解析器会调用ContentHandler中对应的方法来响应该事件。
ContentHandler接口的方法有以下几种:
void startDocument()
void endDocument()
void startElement(String uri, String localName, String qName, Attributes atts)
void endElement(String uri, String localName, String qName)
void characters(char[] ch, int start, int length)
DTDHandler
用于接收基本的DTD相关事件,仅包括注释和未解析的实体声明部分,报告这些事件需要在startDocument()方法之后和第一个startElement()方法之前
EntityResolver
用于解析实体的基本接口,解析器在打开任何外部实体前调用该接口,如果SAX应用程序需要实现自定义处理外部实体,则必须实现此接口。
ErrorHandler
SAX错误处理程序的基本接口,如果SAX应用程序需要实现自定义的错误处理,则它必须实现此接口,然后解析器将通过此接口报告所有的错误和警告。
DefaultHandler
SAX2程序事件处理程序的默认基类,它实现了上面四个接口,所以我们在编写事件处理程序时,可以直接继承该类,然后重写我们需要的方法。
2.处理实例
xml文件
<?xml version="1.0" encoding="gb2312"?>
<丛书>
<书>
<名>萍踪侠影</名>
<人>梁羽生</人>
<价 unit="RMB">100.60</价>
</书>
<书>
<名>岳阳楼记</名>
<人>范仲淹</人>
<价 unit="美元">76.8</价>
</书>
</丛书>
源代码
package test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SAXTest {
public static void main(String[] args){
try{
//创建xml解析处理器
SAXContentHandler contentHandler = new SAXContentHandler();
File file = new File("D:\\book.xml");
//创建SAX解析器
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
//将xml解析处理器分配给SAX解析器,并对文件进行解析
parser.parse(file, contentHandler);
//输出结果
for(Book book : contentHandler.getBooks()){
System.out.println(book.toString());
}
}catch(FileNotFoundException e){
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 自定义XML解析处理器
*/
class SAXContentHandler extends DefaultHandler{
private List<Book> books;
private Book book;
private String tagName;
public List<Book> getBooks(){
return this.books;
}
@Override
public void startDocument() throws SAXException {
this.books = new ArrayList<Book>();
System.out.println("SAX解析文件开始");
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
//有的情况是localName,需要验证
this.tagName = qName;
if(this.tagName.equals("书")){
this.book = new Book();
}else if(this.tagName.equals("价")){
this.book.setUnit(attributes.getValue(0));
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//根据元素名称将字符数据赋给相应的属性
if(this.tagName != null){
String data = new String(ch, start, length);
if(this.tagName.equals("人")){
this.book.setAuthor(data);
}else if(this.tagName.equals("名")){
this.book.setName(data);
}else if(this.tagName.equals("价")){
this.book.setPrice(Double.parseDouble(data));
}
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if(qName.equals("书")){
this.books.add(this.book);
}
//注意将此处设置为null,因为在xml中的空白部分也会被视为一个文本节点,如果不设置为null,当读到空白节点时,如果tagName符合其中一个属性,程序便会将空字符串赋给相应的属性
this.tagName = null;
}
@Override
public void endDocument() throws SAXException {
System.out.println("SAX解析文件结束");
}
}
/**
* 定义实体类
*/
class Book{
public String author;
public String name;
public Double price;
public String unit;
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
@Override
public String toString() {
return "作者:"+this.author+"||书名:"+this.name+"||价格:"+this.price+"("+this.unit+")";
}
}
输出结果
SAX解析文件开始
SAX解析文件结束
作者:梁羽生||书名:萍踪侠影||价格:100.6(RMB)
作者:范仲淹||书名:岳阳楼记||价格:76.8(美元)