Android之SAX解析XML
来源:互联网 发布:linux c fork 编辑:程序博客网 时间:2024/04/29 11:32
SAX 全称“Simple API for XML”,是以事件流来解读xml,也就是说:它不需要读入整个文档,而是文档的读入过程中边读边触发事件函数完成解析。所以用它解析XML速度很快,占用内存小,适合解析较大XML文件。
解析之前需要向XMLReader注册—ContentHandler,也就是事件监听器,它必须继承自DefaultHandler类,实现下面我五个方法;
/** * 在开始XML解析的时候调用 * @throws SAXException */ @Override public void startDocument() throws SAXException {}
/** * 开始解析某个节点的时候调用 * @param uri xml文档的命名空间 * @param localName 当前标签的名字 * @param qName 带命名空间的标签名字 * @param attributes 标签的属性集 * @throws SAXException */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {}
/** * 获取节点中内容的时候调用 * @param ch 当前读取到的TextNode(文本节点)的字节数组 * @param start 字节开始的位置,为0则读取全部 * @param length 当前TextNode的长度 * @throws SAXException */ @Override public void characters(char[] ch, int start, int length) throws SAXException {}
/** * 完成解析某个节点的时候调用 * @param uri xml文档的命名空间 * @param localName 当前结束标签的名字 * @param qName 带命名空间标签的名字 * @throws SAXException */ @Override public void endElement(String uri, String localName, String qName) throws SAXException {}
/** * 完成整个XML解析的时候调用 * @throws SAXException */ @Override public void endDocument() throws SAXException {}
SAX解析步骤:
1.得到XML的输入流。
2.得到SAX解析工厂。( SAXParserFactory factory=SAXParserFactory.newInstance();)
3.有解析工厂产生一个SAX解析器。(XMLReader xmlReader=factory.newSAXParser().getXMLReader();)
4.将ContentHandler的实例设置到XMLReader中。(xmlReader.setContentHandler(handler);)
5.开始执行解析。(xmlReader.parse(inputStream));)
下面我们通过例子,来学习SAX解析XML文件
服务器放的XML数据:
这里我是用自己电脑上的Tomcat搭建的服务器,文件存放地址:TomCat安装目录/Tomcat7.0/webapps/ROOT/get_data.xml.
实现效果:
(1)activity_main.xml文件
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/send_request" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="click" android:text="Send Request" /> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/response_text" android:layout_width="match_parent" android:layout_height="wrap_content" /> </ScrollView></LinearLayout>
(2)ContentHandler.java
package com.example.xmlandsax;import android.util.Log;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;import java.util.ArrayList;import java.util.List;public class ContentHandler extends DefaultHandler { private final static String TAG="AndroidSaxParseXML"; private String nodeName; private StringBuilder id; private StringBuilder name; private StringBuilder version; private List<String> app; public List<String> getApp(){ return app; } /** * 在开始XML解析的时候调用 * @throws SAXException */ @Override public void startDocument() throws SAXException { super.startDocument(); Log.i(TAG,"startDocument"); id=new StringBuilder(); name=new StringBuilder(); version=new StringBuilder(); app=new ArrayList<String>(); } /** * 开始解析某个节点的时候调用 * @param uri xml文档的命名空间 * @param localName 标签的名字 * @param qName 带命名空间的标签名字 * @param attributes 标签的属性集 * @throws SAXException */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); Log.i(TAG,"startElement="+localName); //记录当前节点名 nodeName=localName; } /** * 获取节点中内容的时候调用 * @param ch 当前读取到的TextNode(文本节点)的字节数组 * @param start 字节开始的位置,为0则读取全部 * @param length 当前TextNode的长度 * @throws SAXException */ @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); Log.i(TAG,(new String(ch,start,length)).toString().trim()); //根据当前的节点名判断将内容添加到哪一个StringBuilder对象中 if("id".equals(nodeName)){ id.append(ch,start,length); }else if("name".equals(nodeName)){ name.append(ch,start,length); }else if("version".equals(nodeName)){ version.append(ch,start,length); } } /** * 完成解析某个节点的时候调用 * @param uri xml文档的命名空间 * @param localName 当前结束标签的名字 * @param qName 带命名空间标签的名字 * @throws SAXException */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); Log.i(TAG,"EndElement="+localName); if("app".equals(localName)){ app.add("id is"+id.toString().trim()+",name is"+name.toString().trim()+",version is"+version.toString().trim()+";\n"); //最后要将StringBuilder清空掉 id.setLength(0); name.setLength(0); version.setLength(0); } } /** * 完成整个XML解析的时候调用 * @throws SAXException */ @Override public void endDocument() throws SAXException { super.endDocument(); Log.i(TAG,"endDocument"); }}(3)MainActivity.java
package com.example.xmlandsax;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.TextView;import org.xml.sax.InputSource;import org.xml.sax.SAXException;import org.xml.sax.XMLReader;import java.io.StringReader;import java.util.List;import javax.xml.parsers.SAXParserFactory;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;public class MainActivity extends AppCompatActivity { private TextView response_text; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); response_text = (TextView) this.findViewById(R.id.response_text); } public void click(View v) { sendRequestWithHttpURLConnection(); } public void sendRequestWithHttpURLConnection() { new Thread(new Runnable() { @Override public void run() { try { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("http://10.0.2.2:8080/get_data.xml") .build(); Response response = client.newCall(request).execute(); String responseData = response.body().string(); parseXMLWithSax(responseData); } catch (Exception e) { e.printStackTrace(); } } }).start(); } public void parseXMLWithSax(String xmlData){ try { //得到SAX解析工厂 SAXParserFactory factory=SAXParserFactory.newInstance(); //由解析工厂生产一个SAX解析器 XMLReader xmlReader=factory.newSAXParser().getXMLReader(); ContentHandler handler=new ContentHandler(); //将ContentHandler的实例设置到XMLReader中 xmlReader.setContentHandler(handler); //开始执行解析 xmlReader.parse(new InputSource(new StringReader(xmlData))); List<String> app=handler.getApp(); showResponseToUI(app.toString()); } catch (SAXException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } private void showResponseToUI(final String response){ runOnUiThread(new Runnable() { @Override public void run() { //在这里进行UI操作,将结果显示到界面上 response_text.setText(response); } }); }}(4)build.gradle
网络请求用的是OKHttp,所以要在gradle中加入依赖。
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:24.2.1' compile 'com.squareup.okhttp3:okhttp:3.4.1'}(5)AndroidManifest.xml
需要网络请求权限
<uses-permission android:name="android.permission.INTERNET" />根据以上的项目,我们来分析一下SAX解析的过程:
先看一下上面项目运行后的日志:
1.xml解析开始,startDocument被调用,这个方法在整个XML文件解析过程中只调用一次,我们可以在这个函数中做一些准备,比如说初始化变量等。
2.当解析一个标签的时候,如果该标签有子标签,则先回调该标签的startElement方法,然后触发characters解析该标签的内容,然后子标签触发startElement-characters-endElement(子标签触发),最后该标签触发endElement,该标签解析结束。(这个过程类似与递归,必须明白这一句话。)
下面我来画张图帮助理解一下:
看完上图,可以理解SAX解析XMl的过程。
- Android之SAX解析XML
- Android 解析XML 之SAX
- Android之SAX解析XML
- Android之SAX解析XML
- android xml解析之SAX
- Android之SAX解析XML
- Android xml解析之Sax
- Android之SAX解析XML
- android之sax解析xml文件
- android开发之sax解析xml文档
- Android之SAX解析XML文件
- android之sax解析xml文件
- android之sax解析xml文件 .
- Android 解析XML之二 SAX
- android之sax解析xml文件
- Android学习笔记--解析XML之SAX
- android之sax解析xml文件
- Android之SAX解析dom的XML
- Android中的PopupWindow用法样例:
- VS2015 debug_error C4996: 'fopen'问题_调用文本文档问题
- 浮点型失去精度的解释
- Git&GitHub学习笔记之(二)Git命令操作
- spring cloud 问题描述1
- Android之SAX解析XML
- 关于jQuery绑定事件on和bind的区别详解 -- sanai
- iOS开发问题之:解决iOS网页调用系统相册显示英文的问题
- 操作系统面试知识点
- Spring Framework 5.0的响应式微服务
- Android的消息机制概述
- Nginx事件驱动总结
- BigDecimal 元转分-加减乘除
- jquery中ready和load的区别