您的位置:首页 > 其它

XML解析(二) SAX解析

2015-07-25 15:49 274 查看
XML解析之SAX解析:

SAX解析器:SAXParser类同DOM一样也在javax.xml.parsers包下,此类的实例可以从 SAXParserFactory.newSAXParser() 方法获得。

注意SAXParser的parse()方法:

parse(String uri, DefaultHandler dh),parse(File f, DefaultHandler dh)等都需要传递一个DefaultHandler的对象。

查看API帮助手册可知,SAX解析是事件驱动的,DefaultHandler是SAX2 事件处理程序的默认基类,在 org.xml.sax.helpers 软件包中,由它来实现相关事件的回调,并提供所有回调方法默认的空实现。

DefaultHandler的常用回调方法:

void startDocument():接收文档开始的通知。

void startElement(String uri, String localName, String qName, Attributes attributes): 接收元素开始的通知。

void characters(char[] ch, int start, int length): 接收元素中字符数据的通知。

void endElement(String uri, String localName, String qName):接收元素结束的通知。

void endDocument(): 接收文档结束的通知。

为什么说SAX是推模式解析?

SAX 解析器采用了基于事件的模型,它在解析XML文档的时候可以触发一系列的事件,由解析器自动调用相应事件方法,而不是由我们自己去调用。

使用SAX解析XML,观察各种事件回调:

有如下要解析的xml文件:

1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
3 <students>
4
5     <student id="003">
6
7         <name>xiaoqiao</name>
8
9     </student>
10
11 </students>


解析代码:

1 public class SaxXmlParser {
2
3          public static void main(String[] args) {
4
5                    SAXParserFactory factory = SAXParserFactory.newInstance();
6
7                    try {
8
9                             SAXParser parser = factory.newSAXParser();
10
11                             parser.parse("students_bak.xml", new DefaultHandler(){
12
13                                      @Override
14
15                                      public void characters(char[] ch, int start, int length)
16
17                                                         throws SAXException {
18
19                                                System.out.println("read characters:"+new String(ch,start,length));
20
21                                      }
22
23                                      @Override
24
25                                      public void endDocument() throws SAXException {
26
27                                                System.out.println("end document...");
28
29                                      }
30
31                                      @Override
32
33                                      public void endElement(String uri, String localName, String qName)
34
35                                                         throws SAXException {
36
37                                                System.out.println("end element:<"+qName+">");
38
39                                      }
40
41                                      @Override
42
43                                      public void startDocument() throws SAXException {
44
45                                                System.out.println("start document...");
46
47                                      }
48
49                                      @Override
50
51                                      public void startElement(String uri, String localName, String qName, Attributes attributes)
52
53                                                         throws SAXException {
54
55                                                System.out.println("start element:<"+qName+">");
56
57                                                if(qName.equals("student")){
58
59                                                         System.out.println("id="+attributes.getValue("id"));
60
61                                                }
62
63                                      }
64
65                             });
66
67                    } catch (Exception e) {
68
69                             e.printStackTrace();
70
71                    }
72
73          }
74
75 }


上面代码在parse()方法中,第二个参数定义了一个继承自DefaultHandler的匿名内部类对象,重写了5个主要的事件回调方法,用以观察事件的触发过程。

在startElement()方法中qName存放的是节点名,attributes存放的是该节点的属性,endElement()方法同样。

运行结果:

start document...

start element:<students>

read characters:

start element:<student>

id=003

read characters:

start element:<name>

read characters:xiaoqiao

end element:<name>

read characters:

end element:<student>

read characters:

end element:<students>

end document...

首先回调的是startDocument()方法;

然后碰到<students>节点,回调startElement()方法;

<students>后面有回车,所以会触发characters()方法,输出当前读到的字符;

然后碰到<student>节点,回调startElement()方法,输出id属性值;

后面也有回车,所以会触发characters()方法,输出当前读到的字符;

然后碰到了<name>节点,回调startElement()方法;

后面是xiaoqiao,回调characters()方法;

然后到</name>,回调endElement()方法;

碰到回车,回调characters()方法;

到</student>,回调endElement()方法;

碰到回车,回调characters()方法;

到</students>,回调endElement()方法;

文档结束,回调endDocument()方法,解析工作结束。

如果有需要对文档进行别的处理操作,如查找某个节点等,可以重写响应的事件回调方法,添加上需要的逻辑的实现代码即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: