• Android学习——SAX解析方式


    SAX解析也是一种特别常用的 XML 解析方式,虽然它的用法比 Pull解析要复杂一些,但在语义方面会更加的清楚。通常情况下我们都会新建一个类继承自 DefaultHandler,并重写父类的五个方法,如下

     1 public class MyHandler extends DefaultHandler {
     2 @Override
     3 public void startDocument() throws SAXException {
     4 }
     5 @Override
     6 public void startElement(String uri, String localName, String qName,
     7 Attributes attributes) throws SAXException {
     8 }
     9 @Override
    10 public void characters(char[] ch, int start, int length) throws
    11 SAXException {
    12 }
    13 @Override
    14  
    15 public void endElement(String uri, String localName, String qName) throws
    16 SAXException {
    17 }
    18 @Override
    19 public void endDocument() throws SAXException {
    20 }
    21 }

    startDocument()方法会在开始 XML 解析的时候调用,
    startElement()方法会在开始解析某个结点的时候调用,characters()方法会在获取结点中内容
    的时候调用,endElement()方法会在完成解析某个结点的时候调用,endDocument()方法会在
    完成整个 XML 解析的时候调用。其中,startElement()、characters()和 endElement()这三个方
    法是有参数的,从 XML 中解析出的数据就会以参数的形式传入到这些方法中。需要注意的
    是,在获取结点中的内容时,characters()方法可能会被调用多次,一些换行符也被当作内容
    解析出来,我们需要针对这种情况在代码中做好控制。
    那么下面就让我们尝试用 SAX 解析的方式来实现和上一小节中同样的功能吧。新建一
    个 ContentHandler类继承自 DefaultHandler,并重写父类的五个方法,如下所示:

     1 public class ContentHandler extends DefaultHandler {
     2 private String nodeName;
     3 private StringBuilder id;
     4 private StringBuilder name;
     5 private StringBuilder version;
     6 @Override
     7 public void startDocument() throws SAXException {
     8 id = new StringBuilder();
     9 name = new StringBuilder();
    10 version = new StringBuilder();
    11 }
    12 @Override
    13 public void startElement(String uri, String localName, String qName,
    14 Attributes attributes) throws SAXException {
    15  
    16 // 记录当前结点名
    17 nodeName = localName;
    18 }
    19 @Override
    20 public void characters(char[] ch, int start, int length) throws
    21 SAXException {
    22 // 根据当前的结点名判断将内容添加到哪一个StringBuilder对象中
    23 if ("id".equals(nodeName)) {
    24 id.append(ch, start, length);
    25 } else if ("name".equals(nodeName)) {
    26 name.append(ch, start, length);
    27 } else if ("version".equals(nodeName)) {
    28 version.append(ch, start, length);
    29 }
    30 }
    31 @Override
    32 public void endElement(String uri, String localName, String qName) throws
    33 SAXException {
    34 if ("app".equals(localName)) {
    35 Log.d("ContentHandler", "id is " + id.toString().trim());
    36 Log.d("ContentHandler", "name is " + name.toString().trim());
    37 Log.d("ContentHandler", "version is " + version.toString().trim());
    38 // 最后要将StringBuilder清空掉
    39 id.setLength(0);
    40 name.setLength(0);
    41 version.setLength(0);
    42 }
    43 }
    44 @Override
    45 public void endDocument() throws SAXException {
    46 }
    47 }

    可以看到,我们首先给 id、name 和 version 结点分别定义了一个 StringBuilder 对象,并
    在 startDocument()方法里对它们进行了初始化。 每当开始解析某个结点的时候, startElement()
    方法就会得到调用,其中 localName 参数记录着当前结点的名字,这里我们把它记录下来。
    接着在解析结点中具体内容的时候就会调用 characters()方法, 我们会根据当前的结点名进行
    判断,将解析出的内容添加到哪一个 StringBuilder对象中。最后在 endElement()方法中进行
    判断,如果 app结点已经解析完成,就打印出 id、name 和 version的内容。需要注意的是,
    目前 id、name 和 version中都可能是包括回车或换行符的,因此在打印之前我们还需要调用
    一下 trim()方法,并且打印完成后还要将 StringBuilder的内容清空掉,不然的话会影响下一
    次内容的读取。
    接下来的工作就非常简单了,修改 MainActivity中的代码,如下所示:

     1 public class MainActivity extends Activity implements OnClickListener {
     2 ……
     3 private void sendRequestWithHttpClient() {
     4 new Thread(new Runnable() {
     5 @Override
     6 public void run() {
     7 try {
     8 HttpClient httpClient = new DefaultHttpClient();
     9 // 指定访问的服务器地址是电脑本机
    10 HttpGet httpGet = new HttpGet("http://10.0.2.2:8080/
    11 get_data.xml");
    12 HttpResponse httpResponse = httpClient.execute(httpGet);
    13 if (httpResponse.getStatusLine().getStatusCode() == 200) {
    14 // 请求和响应都成功了
    15 HttpEntity entity = httpResponse.getEntity();
    16 String response = EntityUtils.toString(entity,
    17 "utf-8");
    18 parseXMLWithSAX(response);
    19 }
    20 } catch (Exception e) {
    21 e.printStackTrace();
    22 }
    23 }
    24 }).start();
    25 }
    26 ……
    27 private void parseXMLWithSAX(String xmlData) {
    28 try {
    29 SAXParserFactory factory = SAXParserFactory.newInstance();
    30 XMLReader xmlReader = factory.newSAXParser().getXMLReader();
    31  
    32 ContentHandler handler = new ContentHandler();
    33 // 将ContentHandler的实例设置到XMLReader中
    34 xmlReader.setContentHandler(handler);
    35 // 开始执行解析
    36 xmlReader.parse(new InputSource(new StringReader(xmlData)));
    37 } catch (Exception e) {
    38 e.printStackTrace();
    39 }
    40 }
    41 }


    在得到了服务器返回的数据后,我们这次去调用 parseXMLWithSAX()方法来解析 XML
    数据。parseXMLWithSAX()方法中先是创建了一个 SAXParserFactory的对象,然后再获取到
    XMLReader对象,接着将我们编写的 ContentHandler的实例设置到 XMLReader中,最后调
    用 parse()方法开始执行解析就好了。
    现在重新运行一下程序,点击 Send Request 按钮后观察 LogCat 中的打印日志

  • 相关阅读:
    JS 知识点补充
    JS 数据之间类型的转化
    JS 数据的类型
    数据结构--数组、单链表和双链表介绍 以及 双向链表
    数据结构--队列
    数据结构--栈
    24. 两两交换链表中的节点
    23. 合并K个排序链表
    22. 括号生成
    21. 合并两个有序链表
  • 原文地址:https://www.cnblogs.com/znjy/p/14909193.html
Copyright © 2020-2023  润新知