ATOM feed
android 에서 rss feed 의 parser 로 sax parser 를 사용하고 있다. 그런데 ATOM feed 를 parse 하는 데에도 쓰고 싶어서, 기존의 rss feed 와 같은 방식으로 사용을 해봤는데, 이상하게 children 이 보이지 않았다.
그런데, 아래 link 에서 해결책을 찾았다.
기존의 rss feed 를 parsing 할 때는 바로 tag name 을 적어주면 됐다.
RootElement root = new RootElement("feed");
Element entry = root.getChild("entry");
그런데 ATOM 을 처리할 때는 uri 를 넣어줘야 한다. xml 의 parsing 을 위한 namespace 를 지정해 주는 듯 하다.
static final String ATOM_NAMESPACE = "http://www.w3.org/2005/Atom"; RootElement root = new RootElement(ATOM_NAMESPACE, "feed"); Element entry = root.getChild(ATOM_NAMESPACE, "entry");
Content Handler
ref. 1 에서 SAX parser(Expat Parser) 를 사용하는 방법을 알려준다. 위에서 이야기 한 부분도 Sax parser 를 사용하고, RootElement 를 사용해서 parser 부분에서 사용하는 contentHandler 를 정의한 것이었지만,ref. 1 에서는 DefaultHandler를 상속받아서 자신만의 contentHandler 를 만들어 사용한다.
XmlPullParser
XmlPullParser 를 사용하고 싶으면 아래 예제를 보고 따라하자.좀 더 간단하고, XmlPullParserFactory 를 이용하는 예제는 see also. 2 에서 확인할 수 있다.
주의할점
보통 network 에서 Url을 통해 Rss 에 대한 InputStream 을 가져오기 때문에 이녀석을 바로 XmlPullParser.setInput 의 InputStream 으로 넘겨주게 된다. 대부분의 경우 문제가 없지만, GZIPInputStream 으로 오는 경우에 XmlPullParser 내부에서 제대로 읽지 못하는 듯 하다. 이때는 String 으로 변환해서 StringReader 를 이용해서 넘겨줄 수 있다.MainActivity.java
InputStream is = getInputStream(XML_FEED_URL); PodXmlParser parser = new PodXmlParser(MAX_ITEM); entries = parser.parse(is);
PodXmlParser.java
package com.grabeco.podlist;
/**
* Created with IntelliJ IDEA.
* User: namh
* Date: 13. 9. 13
* Time: 오후 10:32
* To change this template use File | Settings | File Templates.
*/
import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
public class PodXmlParser implements Runnable {
/**
* XML parser
* http://developer.android.com/training/basics/network-ops/xml.html
*/
private static final String ns = null; // namespace
private static final String FEED_TAG = "rss";
private static final String CHANNEL_TAG = "channel";
private static final String ENTRY_TAG = "item";
private static final String ENCLOSURE_TAG = "enclosure";
private static final String PUBDATE_TAG = "pubDate";
private static final String TITLE_TAG = "title";
private static final int ITEM_LIMIT_MAX = 1000;
private int mLimit = ITEM_LIMIT_MAX;
private static final String SEQ_ID_TAG = "SeqID";
private static final String Uno_TAG = "Uno";
private static final String UserID_TAG = "UserID";
private static final String USER_NAME_TAG = "UserNm";
private static final String COMMENT_TAG = "Comment";
private static final String REG_DATE_TAG = "RegDate";
private static final String Rank_TAG = "Rank";
public PodXmlParser(int limit) {
mLimit = limit;
}
/**
* This parser for the podcast feed
* itunes xml example : http://minicast.imbc.com/PodCast/pod.aspx?code=1000671100000100000
*
* @param in
* @return {@link List}
* @throws XmlPullParserException
* @throws IOException
*/
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();
}
}
private List readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
List entries = null;
parser.require(XmlPullParser.START_TAG, ns, FEED_TAG);
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(CHANNEL_TAG)) {
entries = readChannel(parser);
} else {
skip(parser);
}
}
return entries;
}
private List readChannel(XmlPullParser parser) throws IOException, XmlPullParserException {
PodItemList entries = new PodItemList();
int count = 0;
parser.require(XmlPullParser.START_TAG, ns, CHANNEL_TAG);
while (count < mLimit
&& parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals(ENTRY_TAG)) {
entries.add(readEntry(parser));
count++;
} else {
skip(parser);
}
}
return entries;
}
// Parses the contents of an entry. If it encounters a username, comment, or regdate tag, hands them
// off
// to their respective "read" methods for processing. Otherwise, skips the tag.
private PodRssItem readEntry(XmlPullParser parser) throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns, ENTRY_TAG);
String title = null;
String podUrl = null;
String pubDate = null;
int count = 0;
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals(TITLE_TAG)) {
title = readTitle(parser);
} else if (name.equals(ENCLOSURE_TAG)) {
podUrl = readEnclosure(parser);
} else if (name.equals(PUBDATE_TAG)) {
pubDate = readPubDate(parser);
} else {
skip(parser);
}
}
return new PodRssItem(title, podUrl, pubDate);
}
private String readTitle(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, TITLE_TAG);
String title = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, TITLE_TAG);
return title;
}
private String readPubDate(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, PUBDATE_TAG);
String date = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, PUBDATE_TAG);
return date;
}
// Processes link tags in the feed.
private String readEnclosure(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, ENCLOSURE_TAG);
String tag = parser.getName();
String podUrl = parser.getAttributeValue(null, "url");
parser.nextTag();
parser.require(XmlPullParser.END_TAG, ns, ENCLOSURE_TAG);
return podUrl;
}
// For the tags username and comment, extracts their text values.
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
String result = "";
if (parser.next() == XmlPullParser.TEXT) {
// CDATA is also treated, here.
result = parser.getText();
parser.nextTag();
}
return result;
}
// Skips tags the parser isn't interested in. Uses depth to handle nested tags. i.e.,
// if the next tag after a START_TAG isn't a matching END_TAG, it keeps going until it
// finds the matching END_TAG (as indicated by the value of "depth" being 0).
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;
}
}
}
//--------------------------------------------------------
@Override
public void run() {
//this.parse();
}
//--------------------------------------------------------
// public List<PodRssItem> getMessages(){
// return this.messages;
// }
}
댓글 없음:
댓글 쓰기