官方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 ...
随机推荐
- Zookeeper开发常见问题
背景与目的 Zookeeper开发过程中遇到一些常见问题,为了后续开发不犯同样的错误,总结一下此类问题,并进行分析和解决. 适合人员 主要适合zookeeper开发.测试及运维相关人员. 问题与解决 ...
- JMeter 系列之—-01使用
用Jmeter 做压测,总体与LoadRunner 类似: 一.线程组 1. 线程数 2. 循环次数 单个线程循环次数 3. Ramp-up Period(in seconds) [1]决定多长时间启 ...
- bootstrap中固定table的表头
前端时间鼓捣的一个简单的手机站点,今天又拿出来弄一弄 由于主要是给手机訪问.用的是bootstrap响应式布局,今天的任务是做一个数据展示页面 可是因为数据的列比較多.所以横向显示不下,为了较好的显示 ...
- Android5.0(lollipop)新特性介绍(一)
今年6月的Google I/O大会上.Android L的初次见面我相信让会让非常多android粉丝有些小激动和小期待.当然作为开发人员的我来说,激动不言而喻,毕竟这是自08年以来改变最大的一个版本 ...
- 配置 Apache 服务器禁止所有非法域名 访问自己的服务器
.http2..1以前: 第一种 直接拒绝访问 打开 httpd.conf 文件,将一下配置追加到文件最后. <pre name="code" class="htm ...
- Ubuntu下配置Tomcat以指定(非root)身份执行
My Blog:http://www.outflush.com/ 通常情况下.在配置Tomcat生产环境时,一般会配置Tomcat以特定的身份执行(非root).这样有利于提高安全性,防止站点被黑后的 ...
- 连接sql2008时报错
最近把公司的项目搭建到本地(周末回家要加班),可是连接后,发现程序后台出错,错误信息:不支持此服务器版本.目标服务器必须是 SQL Server 2000 或更高版本. 本地是SqlServer200 ...
- MUI日期选择控件
MUI的Demo里面有例子,实际做的时候发现日期老是乱码,调了半天,最后发现引用的CSS错误,例子中引用的是 <link href="Css/mui.picker.min.css&qu ...
- The server committed a protocol violation. Section=ResponseHeader Detail=CR must be followed by LF
打开表单偶尔会出现这个提示,解决方法: web.config增加配置: <configuration> <system.net> <settings> <ht ...
- how to create modals with Bootstrap
In this tutorial you will learn how to create modals with Bootstrap. Creating Modals with Bootstrap ...