《第一行代码》第二版 学习总结23 XML数据解析
最近利用下班时间,找了看什么书比较适合初学android的朋友,很多人推荐了这本书,于是就买了一本,感觉看书,思考,动手,再思考和总结这样过程还是很有必要的,于是就打算把自己学习的东西简单的总结一下;方便自己以后查找,也有利于学习的巩固。在这里首先要感谢一下书籍的作者——郭霖前辈。
之前几篇介绍了关于如何访问网络数据,HttpURLConnection基本使用,OkHttp基本使用;因为网络传输数据(文本数据)常用的用两种(XML和JSON)后者更轻量,但是语义没有前者好;但是毫无疑问,对于两种数据的处理,是我们网络访问数据避免不了的问题,今天我们就先来来看看Android对XML的解析实现。但是关于XML这里肯定不会展开介绍,它也是一种语言(可扩展性标记语言),主要应用就是保存数据,编写配置文件等。
1,准备工作
为了可以自定义xml数据以及后续的json数据,这里的网络数据,我准备使用本地服务器数据,所以首先本地的安装一个服务器,书中推荐的是很轻量的Apache服务器,具体的安装和配置主要如下:
(1)下载链接
估计给了链接还是不知道下载什么,因为最开始我也是有这样的疑惑,没关系,看下面三张图就可以了
(2)安装注意事项
因为是很早之前安装的了,所以具体流程就不多说了,也没有什么,最需要注意的一点就是本地文件的位置目录以及服务器配置文件目录。具体看下图:
其实到这里,你可以先在浏览器中输入http://127.0.0.1/试试看什么效果(其默认端口是80还是88还是8080还是8088哈哈,你可以去配置文件中查看和修改,有时出现端口冲突就可以修改一下;修改之后访问必须要加端口号)
2,代码实现
实现步骤(Pull方式):
第一步:获取网络数据
第二步:获取XML解析器工厂实例
第三步:获取XML解析器
第四步:为解析器设置XML数据源
第五步:开始解析流程 ;获取EventType,判断其类型,如果是节点入口,再获取节点内数据
实现步骤(Sax方式):
第一步:自定义类继承DefaultHandler,重写里面方法用于数据获取
第二步:获取网络数据
第三步:获取Sax解析器工厂
第四步:获取Sax解析器
第五步:实例化一个自定义类并将其设置到解析器中
第六步:设置XMl数据源
(具体的数据解析和获取是在自定义类中重写方法完成的)
示例代码:
XMLDataHandler.java代码:
package com.hfut.operationxmldata; import android.util.Log; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * author:why * created on: 2018/4/12 16:56 * description: */ public class XMLDataHandler extends DefaultHandler { private static final String TAG = "XMLDataHandler"; public static StringBuilder saxParseData=new StringBuilder(); private String nodeName; private StringBuilder studentName; private StringBuilder studentAge; private StringBuilder studentSex; @Override public void startDocument() throws SAXException { saxParseData.setLength(0); studentName = new StringBuilder(); studentAge = new StringBuilder(); studentSex = new StringBuilder(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { nodeName = localName; } @Override public void characters(char[] ch, int start, int length) throws SAXException { if ("name".equals(nodeName)) { studentName.append(ch, start, length); // Log.i(TAG, "characters: "+studentName.toString()); } else if ("age".equals(nodeName)) { studentAge.append(ch, start, length); } else if ("sex".equals(nodeName)) { studentSex.append(ch, start, length); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if("student".equals(localName)){ //通过trim()去除空格和换行等 saxParseData.append("name: "+studentName.toString().trim()+" "); saxParseData.append("age: "+studentAge.toString().trim()+" "); saxParseData.append("sex: "+studentSex.toString().trim()+" "); saxParseData.append("\n"); //清空数据 studentName.setLength(0); studentAge.setLength(0); studentSex.setLength(0); } } @Override public void endDocument() throws SAXException { super.endDocument(); } }
MainActivity.java代码:
package com.hfut.operationxmldata; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.TextView; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserFactory; import java.io.IOException; import java.io.StringReader; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; /** * */ public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; EditText xmlName; TextView xmlContent; public final String localURL = "http://192.168.31.2:8088/"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initUI(); } private void initUI() { xmlName = findViewById(R.id.xml_name); xmlContent = findViewById(R.id.xml_content); } public void pullParseXML(View view) { getData(view.getId()); } public void saxParseXML(View view) { getData(view.getId()); } private void getData(final int id) { final StringBuilder stringBuilder=new StringBuilder(); new Thread(new Runnable() { @Override public void run() { String tempUrl = localURL + xmlName.getText().toString(); OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder() .url(tempUrl) .build(); try { Response response = okHttpClient.newCall(request).execute(); String result = response.body().string(); switch (id) { case R.id.pullWay: stringBuilder.append("解析方式为:pullWay\n\n").append("xml源数据为:\n\n") .append(result+"\n\n").append("解析数据为:\n\n"+pullParse(result)); break; case R.id.saxWay: stringBuilder.append("解析方式为:saxWay\n\n").append("xml源数据为:\n\n") .append(result+"\n\n").append("解析数据为:\n\n"+saxParse(result)); break; default: } showResult(stringBuilder.toString()); } catch (IOException e) { e.printStackTrace(); } } }).start(); } //pull解析xml文件 private final String pullParse(String xmlData) { StringBuilder stringBuilder = new StringBuilder(); try { //创建工厂 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); //获取实例 XmlPullParser xmlPullParser = factory.newPullParser(); //向解析器添加xml数据 xmlPullParser.setInput(new StringReader(xmlData)); int eventType = xmlPullParser.getEventType(); String name = ""; String sex = ""; String age = ""; while (eventType != XmlPullParser.END_DOCUMENT) { String nodeName = xmlPullParser.getName(); switch (eventType) { case XmlPullParser.START_TAG: { if ("name".equals(nodeName)) { name = xmlPullParser.nextText(); stringBuilder.append("name:" + name + " "); } else if ("sex".equals(nodeName)) { sex = xmlPullParser.nextText(); stringBuilder.append("sex:" + sex + " "); } else if("age".equals(nodeName)){ age = xmlPullParser.nextText(); stringBuilder.append("age:" + age + " "); } else{ //System.out.println("其他数据!"); Log.i(TAG, "pullParse: 其他数据"); } } break; case XmlPullParser.END_TAG: { stringBuilder.append("\n"); } break; default: } try { eventType = xmlPullParser.next(); } catch (IOException e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } System.out.println("result:\n" + stringBuilder.toString()); return stringBuilder.toString(); } //sax解析xml文件 private final String saxParse(String xmlData){ //获取工厂 SAXParserFactory factory=SAXParserFactory.newInstance(); XMLDataHandler handler=new XMLDataHandler();; try { //获取xml阅读器实例 XMLReader reader=factory.newSAXParser().getXMLReader(); //设置阅读器读取方式 reader.setContentHandler(handler); //设置读取的xml数据String--InputSource reader.parse(new InputSource(new StringReader(xmlData))); } catch (Exception e) { e.printStackTrace(); } //返回数据 return handler.saxParseData.toString(); } private void showResult(final String s) { runOnUiThread(new Runnable() { @Override public void run() { xmlContent.setText(""); xmlContent.setText(s); } }); } }
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" tools:context="com.hfut.operationxmldata.MainActivity"> <EditText android:layout_marginTop="20dp" android:id="@+id/xml_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入xml文件名称" android:textSize="20dp" /> <Button android:id="@+id/pullWay" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:onClick="pullParseXML" android:text="pull解析XML" android:textSize="20dp" /> <Button android:id="@+id/saxWay" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:onClick="saxParseXML" android:text="sax解析XML" android:textSize="20dp" /> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="10dp"> <TextView android:textSize="20dp" android:textColor="@color/colorPrimary" android:id="@+id/xml_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="显示服务器xml文件数据" /> </ScrollView> </LinearLayout>
主配置文件AndroidManifest.xml代码:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.hfut.operationxmldata"> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
3,运行结果
第一步:运行程序
第二步:输入文件名称,点击"PULL解析XML"
第三步:点击“SAX解析XML”