官方XmlPullParser和网络解析xml示例及详述
Parsing XML Data
This lesson teaches you to
- Choose a Parser
- Analyze the Feed
- Instantiate the Parser
- Read the Feed
- Parse XML
- Skip Tags You Don't Care About
- Consume XML Data
You should also read
Try it out
NetworkUsage.zip
Extensible Markup Language (XML) is a set of rules for encoding documents in machine-readable form. XML is a popular format for sharing data on the internet. Websites that frequently update their content, such as news sites or blogs, often provide an XML feed so that external programs can keep abreast of content changes. Uploading and parsing XML data is a common task for network-connected apps. This lesson explains how to parse XML documents and use their data.
Choose a Parser
We recommend XmlPullParser, which is an efficient and maintainable way to parse XML on Android. Historically Android has had two implementations of this interface:
KXmlParserviaXmlPullParserFactory.newPullParser().ExpatPullParser, viaXml.newPullParser().
Either choice is fine. The example in this section usesExpatPullParser, via Xml.newPullParser().
Analyze the Feed
The first step in parsing a feed is to decide which fields you're interested in. The parser extracts data for those fields and ignores the rest.
Here is an excerpt from the feed that's being parsed in the sample app. Each post to StackOverflow.com appears in the feed as an entry tag that contains several nested tags:
<?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>
The sample app extracts data for the entry tag and its nested tags title, link, and summary.
Instantiate the Parser
The next step is to instantiate a parser and kick off the parsing process. In this snippet, a parser is initialized to not process namespaces, and to use the provided InputStream as its input. It starts the parsing process with a call to nextTag() and invokes the readFeed() method, which extracts and processes the data the app is interested in:
public class StackOverflowXmlParser {
// We don't use namespaces
private 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();
}
}
...
}
Read the Feed
The readFeed() method does the actual work of processing the feed. It looks for elements tagged "entry" as a starting point for recursively processing the feed. If a tag isn't an entry tag, it skips it. Once the whole feed has been recursively processed, readFeed() returns a List containing the entries (including nested data members) it extracted from the feed. This List is then returned by the parser.
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 tag
if (name.equals("entry")) {
entries.add(readEntry(parser));
} else {
skip(parser);
}
}
return entries;
}
Parse XML
The steps for parsing an XML feed are as follows:
- As described in Analyze the Feed, identify the tags you want to include in your app. This example extracts data for the
entrytag and its nested tagstitle,link, andsummary. - Create the following methods:
- A "read" method for each tag you're interested in. For example,
readEntry(),readTitle(), and so on. The parser reads tags from the input stream. When it encounters a tag namedentry,title,linkorsummary, it calls the appropriate method for that tag. Otherwise, it skips the tag. - Methods to extract data for each different type of tag and to advance the parser to the next tag. For example:
- For the
titleandsummarytags, the parser callsreadText(). This method extracts data for these tags by callingparser.getText(). - For the
linktag, the parser extracts data for links by first determining if the link is the kind it's interested in. Then it usesparser.getAttributeValue()to extract the link's value. - For the
entrytag, the parser callsreadEntry(). This method parses the entry's nested tags and returns anEntryobject with the data memberstitle,link, andsummary.
- For the
- A helper
skip()method that's recursive. For more discussion of this topic, see Skip Tags You Don't Care About.
- A "read" method for each tag you're interested in. For example,
This snippet shows how the parser parses entries, titles, links, and summaries.
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.
privateString readText(XmlPullParser parser)throwsIOException,XmlPullParserException{
String result ="";
if(parser.next()==XmlPullParser.TEXT){ result
= parser.getText(); parser
.nextTag();
}
return result;
}
...
}
Skip Tags You Don't Care About
One of the steps in the XML parsing described above is for the parser to skip tags it's not interested in. Here is the parser's skip() method:
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;
}
}
}
This is how it works:
- It throws an exception if the current event isn't a
START_TAG. - It consumes the
START_TAG, and all events up to and including the matchingEND_TAG. - To make sure that it stops at the correct
END_TAGand not at the first tag it encounters after the originalSTART_TAG, it keeps track of the nesting depth.
Thus if the current element has nested elements, the value of depth won't be 0 until the parser has consumed all events between the original START_TAG and its matching END_TAG. For example, consider how the parser skips the <author> element, which has 2 nested elements, <name> and <uri>:
- The first time through the
whileloop, the next tag the parser encounters after<author>is theSTART_TAGfor<name>. The value fordepthis incremented to 2. - The second time through the
whileloop, the next tag the parser encounters is theEND_TAG</name>. The value fordepthis decremented to 1. - The third time through the
whileloop, the next tag the parser encounters is theSTART_TAG<uri>. The value fordepthis incremented to 2. - The fourth time through the
whileloop, the next tag the parser encounters is theEND_TAG</uri>. The value fordepthis decremented to 1. - The fifth time and final time through the
whileloop, the next tag the parser encounters is theEND_TAG</author>. The value fordepthis decremented to 0, indicating that the<author>element has been successfully skipped.
Consume XML Data
The example application fetches and parses the XML feed within an AsyncTask. This takes the processing off the main UI thread. When processing is complete, the app updates the UI in the main activity (NetworkActivity).
In the excerpt shown below, the loadPage() method does the following:
- Initializes a string variable with the URL for the XML feed.
- If the user's settings and the network connection allow it, invokes
new DownloadXmlTask().execute(url). This instantiates a newDownloadXmlTaskobject (AsyncTasksubclass) and runs itsexecute()method, which downloads and parses the feed and returns a string result to be displayed in the 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
}
}
The AsyncTask subclass shown below, DownloadXmlTask, implements the following AsyncTask methods:
doInBackground()executes the methodloadXmlFromNetwork(). It passes the feed URL as a parameter. The methodloadXmlFromNetwork()fetches and processes the feed. When it finishes, it passes back a result string.onPostExecute()takes the returned string and displays it in the UI.
// Implementation of AsyncTask used to download XML feed from stackoverflow.com.
private class DownloadXmlTask extends AsyncTask<String, Void, String> {
@Override
protected 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);
}
} @Override
protected void onPostExecute(String result) {
setContentView(R.layout.main);
// Displays the HTML string in the UI via a WebView
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadData(result, "text/html", null);
}
}
Below is the method loadXmlFromNetwork() that is invoked from DownloadXmlTask. It does the following:
- Instantiates a
StackOverflowXmlParser. It also creates variables for aListofEntryobjects (entries), andtitle,url, andsummary, to hold the values extracted from the XML feed for those fields. - Calls
downloadUrl(), which fetches the feed and returns it as anInputStream. - Uses
StackOverflowXmlParserto parse theInputStream.StackOverflowXmlParserpopulates aListofentrieswith data from the feed. - Processes the
entriesList, and combines the feed data with HTML markup. - Returns an HTML string that is displayed in the main activity UI by the
AsyncTaskmethodonPostExecute().
// 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 parser
StackOverflowXmlParser 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 text
SharedPreferences 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();
}
官方XmlPullParser和网络解析xml示例及详述的更多相关文章
- MsXml创建和解析XML示例
一.MsXml创建XML文档示例 // XmlCreationDemo.cpp #include <stdlib.h> #include <stdio.h> // 引入MSXM ...
- Android DOM解析XML示例程序
DOM方式解析xml是先把xml文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据的.DOM比较符合人的思维模式,但是其对内存的消耗比较大. activity_main.xml < ...
- Stax解析XML示例代码
package org.itat.stax; import java.io.IOException; import java.io.InputStream; import javax.xml.pars ...
- 四种生成和解析XML文档的方法详解(介绍+优缺点比较+示例)
众所周知,现在解析XML的方法越来越多,但主流的方法也就四种,即:DOM.SAX.JDOM和DOM4J 下面首先给出这四种方法的jar包下载地址 DOM:在现在的Java JDK里都自带了,在xml- ...
- Android网络之数据解析----SAX方式解析XML数据
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- iOS开发网络篇—XML数据的解析
iOS开发网络篇—XML数据的解析 iOS开发网络篇—XML介绍 一.XML简单介绍 XML:全称是Extensible Markup Language,译作“可扩展标记语言” 跟JSON一样,也是 ...
- 使用pull方式解析xml文件示例:
网上的示例太多,基本类似,个人在此做个简单的总结: 1.首先在工程的asserts目录下建一个book.xml文件: <?xml version="1.0" encoding ...
- Android开发学习---使用XmlPullParser解析xml文件
Android中解析XML的方式主要有三种:sax,dom和pull关于其内容可参考:http://blog.csdn.net/liuhe688/article/details/6415593 本文将 ...
- ACEXML解析XML文件——简单示例程序
掌握了ACMXML库解析XML文件的方法后,下面来实现一个比较完整的程序. 定义基本结构 xml文件格式如下 <?xml version="1.0"?> <roo ...
随机推荐
- [React] {svg, css module, sass} support in Create React App 2.0
create-react-app version 2.0 added a lot of new features. One of the new features is added the svgr ...
- Office EXCEL 创建图片超链接打不开怎么办 Excel打开图片提示发生了意外错误怎么办
如下图所示,点击超链接提示无法打开指定的文件 如果使用Office打开,则提示发生了意外错误 你需要先把IE浏览器打开,这样就可以打开了,并非是图像的相对位置不正确导致的.
- Office WORD WPS如何取消拼写检查
1 审阅-修订-修订选项-拼写,全部取消勾选.
- org.json.JSONException: A JSONObject text must begin with '{' at character 1 of {解决方法
在使用java读取一个本地的json配置文件的时候,产生了这个异常:org.json.JSONException: A JSONObject text must begin with '{' at c ...
- 释怀我的诺亚尔 不用EF框架,完成完美实体映射,且便于维护!(AutoMapper,petapoco)
释怀我的诺亚尔 不用EF框架,完成完美实体映射,且便于维护!(AutoMapper,petapoco) 最近,需要搭建一个新项目,在需求分析时确定数据库中需要创建多个存储过程.所以如果还是用原来E ...
- linux系统编程:线程同步-相互排斥量(mutex)
线程同步-相互排斥量(mutex) 线程同步 多个线程同一时候訪问共享数据时可能会冲突,于是须要实现线程同步. 一个线程冲突的演示样例 #include <stdio.h> #includ ...
- 配置 Apache 服务器禁止所有非法域名 访问自己的服务器
.http2..1以前: 第一种 直接拒绝访问 打开 httpd.conf 文件,将一下配置追加到文件最后. <pre name="code" class="htm ...
- 2016/2/24 1,css有几种引入方式 2,div除了可以声明id来控制,还可以声明什么控制? 3,如何让2个div,并排显示。4,清除浮动 clear:left / right / both
1,css有几种引入方式 使用HTML标签的STYLE属性 将STYLE属性直接加在单个的HTML元素标签上,控制HTML标签的表现样式.这种引入CSS的方式是分散灵活方便,但缺乏整体性和规划性,不利 ...
- Hbase权限配置以及使用手册
1.Hbase权限控制简介 Hbase的权限控制是通过AccessController Coprocessor协处理器框架实现的,可实现对用户的RWXCA的权限控制. 2.配置 配置hbase-sit ...
- 不同节点 IP 时间同步 分布式时间同步系统的参考时间获取技术分析
linux linux下时间同步的两种方法分享_LINUX_操作系统_脚本之家 http://www.jb51.net/LINUXjishu/73979.html 分布式时间同步系统的参考时间获取技术 ...