与DOM解析的区别:
在使用 DOM 解析XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。
SAX采用事件处理的方式解析XML文件
解析器:解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器
事件处理器:事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。
事件处理器分为四种:ContentHandler(内容处理器)最为多用
ErrorHandler(错误处理器)
DTDHandler(约束处理器)
EntityHandler(实体处理器)
SAX解析过程
//1. 使用SAXParserFactory的newInstance方法创建产生解析器的工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//2.用工厂的newSAXParser方法创建解析器
SAXParser parser = factory.newSAXParser();
//3.得到xml文档读取器
XMLReader reader = parser.getXMLReader();
//为读取器设置内容处理器(还可以设置其他处理器,用到什么设置什么)
reader.setContentHandler(new 你写的处理器());
//4.利用读取器解析xml文档
reader.parse("src/book.xml");
接下来需要写一个类实现ContentHandler这个接口,然后在需要的方法中加入操作
小提示:其实此处实现ContentHandler这个接口会覆盖好多方法,为了不必要的书写,建议继承ContentHandler的实现类DefaultHandler,然后覆盖你所要的方法就OK了。
注:eclipse中覆盖方法的快捷键为Alt+Shift+S,选择Override/Implement Methods
例如:
<?xml version="1.0"encoding="UTF-8"?>
<书架>
<书>
<书名>javaweb开发</书名>
<作者>张孝祥</作者>
<售价>59元</售价>
</书>
<书>
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价>28.00元</售价>
</书>
</书架>
//获取整个xml文档内容的处理器
class ListHandler extends DefaultHandler{
//解析到开始标签的方法
public voidstartElement(String uri, String localName, String name,
Attributesatts) throws SAXException {
System.out.println("<" + name + ">");
}
//解析到结束标签的方法
public void endElement(Stringuri, String localName, String name)
throws SAXException {
System.out.println("</" + name + ">");
}
//解析到内容的方法
public void characters(char[] ch, int start, int length)
throws SAXException {
System.out.println(newString(ch,start,length));
}
}
//获取到第二个书名标签的值
class BookNameHandler extends DefaultHandler{
//定义currentTag意思为当前的标签
private String currentTag;
private int count; //记住当前解析到了几个书名标签
@Override
public voidstartElement(String uri, String localName, String name,
Attributesattributes) throws SAXException {
currentTag =name;
if("书名".equals(currentTag)){
count++;
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if("书名".equals(currentTag)&& count==1){
System.out.println(newString(ch,start,length)); //JavaScript网页开发
}
}
}
//把书的数据封装到javabean的处理器此处为开发中比较常见的方法
class BeanListHandler extends DefaultHandler{
//建立一个集合,用于存储书对象,在这之前建立一个class放入私有的书名作者之类的变量,提供set与get方法
//定义currentTag意思为当前的标签
private String currentTag;
private Book book;
private List list = new ArrayList();
public List getBooks(){
return list;
}
@Override
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
currentTag = name;
if("书".equals(name)){
book = new Book();
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//此处最好写字符串.equals方法,为了将currentTag置为空后,再调用发生空指针异常,或者加上不为空的判断
if(currentTag != null && currentTag.equals("书名")){
book.setBookname(new String(ch,start,length));
}
if(currentTag != null && currentTag.equals("作者")){
book.setBookname(new String(ch,start,length));
}
if(currentTag != null && currentTag.equals("售价")){
book.setBookname(new String(ch,start,length));
}
}
@Override
public void endElement(String uri, String localName, String name)
throws SAXException {
if(name.equals("书")){
list.add(book);
}
//此处将currentTag置为空是防止xml空白处在此用set方法将之前的值覆盖。
currentTag = null;
}
}