編輯:Android開發實例
前言
既然要說XML解析,那麼先來聊聊什麼是XML。XML,可擴展標記語言 (Extensible Markup Language) ,用於標記電子文件使其具有結構性的標記語言,可以用來標記數據、定義數據類型,是一種允許用戶對自己的標記語言進行定義的源語言,這是百度百科的解釋。而XML是一種在Internet中傳輸數據的常見格式,它與HTML一樣,都是SGML(標准通用標記語言),無論你是需要通過Internet訪問數據,或者發送數據給Web服務,都可能需要用到XML的知識。恰恰Android應用程序需要和網絡交互,否則只是一款單機的無互動的應用程序,所以很可能在Android應用程序開發的過程中使用到XML。
由於XML的擴展性強,致使它需要有穩定的基礎規則來支持擴展,該語法規則需要注意的是:
Android中的XML
Android平台最大的優勢在於,上層應用基本可以利用Java編程語言開發,Java平台支持通過許多不同的方式來使用XML,並且大多數與XML相關的API已經在Android系統上得到了完全的支持。但是因為Android這個移動設備的局限性,一般僅考慮使用三種方式解析XML:
SAX
SAX是一種以事件驅動的XML API,由它定義的事件流可以指定從解析器傳到專門的處理程序的代碼的XML結構,簡單來講,它是解析速度快,占用內存少的接解析器,這種解析器比較適合Android等移動設備。
使用SAX的優點:
因為SAX的優勢是流的方式處理,當遇到一個標簽的時候,並不會記錄下之前所碰到的標簽。也就是說,在每個節點讀取會觸發的startElement()方法中,所能知道的信息,僅僅是當前的簽名的名字和屬性,至於標簽嵌套的結構,上層標簽的名字,是否有子元素與其他結構相關的信息,都是不知道的。 使用SAX解析XML的簡單步驟:上面一些重寫的方法通過一個XML文件來講解一下什麼時候被執行。
<?xml version="1.0" encoding="utf-8"?> startDocument
<persons> startElement
<person id="23"> startElement
<name nameid="1"> startElement
Jack characters
</name> endElement
<age> startElement
21 characters
</age> endElement
</person> endElement
</persons> endElement
SAXParserFactory類,定義了一個工廠API,使應用程序能夠配置和獲得基於SAX的解析器以解析XML文檔。它只有一個prctected的構造方法(單例模式),所以需要使用靜態的newInstance()方法來回的SAXParserFactory()對象。使用SAXParserFactory可以通過調用.newSAXParser()方法獲得一個SAXParser,通過SAXParser對象可以執行parser()方法,通過傳遞的參數設定XML流和解析器類。
示例程序
現在通過一個示例程序來講解一下SAX是怎麼解析XML文件的,這個示例程序是運行在Android平台上的,為了模擬真實情況,在IIS服務器上放置了一個靜態的XML文件,通過Android程序去讀取XML文件中的內容,在這個示例程序中,讀取person節點的值。因為是Android程序,所以別忘了賦予其訪問網絡的權限。
XML文件內容:
- <?xml version="1.0" encoding="utf-8"?>
- <persons>
- <person id="23">
- <name nameid="1">Jack</name>
- <age>21</age>
- </person>
- <person id="20">
- <name nameid="2">Dick</name>
- <age>23</age>
- </person>
- </persons>
步驟一,DefaultHandler類的繼承子類MyHandler:
- package cn.bgxt.handler;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import org.xml.sax.Attributes;
- import org.xml.sax.SAXException;
- import org.xml.sax.helpers.DefaultHandler;
- public class MyHandler extends DefaultHandler {
- private List<HashMap<String, String>> list = null; //解析後的XML內容
- private HashMap<String, String> map = null; //存放當前需要記錄的節點的XML內容
- private String currentTag = null;//當前讀取的XML節點
- private String currentValue = null;//當前節點的XML文本值
- private String nodeName = null;//需要解析的節點名稱
- public MyHandler(String nodeName) {
- // 設置需要解析的節點名稱
- this.nodeName = nodeName;
- }
- @Override
- public void startDocument() throws SAXException {
- // 接收文檔開始的通知。
- // 實例化ArrayList用於存放解析XML後的數據
- list = new ArrayList<HashMap<String, String>>();
- }
- @Override
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException {
- // 接收元素開始的通知。
- if (qName.equals(nodeName)) {
- //如果當前運行的節點名稱與設定需要讀取的節點名稱相同,則實例化HashMap
- map = new HashMap<String, String>();
- }
- //Attributes為當前節點的屬性值,如果存在屬性值,則屬性值也讀取。
- if (attributes != null && map != null) {
- for (int i = 0; i < attributes.getLength(); i++) {
- //讀取到的屬性值,插入到Map中。
- map.put(attributes.getQName(i), attributes.getValue(i));
- }
- }
- //記錄當前節點的名稱。
- currentTag = qName;
- }
- @Override
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- // 接收元素中字符數據的通知。
- //當前節點有值的情況下才繼續執行
- if (currentTag != null && map != null) {
- //獲取當前節點的文本值,ch這個直接數組就是存放的文本值。
- currentValue = new String(ch, start, length);
- if (currentValue != null && !currentValue.equals("")
- && !currentValue.equals("\n")) {
- //讀取的文本需要判斷不能為null、不能等於”“、不能等於”\n“
- map.put(currentTag, currentValue);
- }
- }
- //讀取完成後,需要清空當前節點的標簽值和所包含的文本值。
- currentTag = null;
- currentValue = null;
- }
- @Override
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- // 接收元素結束的通知。
- if (qName.equals(nodeName)) {
- //如果讀取的結合節點是我們需要關注的節點,則把map加入到list中保存
- list.add(map);
- //使用之後清空map,開始新一輪的讀取person。
- map = null;
- }
- }
- public List<HashMap<String, String>> getList() {
- return list;
- }
- }
因為XML文件是放在服務器上的,需要寫一個HttpUitils類讀取服務器上XML文件,使用的是URLHttpConnection的方式讀取,如果不了解URLHttpConnection的朋友,可以看之前的文章:http://www.fengfly.com/plus/view-213371-1.html。下面直接附上代碼:
- package cn.bgxt.http;
- import java.io.InputStream;
- import java.net.HttpURLConnection;
- import java.net.URL;
- public class HttpUtils {
- public HttpUtils() {
- }
- public static InputStream getXML(String path) {
- try {
- URL url=new URL(path);
- if(url!=null)
- {
- HttpURLConnection connection=(HttpURLConnection)url.openConnection();
- connection.setDoInput(true);
- connection.setConnectTimeout(3000);
- connection.setRequestMethod("GET");
- int requesetCode=connection.getResponseCode();
- if(requesetCode==200)
- {
- //如果執行成功,返回HTTP響應流
- return connection.getInputStream();
- }
- }
- } catch (Exception e) {
- // TODO: handle exception
- }
- return null;
- }
- }
還需要一個調用SAXParser對象的類,這裡新建一個SaxService類,實例化SAXParserFactory用於設定XML流和解析器。代碼如下:
- package cn.bgxt.service;
- import java.io.InputStream;
- import java.util.HashMap;
- import java.util.List;
- import javax.xml.parsers.SAXParser;
- import javax.xml.parsers.SAXParserFactory;
- import cn.bgxt.handler.MyHandler;
- public class SaxService {
- public SaxService() {
- // TODO Auto-generated constructor stub
- }
- public static List<HashMap<String, String>> readXML(InputStream inputStream,String nodeName)
- {
- try {
- //實例化SAX工廠類
- SAXParserFactory factory=SAXParserFactory.newInstance();
- //實例化SAX解析器。
- SAXParser sParser=factory.newSAXParser();
- //實例化DefaultHandler,設置需要解析的節點
- MyHandler myHandler=new MyHandler(nodeName);
- // 開始解析
- sParser.parse(inputStream, myHandler);
- // 解析完成之後,關閉流
- inputStream.close();
- //返回解析結果。
- return myHandler.getList();
- } catch (Exception e) {
- // TODO: handle exception
- }
- return null;
- }
- }
最後就是Android的一個Activity類了,布局界面很簡單,只有一個按鈕控件,這裡不展示布局代碼了。點擊按鈕後,觸發點擊事件,因為是Android4.0+,所以不能在主線程中訪問網絡,需要另起一個線程,這裡使用Thread類。代碼如下:
- package cn.bgxt.androidxmlforsax;
- import java.io.InputStream;
- import java.util.HashMap;
- import java.util.List;
- import cn.bgxt.http.HttpUtils;
- import cn.bgxt.service.SaxService;
- import android.os.Bundle;
- import android.app.Activity;
- import android.view.Menu;
- import android.view.View;
- import android.widget.Button;
- public class MainActivity extends Activity {
- private Button btn;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- btn=(Button)findViewById(R.id.btn);
- btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- //Android4.0+需要另起線程訪問網絡
- Thread thread=new Thread(new Runnable() {
- @Override
- public void run() {
- // 設置XML文檔的位置
- String path="http://192.168.1.107:1231/persons.xml";
- //讀取服務器上的XML,獲取XML流
- InputStream inputStream=HttpUtils.getXML(path);
- try {
- //解析流,設定需要解析的節點
- List<HashMap<String, String>> list=SaxService.readXML(inputStream, "person");
- for(HashMap<String,String> map:list)
- {
- //打印到LogCat中
- System.out.println(map.toString());
- }
- } catch (Exception e) {
- // TODO: handle exception
- }
- }
- });
- thread.start();
- }
- });
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
- }
當點擊後,XML解析後的內容會把打印到日志中,可以使用LogCat查看。
示例程序的下載
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩
HelloWorld的目錄結構有: src:存放應用程序的邏輯代碼,這裡面的代碼是人工寫的gen:存放資源代碼,這裡面的代碼是自動生成的assets:存放mp
本文實例講述了Android編程之菜單實現方法。分享給大家供大家參考,具體如下: 菜單是許多應用程序不可或缺的一部分,Android中更是如此,所有搭載Andro
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放