使用java的Sax对xml文件进行解析,大致可分为以下几个步骤
1、创建SAXParserFactory实例
2、创建SAXParser实例
3、创建一个继承自DefaultHandler的handler实例
4、使用handler对xml文档进行解析
一、要解析的book.xml文档如下
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book id="156">
<name>计算机网络</name>
<author>谢希仁</author>
<price>39</price>
<year>2013</year>
</book>
<book id="234">
<name>计算机操作系统</name>
<author>佚名</author>
<price>40</price>
<year>2013</year>
<edition>第四版</edition>
</book>
<book id="367">
<name>计算机组成原理</name>
<price>35</price>
<year>2013</year>
<edition>第三版</edition>
</book>
</bookstore>
// 创建SAXParserFactory实例
SAXParserFactory spf = SAXParserFactory.newInstance();
三、创建SAXParser实例
// 创建SAXParser实例
SAXParser parser = spf.newSAXParser();
四、创建DefaultHandler实例(这一步是非常关键的一步)
在介绍DefaultHandler之前,必须对xml的节点和元素进行区分,可以参考http://blog.csdn.net/kingsonyoung/article/details/51985327
DefaultHandler有如下几个接口
一般前两个方法,开始解析和结束解析文档的不需要做处理外,我们的所有操作都是在解析节点部分,我们调用startElement 开始解析节点,然后调用characters 保存节点的内容,最后调用endElement表示结束对一个节点的访问
public void startDocument() {
// 开始解析文档
}
public void endDocument() {
// 文档解析结束
}
public void startElement(String uri, String localName, String qName, Attributes attributes) {
// 开始解析元素节点,注意,此处只是会解析元素节点,即 XML 标签,遇到回车等textNode时不会执行此函数
}
public void characters(char[] ch, int start, int length) {
// 保存节点内容,此处会将回车等textNode的回车符也进行解析
}
public void endElement(String uri, String localName, String qName) {
// 结束解析元素节点
}
下面是一个解析book.xml的Handler
public class MyHandler extends DefaultHandler {
int bookIndex = 0;
/**
* 用来遍历开始标签,每走到一个开始标签,如<div>,<book>等不带/的标签,就会调用一次该方法
*
* @param uri
* @param localName
* @param qName
* 节点名,即标签名称
* @param attributes
* 标签的属性
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// 调用DefaultHandler类的startElement方法
super.startElement(uri, localName, qName, attributes);
// 如果是book开始节点
if ("book".equals(qName)) {
bookIndex++;
// 获取id属性值
String id = attributes.getValue("id");
System.out.println("id是:" + id);
}
// 如果是book节点下的子节点的开始节点
else if (!"bookstore".equals(qName)) {
System.out.print(qName + ":");
}
}
/**
* 保存元素节点中的文本节点的文本内容
*
* @param ch
* 节点中的内容
* @param start
* 开始标签的位置
* @param length
* 开始标签的位置到结束标签的位置的长度
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
String value = new String(ch, start, length);
// 如果节点内容不为空,主要是用来过滤回车符形成的textNode
if (!value.trim().equals("")) {
System.out.println(value);
}
}
/**
* 用来遍历结束标签
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
// 如果是book节点结束
if ("book".equals(qName)) {
System.out.println("--------------结束遍历第" + bookIndex + "本书---------------");
}
}
/**
* 用来标识解析开始
*/
@Override
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("开始解析xml文件");
}
/**
* 用来标识解析结束
*/
@Override
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("结束解析xml文件");
}
}
五、使用handler对xml文档进行解析
// 开始解析
parser.parse("book.xml", new MyHandler());
六、运行结果
运行结果如下:
<span style="font-family: Tahoma, Verdana, Geneva, Arial, Helvetica, sans-serif;">开始解析xml文件
id是:156
name:计算机网络
author:谢希仁
price:39
year:2013
--------------结束遍历第1本书---------------
id是:234
name:计算机操作系统
author:佚名
price:40
year:2013
edition:第四版
--------------结束遍历第2本书---------------
id是:367
name:计算机组成原理
price:35
year:2013
edition:第三版
--------------结束遍历第3本书---------------
结束解析xml文件</span>
在重写DefaultHandler的startElement,characters接口时需注意一下细节
1、当遇到一个开始元素节点时就会执行一次startElement,这里需要特别注意,元素节点指的是一个xml标签,也就是说遇到开始文本节点不会执行该方法
下面我们把节点名都打印出来,发现的确只是打印出了xml标签,即元素节点。而并没有#text类型的文本节点
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// 调用DefaultHandler类的startElement方法
super.startElement(uri, localName, qName, attributes);
System.out.println(qName);
}
打印结果如下:
开始解析xml文件
bookstore
book
name
author
price
year
book
name
author
price
year
edition
book
name
price
year
edition
结束解析xml文件
2、当遇到空格或者换行符时,也会触发characters方法。