日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【Android Developers Training】 81. 解析XML数据

發布時間:2023/12/2 Android 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android Developers Training】 81. 解析XML数据 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術一般,由于喜愛安卓而產生了翻譯的念頭,純屬個人興趣愛好。

原文鏈接:http://developer.android.com/training/basics/network-ops/xml.html


可擴展標記語言(XML)是一種將文檔編碼為機器可閱讀的形式的規則集合。XML是一種在互聯網中分享數據的比較流行的格式。那些頻繁更新內容的網站(如新的站點或者博客),經常會提供一個XML源,這樣外部程序就可以與內容變更保持同步。上傳及解析XML數據對于需要聯網的應用來說是一個很平常的任務。這節課將講解如何解析XML文檔并使用它們的數據。


一). 選擇一個解析器

我們推薦使用XmlPullParser,它是一個在Android上解析XML的一種比較有效及穩定的方法。歷史中Android有兩種實現該接口的方法:

  • 通過XmlPullParserFactory.newPullParser()實現的KXmlParser。
  • 通過Xml.newPullParser()實現的ExpatPullParser。

每一種選擇都是可以的。不過這里我們使用第二個例子。?


二). 分析源

解析源的第一步是決定哪些字段是你感興趣的。解析器會提取這些你感興趣的字段數據并把其余的忽略。

下面是在應用中被解析的源的一段摘錄。每一個到StackOverflow.com的推送都會在源中顯示為一個entry標簽,并包含若干entry子標簽:

<?xml version="1.0" encoding="utf-8"?> <feed xmlns="http://www.w3.org/2005/Atom" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" ..."> <title type="text">newest questions tagged android - Stack Overflow</title> ...<entry>...</entry><entry><id>http://stackoverflow.com/q/9439999</id><re:rank scheme="http://stackoverflow.com">0</re:rank><title type="text">Where is my data file?</title><category scheme="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest/tags" term="android"/><category scheme="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest/tags" term="file"/><author><name>cliff2310</name><uri>http://stackoverflow.com/users/1128925</uri></author><link rel="alternate" href="http://stackoverflow.com/questions/9439999/where-is-my-data-file" /><published>2012-02-25T00:30:54Z</published><updated>2012-02-25T00:30:54Z</updated><summary type="html"><p>I have an Application that requires a data file...</p></summary></entry><entry>...</entry> ... </feed>

應用會提取會提取entry標簽及其子標簽:titlelinksummary子標簽的數據。


三). 初始化解析器

下一步是初始化解析器,并啟動解析的步驟。在下面的代碼片段中,一個不處理命名空間的解析器被初始化,并使用InputStream作為參數。通過調用nextTag()開始解析的步驟,并激活readFeed()方法,該方法提取并處理應用感興趣的數據:

public class StackOverflowXmlParser {// We don't use namespacesprivate static final String ns = null;public List parse(InputStream in) throws XmlPullParserException, IOException {try {XmlPullParser parser = Xml.newPullParser();parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);parser.setInput(in, null);parser.nextTag();return readFeed(parser);} finally {in.close();}}... }

四). 閱讀源

readFeed()方法執行一些工作來處理源。它尋找entry標簽作為開始遞歸處理的起始點。如果一個標簽不是entry標簽,那么就忽略它。一點整個源都被遞歸處理完了,readFeed()方法返回一個包含它從源中提取的字段的List(包含子數據成員)。該List被解析器返回。

