您的位置:首页 > 编程语言 > Java开发

SAX方式解析XML文件的方法分析

2016-01-07 14:24 363 查看
SAX(Simple API for XML)SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理方法,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。SAX解析方式适用于大型文档,因为他的解析是逐行进行不用像DOM中那样为所有节点创建对象,这样效率大大提高,所以虽然它不是W3C标准,但它却得到了广泛认可。

这是一个需要解析的XML文件:
<?xml version="1.0" encoding="utf-8"?>
<bookstore>
<book id="2" type="长篇小说">
<name>《平凡的世界》</name>
<author>路遥</author>
<year>2014</year>
<price>22</price>
<outline>《平凡的世界》是中国作家路遥创作的一部百万字的小说。
</outline>>
</book>
<book id="7" type="外文小说">
<name>"Gone with the Wind"</name>
<author>Margaret.Mitchell</author>
<price>99</price>
<language>English</language>
<outline>《飘》是美国女作家玛格丽特·米切尔(1900—1949)十年磨一剑的作品,也是惟一的作品。</outline>
</book>
<book id="13" type="中文小说">
<name>《秦腔》</name>
<author>贾平凹</author>
<price>99</price>
<language>汉语</language>
<outline>《秦腔》以两条线展开,一条线是秦腔戏曲,一条线是农民与土地的关系。</outline>>
</book>

</bookstore>
如上所示,我们将从首行开始逐一进行解析,SAX解析时会识别开始标签和结束标签,这些用相应的方法进行实现,具体如下:需要注意的是:DefaultHandler类是SAX2事件处理程序的默认基类。它实现了EntityResolver、DTDHandler、ContentHandler和ErrorHandler这四个接口。包含这四个接口的所有方法,所以我们在编写事件处理程序时,可以不用直接实现这四个接口,而继承该类,然后重写我们需要的方法即可我们SAX方法解析XML文件时需要一个Handler类来提供解析的方法,里面包含了重写的继承于DefaultHandler类的两种方法,分别有开始和结束的方法
package Handler;

import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import entity.Book;

public class SAXParserHandlerBook extends DefaultHandler{

int bookIndex = 0;

Book book = null;

private ArrayList<Book> bookList = new ArrayList<Book>();

public ArrayList<Book> getBookList(){
return bookList;

}
//用来标识解析开始和结束
@Override
public void startDocument() throws SAXException {

super.startDocument();

System.out.println("SAX解析开始");
}
@Override
public void endDocument() throws SAXException {

super.startDocument();

System.out.println("SAX解析开始");
}

// 用来遍历XML文件的开始标签
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

super.startElement(uri, localName, qName, attributes);
//开始解析book节点的属性

//注意:这种方法是知道节点名为book且其属性只有id一个属性,只需获取其属性值的情况
if(qName.equals("book")){
//在清空之前保存
bookList.add(book);
//保证每次运行到这里的时候book都是null以便保存其他子节点的值
book = null;
//创建book对象
book = new Book();
//这边我们需要一个全局变量来记录遍历进行到哪本书
bookIndex++;

//			String value = attributes.getValue("id");
//【注意这种方法是知道了属性的属性名来获取属性值的简便方法】
//			System.out.println("book的属性值:"+attributes.getValue("id"));

//在不知道book节点的属性数量以及属性名和属性值的情况下进行解析
int len = attributes.getLength();

System.out.println("*************************开始遍历第"+(bookIndex)+"本书*************************");

for(int i = 0; i < len; i ++){

System.out.println("第"+(i+1)+"个属性:");

System.out.println("属性名是:"+ attributes.getQName(i));

System.out.println("属性值是:"+ attributes.getValue(i));
System.out.println();

if(attributes.getQName(i).equals("id")){

book.setId(attributes.getQName(i));

}else if(attributes.getQName(i).equals("type")){

book.setId(attributes.getQName(i));
}
}
}

//获取book节点的所有子节点节点名
if(qName != "book"){

System.out.println("节点名:"+qName);

}else if(qName.equals("author")){

book.setAuthor(value);

}else if(qName.equals("year")){

book.setYear(value);

}else if(qName.equals("lauguage")){

book.setLauguage(value);

}else if(qName.equals("price")){

book.setPrice(value);

}else if(qName.equals("outline")){

book.setOutline(value);

}else if(qName.equals("name")){

book.setName(value);
}
}
//以上部分用switch语句实现代码开起来应该会相对整洁一点,
String value = null;

