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; // } }
댓글 없음:
댓글 쓰기