Fixed problems in Atom feed parser

This commit is contained in:
daniel oeh
2012-09-01 12:55:35 +02:00
parent 61edc98f85
commit 0bfd5421a1
5 changed files with 58 additions and 26 deletions

View File

@ -22,7 +22,6 @@ public class SyndHandler extends DefaultHandler {
private static final String DEFAULT_PREFIX = ""; private static final String DEFAULT_PREFIX = "";
protected HandlerState state; protected HandlerState state;
public SyndHandler(Feed feed, TypeGetter.Type type) { public SyndHandler(Feed feed, TypeGetter.Type type) {
state = new HandlerState(feed); state = new HandlerState(feed);
if (type == TypeGetter.Type.RSS20) { if (type == TypeGetter.Type.RSS20) {
@ -49,8 +48,8 @@ public class SyndHandler extends DefaultHandler {
if (!state.tagstack.empty()) { if (!state.tagstack.empty()) {
if (state.getTagstack().size() >= 2) { if (state.getTagstack().size() >= 2) {
if (state.contentBuf != null) { if (state.contentBuf != null) {
String content = new String(ch, start, length); String content = new String(ch, start, length);
state.contentBuf.append(content); state.contentBuf.append(content);
} }
} }
} }
@ -83,24 +82,29 @@ public class SyndHandler extends DefaultHandler {
state.defaultNamespaces.push(new NSAtom()); state.defaultNamespaces.push(new NSAtom());
} else if (prefix.equals(NSAtom.NSTAG)) { } else if (prefix.equals(NSAtom.NSTAG)) {
state.namespaces.put(uri, new NSAtom()); state.namespaces.put(uri, new NSAtom());
if (AppConfig.DEBUG) Log.d(TAG, "Recognized Atom namespace"); if (AppConfig.DEBUG)
Log.d(TAG, "Recognized Atom namespace");
} }
} else if (uri.equals(NSContent.NSURI) && prefix.equals(NSContent.NSTAG)) { } else if (uri.equals(NSContent.NSURI)
&& prefix.equals(NSContent.NSTAG)) {
state.namespaces.put(uri, new NSContent()); state.namespaces.put(uri, new NSContent());
if (AppConfig.DEBUG) Log.d(TAG, "Recognized Content namespace"); if (AppConfig.DEBUG)
Log.d(TAG, "Recognized Content namespace");
} else if (uri.equals(NSITunes.NSURI) && prefix.equals(NSITunes.NSTAG)) { } else if (uri.equals(NSITunes.NSURI) && prefix.equals(NSITunes.NSTAG)) {
state.namespaces.put(uri, new NSITunes()); state.namespaces.put(uri, new NSITunes());
if (AppConfig.DEBUG) Log.d(TAG, "Recognized ITunes namespace"); if (AppConfig.DEBUG)
} else if (uri.equals(NSSimpleChapters.NSURI) && prefix.equals(NSSimpleChapters.NSTAG)) { Log.d(TAG, "Recognized ITunes namespace");
} else if (uri.equals(NSSimpleChapters.NSURI)
&& prefix.equals(NSSimpleChapters.NSTAG)) {
state.namespaces.put(uri, new NSSimpleChapters()); state.namespaces.put(uri, new NSSimpleChapters());
if (AppConfig.DEBUG) Log.d(TAG, "Recognized SimpleChapters namespace"); if (AppConfig.DEBUG)
Log.d(TAG, "Recognized SimpleChapters namespace");
} }
} }
private Namespace getHandlingNamespace(String uri) { private Namespace getHandlingNamespace(String uri) {
Namespace handler = state.namespaces.get(uri); Namespace handler = state.namespaces.get(uri);
if (handler == null && uri.equals(DEFAULT_PREFIX) if (handler == null && !state.defaultNamespaces.empty()) {
&& !state.defaultNamespaces.empty()) {
handler = state.defaultNamespaces.peek(); handler = state.defaultNamespaces.peek();
} }
return handler; return handler;

View File

@ -10,22 +10,24 @@ public class AtomText extends SyndElement {
public static final String TYPE_TEXT = "text"; public static final String TYPE_TEXT = "text";
public static final String TYPE_HTML = "html"; public static final String TYPE_HTML = "html";
public static final String TYPE_XHTML = "xhtml"; public static final String TYPE_XHTML = "xhtml";
private String type; private String type;
private String content; private String content;
public AtomText(String name, Namespace namespace, String type) { public AtomText(String name, Namespace namespace, String type) {
super(name, namespace); super(name, namespace);
this.type = type; this.type = type;
} }
/** Processes the content according to the type and returns it. */ /** Processes the content according to the type and returns it. */
public String getProcessedContent() { public String getProcessedContent() {
if (type.equals(TYPE_HTML)) { if (type == null) {
return content;
} else if (type.equals(TYPE_HTML)) {
return StringEscapeUtils.unescapeHtml4(content); return StringEscapeUtils.unescapeHtml4(content);
} else if (type.equals(TYPE_XHTML)) { } else if (type.equals(TYPE_XHTML)) {
return content; return content;
} else { // Handle as text by default } else { // Handle as text by default
return content; return content;
} }
} }
@ -41,7 +43,5 @@ public class AtomText extends SyndElement {
public String getType() { public String getType() {
return type; return type;
} }
} }

View File

@ -102,7 +102,12 @@ public class NSAtom extends Namespace {
if (state.getTagstack().size() >= 2) { if (state.getTagstack().size() >= 2) {
AtomText textElement = null; AtomText textElement = null;
String content = state.getContentBuf().toString(); String content;
if (state.getContentBuf() != null) {
content = state.getContentBuf().toString();
} else {
content = new String();
}
SyndElement topElement = state.getTagstack().peek(); SyndElement topElement = state.getTagstack().peek();
String top = topElement.getName(); String top = topElement.getName();
SyndElement secondElement = state.getSecondTag(); SyndElement secondElement = state.getSecondTag();

View File

@ -47,6 +47,7 @@ public class SyndDateUtils {
SimpleDateFormat format = RFC822Formatter.get(); SimpleDateFormat format = RFC822Formatter.get();
for (int i = 0; i < RFC822DATES.length; i++) { for (int i = 0; i < RFC822DATES.length; i++) {
try { try {
format.applyPattern(RFC822DATES[i]);
result = format.parse(date); result = format.parse(date);
break; break;
} catch (ParseException e) { } catch (ParseException e) {

View File

@ -15,6 +15,7 @@ import java.util.Date;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.util.Log; import android.util.Log;
import de.danoeh.antennapod.feed.Feed; import de.danoeh.antennapod.feed.Feed;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.syndication.handler.FeedHandler; import de.danoeh.antennapod.syndication.handler.FeedHandler;
/** Enqueues a list of Feeds and tests if they are parsed correctly */ /** Enqueues a list of Feeds and tests if they are parsed correctly */
@ -23,6 +24,10 @@ public class FeedHandlerTest extends AndroidTestCase {
private static final String FEEDS_DIR = "testfeeds"; private static final String FEEDS_DIR = "testfeeds";
private static final String[] rssUrls = { private static final String[] rssUrls = {
"http://bitlove.org/astro/youtube/feed",
"http://bitlove.org/channelcast/channelcast/feed",
"http://bitlove.org/cccb/chaosradio/feed",
"http://bitlove.org/astro/bitlove-show/feed",
"http://feeds.thisamericanlife.org/talpodcast", "http://feeds.thisamericanlife.org/talpodcast",
"http://www.casasola.de/137b/1337motiv/1337motiv.xml", "http://www.casasola.de/137b/1337motiv/1337motiv.xml",
"http://alternativlos.org/ogg.rss", "http://www.bitsundso.de/feed", "http://alternativlos.org/ogg.rss", "http://www.bitsundso.de/feed",
@ -66,8 +71,6 @@ public class FeedHandlerTest extends AndroidTestCase {
"http://bitlove.org/alexolma/iphoneblog/feed", "http://bitlove.org/alexolma/iphoneblog/feed",
"http://bitlove.org/andydrop/nachtnerd/feed", "http://bitlove.org/andydrop/nachtnerd/feed",
"http://bitlove.org/apollo40/ps3newsroom/feed", "http://bitlove.org/apollo40/ps3newsroom/feed",
"http://bitlove.org/astro/bitlove-show/feed",
"http://bitlove.org/astro/youtube/feed",
"http://bitlove.org/beapirate/hauptstadtpiraten/feed", "http://bitlove.org/beapirate/hauptstadtpiraten/feed",
"http://bitlove.org/benni/besondereumstaende/feed", "http://bitlove.org/benni/besondereumstaende/feed",
"http://bitlove.org/bennihahn/unicast/feed", "http://bitlove.org/bennihahn/unicast/feed",
@ -422,15 +425,35 @@ public class FeedHandlerTest extends AndroidTestCase {
} }
private boolean isFeedValid(Feed feed) { private boolean isFeedValid(Feed feed) {
Log.i(TAG, "Checking if " + feed.getDownload_url() + " is valid");
boolean result = false; boolean result = false;
if (feed.getTitle() == null) { if (feed.getTitle() == null) {
Log.e(TAG, "Feed has no title"); Log.e(TAG, "Feed has no title");
return false;
} }
if (feed.getItems() == null) { if (feed.getItems() == null) {
Log.e(TAG, "Feed has no items"); Log.e(TAG, "Feed has no items");
return false;
} }
result = feed.getTitle() != null && feed.getItems() != null; if (!hasValidFeedItems(feed)) {
return result; Log.e(TAG, "Feed has invalid items");
return false;
}
return true;
}
private boolean hasValidFeedItems(Feed feed) {
for (FeedItem item : feed.getItems()) {
if (item.getTitle() == null) {
Log.e(TAG, "Item has no title");
return false;
}
if (item.getPubDate() == null) {
Log.e(TAG, "Item has no pubDate");
return false;
}
}
return true;
} }
public void testParseRSS() { public void testParseRSS() {
@ -448,7 +471,7 @@ public class FeedHandlerTest extends AndroidTestCase {
} }
Log.i(TAG, "Atom Test completed"); Log.i(TAG, "Atom Test completed");
} }
private void parseFeed(Feed feed) { private void parseFeed(Feed feed) {
try { try {
Log.i(TAG, "Testing feed with url " + feed.getDownload_url()); Log.i(TAG, "Testing feed with url " + feed.getDownload_url());
@ -457,8 +480,7 @@ public class FeedHandlerTest extends AndroidTestCase {
handler.parseFeed(feed); handler.parseFeed(feed);
assertTrue(isFeedValid(feed)); assertTrue(isFeedValid(feed));
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, Log.e(TAG, "Error when trying to test " + feed.getDownload_url());
"Error when trying to test " + feed.getDownload_url());
e.printStackTrace(); e.printStackTrace();
fail(); fail();
} }