private List readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {List entries = new ArrayList();parser.require(XmlPullParser.START_TAG, ns, "feed");while (parser.next() != XmlPullParser.END_TAG) {if (parser.getEventType() != XmlPullParser.START_TAG) {continue;}String name = parser.getName();// Starts by looking for the entry tagif (name.equals("entry")) {entries.add(readEntry(parser));} else {skip(parser);}} return entries; }

五). 解析XML

解析一個XML源的步驟如下:

  • 如第二節中所述,在你的應用中標識出你希望包含的標簽。該例子中提取的數據為entry標簽及其子標簽:titlelinksummary子標簽的數據。
  • 創建下列方法:
      • 為每個你感興趣的標簽創建“read”方法。例如,readEntry(),readTitle()等。解析器從輸入流中讀取標簽。當它遇到了名為entry,title,link或summary時,它會為標簽調用相應的方法。否則就略過該標簽。
      • 為每個不同類型標簽提取數據并將解析器推進到下一個標簽的方法。例如:
        • 對于title和summary標簽,解析器調用readText()。該方法提取通過調用parser.getText(),從這些標簽中提取數據。
        • 對于link標簽,解析器首先確定該link是否是自己感興趣的,如果是的話就調用parser.getAttributeValue()來提取它的值。
        • 對于entry標簽,解析器會調用readEntry()。該方法解析entry中的子標簽,并返回一個Entry對象,其中包含了數據成員:title,link和summary。
      • 一個用以輔助的方法skip()。更多信息可以閱讀:Skip Tags You Don't Care About。

    下列代碼片段展示了如何解析上述標簽:

    public static class Entry {public final String title;public final String link;public final String summary;private Entry(String title, String summary, String link) {this.title = title;this.summary = summary;this.link = link;} }// Parses the contents of an entry. If it encounters a title, summary, or link tag, hands them off // to their respective "read" methods for processing. Otherwise, skips the tag. private Entry readEntry(XmlPullParser parser) throws XmlPullParserException, IOException {parser.require(XmlPullParser.START_TAG, ns, "entry");String title = null;String summary = null;String link = null;while (parser.next() != XmlPullParser.END_TAG) {if (parser.getEventType() != XmlPullParser.START_TAG) {continue;}String name = parser.getName();if (name.equals("title")) {title = readTitle(parser);} else if (name.equals("summary")) {summary = readSummary(parser);} else if (name.equals("link")) {link = readLink(parser);} else {skip(parser);}}return new Entry(title, summary, link); }// Processes title tags in the feed. private String readTitle(XmlPullParser parser) throws IOException, XmlPullParserException {parser.require(XmlPullParser.START_TAG, ns, "title");String title = readText(parser);parser.require(XmlPullParser.END_TAG, ns, "title");return title; }// Processes link tags in the feed. private String readLink(XmlPullParser parser) throws IOException, XmlPullParserException {String link = "";parser.require(XmlPullParser.START_TAG, ns, "link");String tag = parser.getName();String relType = parser.getAttributeValue(null, "rel"); if (tag.equals("link")) {if (relType.equals("alternate")){link = parser.getAttributeValue(null, "href");parser.nextTag();} }parser.require(XmlPullParser.END_TAG, ns, "link");return link; }// Processes summary tags in the feed. private String readSummary(XmlPullParser parser) throws IOException, XmlPullParserException {parser.require(XmlPullParser.START_TAG, ns, "summary");String summary = readText(parser);parser.require(XmlPullParser.END_TAG, ns, "summary");return summary; }// For the tags title and summary, extracts their text values. private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {String result = "";if (parser.next() == XmlPullParser.TEXT) {result = parser.getText();parser.nextTag();}return result; }... }

    六). 跳過你不關注的標簽

    上面所描述的解析XML步驟中,其中有一步是解析器跳過我們不關注的標簽。下面是skip()方法的代碼:

    private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {if (parser.getEventType() != XmlPullParser.START_TAG) {throw new IllegalStateException();}int depth = 1;while (depth != 0) {switch (parser.next()) {case XmlPullParser.END_TAG:depth--;break;case XmlPullParser.START_TAG:depth++;break;}}}

    它為何這樣就能實現跳過的功能呢:

    • 如果當前遇到的不是START_TAG,那么拋出一個異常。
    • 它接收START_TAG,以及之后遇到的內容,并匹配END_TAG。
    • 為了確保它在正確的END_TAG停止,而不是在START_TAG之后遇到的第一個標簽,它會一直向子標簽深度搜索。

    因此如果當前標簽含有子標簽,那么depth的值不會變成0,直到解析器處理了所有在原始的START_TAG和與它匹配的END_TAG之間的所有標簽。例如,考慮該解析器如何略過<author>標簽,該標簽含有兩個子標簽<name>和<uri>:

    • 第一次while循環,解析器在<author>之后遇到了START_TAG:<name>,此時depth的值增加到2。
    • 第二次while循環,解析器遇到了END_TAG:</name>。此時depth的值減少到1。
    • 第三次while循環,解析器遇到了START_TAG:<uri>。此時depth的值增加到2。
    • 第四次while循環,解析器遇到了END_TAG:</uri>。此時depth的值減少到1。
    • 最后一次while循環,解析器遇到了END_TAG:</author>。此時depth的值減少到0,表明<author>已經被成功忽略了。

    七). 處理XML數據

    樣例代碼中,使用了AsyncTask獲取并解析XML源。這樣該過程就不會再UI主線程中執行。當處理執行完畢,應用會更新主Activity(NetworkActivity)的UI。

    在下面摘錄的代碼片段中,loadPage()方法進行了如下的處理:

    用XML源的URL初始化一個String變量。

    在用戶的設置及網絡連接允許的情況下,調用new DownloadXmlTask().execute(url)。這將初始化一個新的DownloadXmlTask對象(AsyncTask的子類)并運行它的execute()方法,它會下載并解析源并將結果以String的形式返回,顯示在UI上。?

    public class NetworkActivity extends Activity {public static final String WIFI = "Wi-Fi";public static final String ANY = "Any";private static final String URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";// Whether there is a Wi-Fi connection.private static boolean wifiConnected = false; // Whether there is a mobile connection.private static boolean mobileConnected = false;// Whether the display should be refreshed.public static boolean refreshDisplay = true; public static String sPref = null;...// Uses AsyncTask to download the XML feed from stackoverflow.com.public void loadPage() { if((sPref.equals(ANY)) && (wifiConnected || mobileConnected)) {new DownloadXmlTask().execute(URL);}else if ((sPref.equals(WIFI)) && (wifiConnected)) {new DownloadXmlTask().execute(URL);} else {// show error } }

    AsyncTask的子類:DownloadXmlTask如下所示,它實現了下列AsyncTask的方法:

    doInBackground()執行loadXmlFromNetwork(),它將源的URL作為參數傳入。loadXmlFromNetwork()方法獲取并處理源。當它結束以后,它會返回String作為結果。

    onPostExecute()接收結果String并將它顯示在UI上。

    // Implementation of AsyncTask used to download XML feed from stackoverflow.com. private class DownloadXmlTask extends AsyncTask<String, Void, String> {@Overrideprotected String doInBackground(String... urls) {try {return loadXmlFromNetwork(urls[0]);} catch (IOException e) {return getResources().getString(R.string.connection_error);} catch (XmlPullParserException e) {return getResources().getString(R.string.xml_error);}}@Overrideprotected void onPostExecute(String result) { setContentView(R.layout.main);// Displays the HTML string in the UI via a WebViewWebView myWebView = (WebView) findViewById(R.id.webview);myWebView.loadData(result, "text/html", null);} }

    下面是方法:loadXmlFromNetwork(),它被DownloadXmlTask調用,它執行下列任務:

    • 初始化一個StackOverflowXmlParser,它也創建一個裝載entry對象的List(entries),以及title,url,和summary,來存儲從XML源中相應字段里提取出的數據。
    • 調用downloadUrl(),它獲取源并以InputStream的形式返回
    • 使用StackOverflowXmlParser來解析InputStream。StackOverflowXmlParser會用源中的數據填充entries這個List。
    • 處理List,并將源數據和HTML標記向結合。
    • 返回HTML字符串,由AsyncTask的onPostExecute()方法將它顯示在主Activity UI上的。
    // Uploads XML from stackoverflow.com, parses it, and combines it with // HTML markup. Returns HTML string. private String loadXmlFromNetwork(String urlString) throws XmlPullParserException, IOException {InputStream stream = null;// Instantiate the parserStackOverflowXmlParser stackOverflowXmlParser = new StackOverflowXmlParser();List<Entry> entries = null;String title = null;String url = null;String summary = null;Calendar rightNow = Calendar.getInstance(); DateFormat formatter = new SimpleDateFormat("MMM dd h:mmaa");// Checks whether the user set the preference to include summary textSharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);boolean pref = sharedPrefs.getBoolean("summaryPref", false);StringBuilder htmlString = new StringBuilder();htmlString.append("<h3>" + getResources().getString(R.string.page_title) + "</h3>");htmlString.append("<em>" + getResources().getString(R.string.updated) + " " + formatter.format(rightNow.getTime()) + "</em>");try {stream = downloadUrl(urlString); entries = stackOverflowXmlParser.parse(stream);// Makes sure that the InputStream is closed after the app is// finished using it.} finally {if (stream != null) {stream.close();} }// StackOverflowXmlParser returns a List (called "entries") of Entry objects.// Each Entry object represents a single post in the XML feed.// This section processes the entries list to combine each entry with HTML markup.// Each entry is displayed in the UI as a link that optionally includes// a text summary.for (Entry entry : entries) { htmlString.append("<p><a href='");htmlString.append(entry.link);htmlString.append("'>" + entry.title + "</a></p>");// If the user set the preference to include summary text,// adds it to the display.if (pref) {htmlString.append(entry.summary);}}return htmlString.toString(); }// Given a string representation of a URL, sets up a connection and gets // an input stream. private InputStream downloadUrl(String urlString) throws IOException {URL url = new URL(urlString);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setReadTimeout(10000 /* milliseconds */);conn.setConnectTimeout(15000 /* milliseconds */);conn.setRequestMethod("GET");conn.setDoInput(true);// Starts the query conn.connect();return conn.getInputStream(); }

    轉載于:https://www.cnblogs.com/jdneo/p/3612892.html

    總結

    以上是生活随笔為你收集整理的【Android Developers Training】 81. 解析XML数据的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。