@Override
public void characters(char[] ch, int start, int length) throws SAXException {

super.characters(ch, start, length);

value = new String(ch, start, length);

if(!value.trim().equals("")){

System.out.println("节点值:"+value);

System.out.println();
}
}

// 用来遍历XML结束标签(non-Javadoc)
@see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)

@Override
public void endElement(String uri, String localName, String qName) throws SAXException {

super.endElement(uri, localName, qName);
//判断针对一本书是否已经遍历结束
if(qName.equals("book")){

System.out.println("===========================结束遍历===========================");
}
}

}
Handler类准备好之后我们来编写测试程序看一下解析结果:
package test_XML;

import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;

import Handler.SAXParserHandlerBook;

public class TestSAX {

public static void main(String[] args) throws ParserConfigurationException, SAXException{

try {

// 是创建一个Handler处理类,去逐个分析每一个节点,并且是顺序的

//1.通过SAXParseFactory的静态方法newInstance()来获取SAXParseFactory的实例对象factory
SAXParserFactory factory = SAXParserFactory.newInstance();

//2.通过SAXParserFactory 静态方法NewSAXParser()方法返回一个SAXParser类的实例;
SAXParserHandlerBook handler = new SAXParserHandlerBook();
//3.重写startElement、endElement、startDocument、endDocument方法
/*
* 可以将其保存在继承了DefaultHandler类的SAXParserHandler类中
* 然后创建SAXParserHandler类的对象并将其传入SAXParser类的对象parser的parser方法;
*/
SAXParser parser=factory.newSAXParser();

parser.parse("book.xml", handler);

} catch (SAXException e) {

e.printStackTrace();

}catch (IOException e) {

e.printStackTrace();
}
}
}

以下是解析结果:SAX解析开始
节点名:bookstore
*************************开始遍历第1本书*************************
第1个属性:
属性名是:id
属性值是:2

第2个属性:
属性名是:type
属性值是:长篇小说

节点名:name
节点值:《平凡的世界》

节点名:author
节点值:路遥

节点名:year
节点值:2014

节点名:price
节点值:22

节点名:outline
节点值:《平凡的世界》是中国作家路遥创作的一部百万字的小说。

===========================结束遍历===========================
*************************开始遍历第2本书*************************
第1个属性:
属性名是:id
属性值是:7

第2个属性:
属性名是:type
属性值是:外文小说

节点名:name
节点值:"Gone with the Wind"

节点名:author
节点值:Margaret.Mitchell

节点名:price
节点值:99

节点名:language
节点值:English

节点名:outline
节点值:《飘》是美国女作家玛格丽特·米切尔(1900—1949)十年磨一剑的作品,也是惟一的作品。

===========================结束遍历===========================
*************************开始遍历第3本书*************************
第1个属性:
属性名是:id
属性值是:13

第2个属性:
属性名是:type
属性值是:中文小说

节点名:name
节点值:《秦腔》

节点名:author
节点值:贾平凹

节点名:price
节点值:99

节点名:language
节点值:汉语

节点名:outline
节点值:《秦腔》以两条线展开,一条线是秦腔戏曲,一条线是农民与土地的关系。

节点值:>

===========================结束遍历===========================
DOM(Document Object Model)是表示和处理一个HTML或XML文档的常用方法,DOM的优势是易用性强,使用DOM这种解析方法的时候,将把所有的XML文档信息都存于内存中,遍历操作简单快速。SAX(Simple API for XML)不是W3C的标准,但是对于大型XML文件的解析效率要高与DOM。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java XML SAX