Bug 1241810 - Introduce SimpleFeedParser for implementing "content notifications". r=mcomella

This is just a simple XML Pull Parser that can read arbitrary ATOM and RSS feeds and returns an
object describing the feed and the latest entry. It's goal is to be small and simple rather than
a full-featured feed parser library.

MozReview-Commit-ID: LIa9neYSfCF

--HG--
rename : mobile/android/app/src/main/resources/robolectric.properties => mobile/android/tests/background/junit4/resources/robolectric.properties
extra : rebase_source : 121fe20ce889092c00fc00ea43e69262724c1290
This commit is contained in:
Sebastian Kaspari 2016-02-24 10:55:35 -08:00
Родитель 3a42cce9c7
Коммит d145b545ef
17 изменённых файлов: 16026 добавлений и 0 удалений

Просмотреть файл

@ -138,6 +138,9 @@ android {
exclude 'org/mozilla/gecko/push/**/*.java'
}
}
resources {
srcDir "${topsrcdir}/mobile/android/tests/background/junit4/resources"
}
}
androidTest {

Просмотреть файл

@ -0,0 +1,98 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.feeds.parser;
import ch.boye.httpclientandroidlib.util.TextUtils;
public class Feed {
private String title;
private String websiteURL;
private String feedURL;
private Item lastItem;
public static Feed create(String title, String websiteURL, String feedURL, Item lastItem) {
Feed feed = new Feed();
feed.setTitle(title);
feed.setWebsiteURL(websiteURL);
feed.setFeedURL(feedURL);
feed.setLastItem(lastItem);
return feed;
}
/* package-private */ Feed() {}
/* package-private */ void setTitle(String title) {
this.title = title;
}
/* package-private */ void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
/* package-private */ void setFeedURL(String feedURL) {
this.feedURL = feedURL;
}
/* package-private */ void setLastItem(Item lastItem) {
this.lastItem = lastItem;
}
/**
* Is this feed object sufficiently complete so that we can use it?
*/
/* package-private */ boolean isSufficientlyComplete() {
return !TextUtils.isEmpty(title) &&
lastItem != null &&
!TextUtils.isEmpty(lastItem.getURL()) &&
!TextUtils.isEmpty(lastItem.getTitle());
}
/**
* Guesstimate if the given feed is a newer representation of this feed.
*/
public boolean hasBeenUpdated(Feed newFeed) {
final Item otherItem = newFeed.getLastItem();
if (lastItem.getTimestamp() > otherItem.getTimestamp()) {
// The timestamp is from a newer date so we expect that this item is a new item. But this
// could also mean that the timestamp of an already existing item has been updated. We
// accept that and assume that the content will have changed too in this case.
return true;
}
if (lastItem.getTimestamp() == otherItem.getTimestamp() && lastItem.getTimestamp() != 0) {
// We have a timestamp that is not zero and this item has still the timestamp: It's very
// likely that we are looking at the same item. We assume this is not new content.
return false;
}
if (!lastItem.getURL().equals(otherItem.getURL())) {
// The URL changed: It is very likely that this is a new item. At least it has been updated
// in a way that we just treat it as new content here.
return true;
}
return false;
}
public String getTitle() {
return title;
}
public String getWebsiteURL() {
return websiteURL;
}
public String getFeedURL() {
return feedURL;
}
public Item getLastItem() {
return lastItem;
}
}

Просмотреть файл

@ -0,0 +1,49 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.feeds.parser;
public class Item {
private String title;
private String url;
private long timestamp;
public static Item create(String title, String url, long timestamp) {
Item item = new Item();
item.setTitle(title);
item.setURL(url);
item.setTimestamp(timestamp);
return item;
}
/* package-private */ void setTitle(String title) {
this.title = title;
}
/* package-private */ void setURL(String url) {
this.url = url;
}
/* package-private */ void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public String getTitle() {
return title;
}
public String getURL() {
return url;
}
/**
* @return the number of milliseconds since Jan. 1, 1970, midnight GMT.
*/
public long getTimestamp() {
return timestamp;
}
}

Просмотреть файл

@ -0,0 +1,357 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.feeds.parser;
import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import ch.boye.httpclientandroidlib.util.TextUtils;
/**
* A super simple feed parser written for implementing "content notifications". This XML Pull Parser
* can read ATOM and RSS feeds and returns an object describing the feed and the latest entry.
*/
public class SimpleFeedParser {
/**
* Generic exception that's thrown by the parser whenever a stream cannot be parsed.
*/
public static class ParserException extends Exception {
private static final long serialVersionUID = -6119538440219805603L;
public ParserException(Throwable cause) {
super(cause);
}
public ParserException(String message) {
super(message);
}
}
private static final String LOGTAG = "Gecko/FeedParser";
private static final String TAG_RSS = "rss";
private static final String TAG_FEED = "feed";
private static final String TAG_RDF = "RDF";
private static final String TAG_TITLE = "title";
private static final String TAG_ITEM = "item";
private static final String TAG_LINK = "link";
private static final String TAG_ENTRY = "entry";
private static final String TAG_PUBDATE = "pubDate";
private static final String TAG_UPDATED = "updated";
private static final String TAG_DATE = "date";
private static final String TAG_SOURCE = "source";
private static final String TAG_IMAGE = "image";
private class ParserState {
public Feed feed;
public Item currentItem;
public boolean isRSS;
public boolean isATOM;
public boolean inSource;
public boolean inImage;
}
public Feed parse(InputStream in) throws ParserException, IOException {
final ParserState state = new ParserState();
try {
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser parser = factory.newPullParser();
parser.setInput(in, null);
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
handleStartDocument(state);
break;
case XmlPullParser.START_TAG:
handleStartTag(parser, state);
break;
case XmlPullParser.END_TAG:
handleEndTag(parser, state);
break;
}
eventType = parser.next();
}
} catch (XmlPullParserException e) {
throw new ParserException(e);
}
if (!state.feed.isSufficientlyComplete()) {
throw new ParserException("Feed is not sufficiently complete");
}
return state.feed;
}
private void handleStartDocument(ParserState state) {
state.feed = new Feed();
}
private void handleStartTag(XmlPullParser parser, ParserState state) throws IOException, XmlPullParserException {
switch (parser.getName()) {
case TAG_RSS:
state.isRSS = true;
break;
case TAG_FEED:
state.isATOM = true;
break;
case TAG_RDF:
// This is a RSS 1.0 feed
state.isRSS = true;
break;
case TAG_ITEM:
case TAG_ENTRY:
state.currentItem = new Item();
break;
case TAG_TITLE:
handleTitleStartTag(parser, state);
break;
case TAG_LINK:
handleLinkStartTag(parser, state);
break;
case TAG_PUBDATE:
handlePubDateStartTag(parser, state);
break;
case TAG_UPDATED:
handleUpdatedStartTag(parser, state);
break;
case TAG_DATE:
handleDateStartTag(parser, state);
break;
case TAG_SOURCE:
state.inSource = true;
break;
case TAG_IMAGE:
state.inImage = true;
break;
}
}
private void handleEndTag(XmlPullParser parser, ParserState state) {
switch (parser.getName()) {
case TAG_ITEM:
case TAG_ENTRY:
handleItemOrEntryREndTag(state);
break;
case TAG_SOURCE:
state.inSource = false;
break;
case TAG_IMAGE:
state.inImage = false;
break;
}
}
private void handleTitleStartTag(XmlPullParser parser, ParserState state) throws IOException, XmlPullParserException {
if (state.inSource || state.inImage) {
// We do not care about titles in <source> or <image> tags.
return;
}
String title = getTextUntilEndTag(parser, TAG_TITLE);
title = title.replaceAll("[\r\n]", " ");
title = title.replaceAll(" +", " ");
if (state.currentItem != null) {
state.currentItem.setTitle(title);
} else {
state.feed.setTitle(title);
}
}
private void handleLinkStartTag(XmlPullParser parser, ParserState state) throws IOException, XmlPullParserException {
if (state.inSource || state.inImage) {
// We do not care about links in <source> or <image> tags.
return;
}
Map<String, String> attributes = fetchAttributes(parser);
if (attributes.size() > 0) {
String rel = attributes.get("rel");
if (state.currentItem == null && "self".equals(rel)) {
state.feed.setFeedURL(attributes.get("href"));
return;
}
if (rel == null || "alternate".equals(rel)) {
String type = attributes.get("type");
if (type == null || type.equals("text/html")) {
String link = attributes.get("href");
if (TextUtils.isEmpty(link)) {
return;
}
if (state.currentItem != null) {
state.currentItem.setURL(link);
} else {
state.feed.setWebsiteURL(link);
}
return;
}
}
}
if (state.isRSS) {
String link = getTextUntilEndTag(parser, TAG_LINK);
if (TextUtils.isEmpty(link)) {
return;
}
if (state.currentItem != null) {
state.currentItem.setURL(link);
} else {
state.feed.setWebsiteURL(link);
}
}
}
private void handleItemOrEntryREndTag(ParserState state) {
if (state.feed.getLastItem() == null || state.feed.getLastItem().getTimestamp() < state.currentItem.getTimestamp()) {
// Only set this item as "last item" if we do not have an item yet or this item is newer.
state.feed.setLastItem(state.currentItem);
}
state.currentItem = null;
}
private void handlePubDateStartTag(XmlPullParser parser, ParserState state) throws IOException, XmlPullParserException {
if (state.currentItem == null) {
return;
}
String pubDate = getTextUntilEndTag(parser, TAG_PUBDATE);
if (TextUtils.isEmpty(pubDate)) {
return;
}
// RFC-822
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
updateCurrentItemTimestamp(state, pubDate, format);
}
private void handleUpdatedStartTag(XmlPullParser parser, ParserState state) throws IOException, XmlPullParserException {
if (state.inSource) {
// We do not care about stuff in <source> tags.
return;
}
if (state.currentItem == null) {
// We are only interested in <updated> values of feed items.
return;
}
String updated = getTextUntilEndTag(parser, TAG_UPDATED);
if (TextUtils.isEmpty(updated)) {
return;
}
SimpleDateFormat[] formats = new SimpleDateFormat[] {
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US),
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US)
};
// Fix timezones SimpleDateFormat can't parse:
// 2016-01-26T18:56:54Z -> 2016-01-26T18:56:54+0000 (Timezone: Z -> +0000)
updated = updated.replaceFirst("Z$", "+0000");
// 2016-01-26T18:56:54+01:00 -> 2016-01-26T18:56:54+0100 (Timezone: +01:00 -> +0100)
updated = updated.replaceFirst("([0-9]{2})([\\+\\-])([0-9]{2}):([0-9]{2})$", "$1$2$3$4");
updateCurrentItemTimestamp(state, updated, formats);
}
private void handleDateStartTag(XmlPullParser parser, ParserState state) throws IOException, XmlPullParserException {
if (state.currentItem == null) {
// We are only interested in <updated> values of feed items.
return;
}
String text = getTextUntilEndTag(parser, TAG_DATE);
if (TextUtils.isEmpty(text)) {
return;
}
// Fix timezones SimpleDateFormat can't parse:
// 2016-01-26T18:56:54+00:00 -> 2016-01-26T18:56:54+0000
text = text.replaceFirst("([0-9]{2})([\\+\\-])([0-9]{2}):([0-9]{2})$", "$1$2$3$4");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
updateCurrentItemTimestamp(state, text, format);
}
private void updateCurrentItemTimestamp(ParserState state, String text, SimpleDateFormat... formats) {
for (SimpleDateFormat format : formats) {
try {
Date date = format.parse(text);
state.currentItem.setTimestamp(date.getTime());
return;
} catch (ParseException e) {
Log.w(LOGTAG, "Could not parse 'updated': " + text);
}
}
}
private Map<String, String> fetchAttributes(XmlPullParser parser) {
Map<String, String> attributes = new HashMap<>();
for (int i = 0; i < parser.getAttributeCount(); i++) {
attributes.put(parser.getAttributeName(i), parser.getAttributeValue(i));
}
return attributes;
}
private String getTextUntilEndTag(XmlPullParser parser, String tag) throws IOException, XmlPullParserException {
StringBuilder builder = new StringBuilder();
while (parser.next() != XmlPullParser.END_DOCUMENT) {
if (parser.getEventType() == XmlPullParser.TEXT) {
builder.append(parser.getText());
} else if (parser.getEventType() == XmlPullParser.END_TAG && tag.equals(parser.getName())) {
break;
}
}
return builder.toString().trim();
}
}

Просмотреть файл

@ -273,6 +273,9 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
'favicons/LoadFaviconTask.java',
'favicons/OnFaviconLoadedListener.java',
'favicons/RemoteFavicon.java',
'feeds/parser/Feed.java',
'feeds/parser/Item.java',
'feeds/parser/SimpleFeedParser.java',
'FilePicker.java',
'FilePickerResultHandler.java',
'FindInPageBar.java',

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://en.wikipedia.org/wiki/Atom_%28standard%29#Example_of_an_Atom_1.0_feed
-->
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Example Feed</title>
<subtitle>A subtitle.</subtitle>
<link href="http://example.org/feed/" rel="self" />
<link href="http://example.org/" />
<id>urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af6</id>
<updated>2003-12-13T18:30:02Z</updated>
<entry>
<title>Atom-Powered Robots Run Amok</title>
<link href="http://example.org/2003/12/13/atom03" />
<link rel="alternate" type="text/html" href="http://example.org/2003/12/13/atom03.html"/>
<link rel="edit" href="http://example.org/2003/12/13/atom03/edit"/>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<updated>2003-12-13T18:30:02Z</updated>
<summary>Some text.</summary>
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<p>This is the entry content.</p>
</div>
</content>
<author>
<name>John Doe</name>
<email>johndoe@example.com</email>
</author>
</entry>
</feed>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Snapshot from https://medium.com/feed/@Antlam/
-->
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
<channel>
<title><![CDATA[Anthony Lam on Medium]]></title>
<description><![CDATA[Latest posts by Anthony Lam on Medium]]></description>
<link>https://medium.com/@antlam?source=rss-59f49b9e4b19------2</link>
<image>
<url>https://d262ilb51hltx0.cloudfront.net/fit/c/150/150/1*BNfAhhQ8TybWsu_gMMixWw.jpeg</url>
<title>Anthony Lam on Medium</title>
<link>https://medium.com/@antlam?source=rss-59f49b9e4b19------2</link>
</image>
<generator>RSS for Node</generator>
<lastBuildDate>Tue, 26 Jan 2016 17:06:09 GMT</lastBuildDate>
<atom:link href="https://medium.com/feed/@antlam" rel="self" type="application/rss+xml"/>
<webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
<atom:link href="http://medium.superfeedr.com" rel="hub"/>
<item>
<title><![CDATA[UX thoughts for 2016]]></title>
<description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@antlam/ux-thoughts-for-2016-1fc1d6e515e8?source=rss-59f49b9e4b19------2"><img src="https://d262ilb51hltx0.cloudfront.net/fit/c/600/200/1*mOiPSWfvCBoLUrfQlIrdVQ.png" width="600" height="200"></a></p><p class="medium-feed-snippet">And just like that, another year.</p><p class="medium-feed-link"><a href="https://medium.com/@antlam/ux-thoughts-for-2016-1fc1d6e515e8?source=rss-59f49b9e4b19------2">Continue reading on Medium »</a></p></div>]]></description>
<link>https://medium.com/@antlam/ux-thoughts-for-2016-1fc1d6e515e8?source=rss-59f49b9e4b19------2</link>
<guid isPermaLink="false">https://medium.com/p/1fc1d6e515e8</guid>
<dc:creator><![CDATA[Anthony Lam]]></dc:creator>
<pubDate>Mon, 11 Jan 2016 18:43:58 GMT</pubDate>
</item>
<item>
<title><![CDATA[A New Mobile Tabs tray]]></title>
<description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@antlam/a-new-mobile-tabs-tray-327ac262eacb?source=rss-59f49b9e4b19------2"><img src="https://d262ilb51hltx0.cloudfront.net/fit/c/600/200/1*scpLRAL_zy9CcW6BLGZHng.png" width="600" height="200"></a></p><p class="medium-feed-snippet">Why we&#8217;re giving it an update in Firefox for Android</p><p class="medium-feed-link"><a href="https://medium.com/@antlam/a-new-mobile-tabs-tray-327ac262eacb?source=rss-59f49b9e4b19------2">Continue reading on Medium »</a></p></div>]]></description>
<link>https://medium.com/@antlam/a-new-mobile-tabs-tray-327ac262eacb?source=rss-59f49b9e4b19------2</link>
<guid isPermaLink="false">https://medium.com/p/327ac262eacb</guid>
<dc:creator><![CDATA[Anthony Lam]]></dc:creator>
<pubDate>Fri, 06 Nov 2015 17:30:55 GMT</pubDate>
</item>
<item>
<title><![CDATA[Quick search]]></title>
<description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@antlam/quick-search-bdd374257e75?source=rss-59f49b9e4b19------2"><img src="https://d262ilb51hltx0.cloudfront.net/fit/c/600/200/1*DyBNARNADZsexPnxkMaEgQ.png" width="600" height="200"></a></p><p class="medium-feed-snippet">Instantly search with any of your search providers</p><p class="medium-feed-link"><a href="https://medium.com/@antlam/quick-search-bdd374257e75?source=rss-59f49b9e4b19------2">Continue reading on Medium »</a></p></div>]]></description>
<link>https://medium.com/@antlam/quick-search-bdd374257e75?source=rss-59f49b9e4b19------2</link>
<guid isPermaLink="false">https://medium.com/p/bdd374257e75</guid>
<dc:creator><![CDATA[Anthony Lam]]></dc:creator>
<pubDate>Tue, 01 Sep 2015 17:36:32 GMT</pubDate>
</item>
<item>
<title><![CDATA[Designing helpfulness]]></title>
<description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@antlam/designing-helpfulness-c1777727faf?source=rss-59f49b9e4b19------2"><img src="https://d262ilb51hltx0.cloudfront.net/fit/c/600/200/1*Cg8wkgjwCH7A1Aotec1Okw.png" width="600" height="200"></a></p><p class="medium-feed-snippet">Being there, without being annoying</p><p class="medium-feed-link"><a href="https://medium.com/@antlam/designing-helpfulness-c1777727faf?source=rss-59f49b9e4b19------2">Continue reading on Medium »</a></p></div>]]></description>
<link>https://medium.com/@antlam/designing-helpfulness-c1777727faf?source=rss-59f49b9e4b19------2</link>
<guid isPermaLink="false">https://medium.com/p/c1777727faf</guid>
<dc:creator><![CDATA[Anthony Lam]]></dc:creator>
<pubDate>Tue, 11 Aug 2015 20:59:13 GMT</pubDate>
</item>
<item>
<title><![CDATA[Share to… Firefox?]]></title>
<description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@antlam/share-to-firefox-245984b2da33?source=rss-59f49b9e4b19------2"><img src="https://d262ilb51hltx0.cloudfront.net/fit/c/600/200/1*H5wztlFTvbE1EM_5MRkuzg.png" width="600" height="200"></a></p><p class="medium-feed-snippet">You may remember this from such share intents as &#8220;Add to Firefox&#8221;</p><p class="medium-feed-link"><a href="https://medium.com/@antlam/share-to-firefox-245984b2da33?source=rss-59f49b9e4b19------2">Continue reading on Medium »</a></p></div>]]></description>
<link>https://medium.com/@antlam/share-to-firefox-245984b2da33?source=rss-59f49b9e4b19------2</link>
<guid isPermaLink="false">https://medium.com/p/245984b2da33</guid>
<dc:creator><![CDATA[Anthony Lam]]></dc:creator>
<pubDate>Fri, 08 May 2015 20:18:18 GMT</pubDate>
</item>
<item>
<title><![CDATA[Open multiple links]]></title>
<description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@antlam/open-multiple-links-1ce475c47de3?source=rss-59f49b9e4b19------2"><img src="https://d262ilb51hltx0.cloudfront.net/fit/c/600/200/1*yEQ5DjomHZIgVzUN-FKx2A.jpeg" width="600" height="200"></a></p><p class="medium-feed-snippet">Queue links in Firefox instead of switching applications each time.</p><p class="medium-feed-link"><a href="https://medium.com/@antlam/open-multiple-links-1ce475c47de3?source=rss-59f49b9e4b19------2">Continue reading on Medium »</a></p></div>]]></description>
<link>https://medium.com/@antlam/open-multiple-links-1ce475c47de3?source=rss-59f49b9e4b19------2</link>
<guid isPermaLink="false">https://medium.com/p/1ce475c47de3</guid>
<dc:creator><![CDATA[Anthony Lam]]></dc:creator>
<pubDate>Tue, 14 Apr 2015 18:44:59 GMT</pubDate>
</item>
<item>
<title><![CDATA[Firefox for Android on Tablets]]></title>
<description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@antlam/firefox-for-android-on-tablets-f67edc83dd46?source=rss-59f49b9e4b19------2"><img src="https://d262ilb51hltx0.cloudfront.net/fit/c/600/200/1*H5p3YQ1NGpfGPDryd22Ujg.png" width="600" height="200"></a></p><p class="medium-feed-snippet">Redesigning the browser interface&#8202;&#8212;&#8202;Part two</p><p class="medium-feed-link"><a href="https://medium.com/@antlam/firefox-for-android-on-tablets-f67edc83dd46?source=rss-59f49b9e4b19------2">Continue reading on Medium »</a></p></div>]]></description>
<link>https://medium.com/@antlam/firefox-for-android-on-tablets-f67edc83dd46?source=rss-59f49b9e4b19------2</link>
<guid isPermaLink="false">https://medium.com/p/f67edc83dd46</guid>
<dc:creator><![CDATA[Anthony Lam]]></dc:creator>
<pubDate>Tue, 03 Feb 2015 20:29:18 GMT</pubDate>
</item>
<item>
<title><![CDATA[Are big phones back?]]></title>
<description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@antlam/are-big-phones-back-59550ba0f24e?source=rss-59f49b9e4b19------2"><img src="https://d262ilb51hltx0.cloudfront.net/fit/c/600/200/1*XArwkY9ZcmtCkEhDwl0aKA.jpeg" width="600" height="200"></a></p><p class="medium-feed-snippet">Some thoughts and impressions</p><p class="medium-feed-link"><a href="https://medium.com/@antlam/are-big-phones-back-59550ba0f24e?source=rss-59f49b9e4b19------2">Continue reading on Medium »</a></p></div>]]></description>
<link>https://medium.com/@antlam/are-big-phones-back-59550ba0f24e?source=rss-59f49b9e4b19------2</link>
<guid isPermaLink="false">https://medium.com/p/59550ba0f24e</guid>
<dc:creator><![CDATA[Anthony Lam]]></dc:creator>
<pubDate>Tue, 23 Dec 2014 20:05:36 GMT</pubDate>
</item>
<item>
<title><![CDATA[Firefox for Android looks a bit different]]></title>
<description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@antlam/firefox-for-android-looks-a-bit-different-8ae8eba41b1f?source=rss-59f49b9e4b19------2"><img src="https://d262ilb51hltx0.cloudfront.net/fit/c/600/200/1*Lk31G3Qt2fs5WcOtBQQVgw.png" width="600" height="200"></a></p><p class="medium-feed-snippet">Redesigning the browser interface</p><p class="medium-feed-link"><a href="https://medium.com/@antlam/firefox-for-android-looks-a-bit-different-8ae8eba41b1f?source=rss-59f49b9e4b19------2">Continue reading on Medium »</a></p></div>]]></description>
<link>https://medium.com/@antlam/firefox-for-android-looks-a-bit-different-8ae8eba41b1f?source=rss-59f49b9e4b19------2</link>
<guid isPermaLink="false">https://medium.com/p/8ae8eba41b1f</guid>
<dc:creator><![CDATA[Anthony Lam]]></dc:creator>
<pubDate>Fri, 29 Aug 2014 23:38:07 GMT</pubDate>
</item>
<item>
<title><![CDATA[My fancy new watch]]></title>
<description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@antlam/my-fancy-new-watch-4856162890a3?source=rss-59f49b9e4b19------2"><img src="https://d262ilb51hltx0.cloudfront.net/fit/c/600/200/1*_gsBD-Vw7qevrwLxXZe8jA.jpeg" width="600" height="200"></a></p><p class="medium-feed-snippet">Early thoughts</p><p class="medium-feed-link"><a href="https://medium.com/@antlam/my-fancy-new-watch-4856162890a3?source=rss-59f49b9e4b19------2">Continue reading on Medium »</a></p></div>]]></description>
<link>https://medium.com/@antlam/my-fancy-new-watch-4856162890a3?source=rss-59f49b9e4b19------2</link>
<guid isPermaLink="false">https://medium.com/p/4856162890a3</guid>
<dc:creator><![CDATA[Anthony Lam]]></dc:creator>
<pubDate>Tue, 22 Jul 2014 01:36:52 GMT</pubDate>
</item>
</channel>

Просмотреть файл

@ -0,0 +1,314 @@
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
<channel>
<title>SPIEGEL ONLINE - Schlagzeilen</title>
<link>http://www.spiegel.de</link>
<description>Deutschlands führende Nachrichtenseite. Alles Wichtige aus Politik, Wirtschaft, Sport, Kultur, Wissenschaft, Technik und mehr.</description>
<language>de</language>
<pubDate>Wed, 27 Jan 2016 18:20:31 +0100</pubDate>
<lastBuildDate>Wed, 27 Jan 2016 18:20:31 +0100</lastBuildDate>
<image>
<title>SPIEGEL ONLINE</title>
<link>http://www.spiegel.de</link>
<url>http://www.spiegel.de/static/sys/logo_120x61.gif</url>
</image>
<item>
<title>Angebliche Vergewaltigung einer 13-Jährigen: Steinmeier kanzelt russischen Minister Lawrow ab</title>
<link>http://www.spiegel.de/politik/ausland/steinmeier-kanzelt-lawrow-ab-aerger-um-angebliche-vergewaltigung-a-1074292.html#ref=rss</link>
<description>Der Ton wird scharf zwischen Berlin und Moskau: Frank-Walter Steinmeier wirft dem russischen Außenminister Lawrow politische Propaganda vor - es geht um die angebliche Vergewaltigung einer 13-Jährigen in Berlin.</description>
<category>Politik</category>
<pubDate>Wed, 27 Jan 2016 18:16:16 +0100</pubDate>
<guid>http://www.spiegel.de/politik/ausland/steinmeier-kanzelt-lawrow-ab-aerger-um-angebliche-vergewaltigung-a-1074292.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949492-thumbsmall-wtgq.jpg" hspace="5" align="left" >Der Ton wird scharf zwischen Berlin und Moskau: Frank-Walter Steinmeier wirft dem russischen Außenminister Lawrow politische Propaganda vor - es geht um die angebliche Vergewaltigung einer 13-Jährigen in Berlin.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949492-thumbsmall-wtgq.jpg"/>
</item>
<item>
<title>Grafischer Überblick: Hier gibt es die wenigsten Herzinfarkte in Deutschland</title>
<link>http://www.spiegel.de/gesundheit/diagnose/ostdeutsche-sterben-deutlich-haeufiger-an-einem-herzinfarkt-a-1074231.html#ref=rss</link>
<description>Nirgendwo arbeiten mehr Kardiologen als in Hamburg - auch deshalb gibt es dort weniger Herzinfarkte als in anderen Bundesländern. Wie sieht es in Ihrer Gegend aus, wo ist die Sterblichkeit am höchsten? Der Überblick.</description>
<category>Gesundheit</category>
<pubDate>Wed, 27 Jan 2016 18:08:00 +0100</pubDate>
<guid>http://www.spiegel.de/gesundheit/diagnose/ostdeutsche-sterben-deutlich-haeufiger-an-einem-herzinfarkt-a-1074231.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-566602-thumbsmall-bxcg.jpg" hspace="5" align="left" >Nirgendwo arbeiten mehr Kardiologen als in Hamburg - auch deshalb gibt es dort weniger Herzinfarkte als in anderen Bundesländern. Wie sieht es in Ihrer Gegend aus, wo ist die Sterblichkeit am höchsten? Der Überblick.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-566602-thumbsmall-bxcg.jpg"/>
</item>
<item>
<title>Nachhilfe für gute Schüler: Lasst Eure Kinder auch das Scheitern lernen</title>
<link>http://www.spiegel.de/schulspiegel/nachhilfe-entspannte-schueler-brauchen-entspannte-eltern-a-1074197.html#ref=rss</link>
<description>Selbst gute Schüler werden von ihren Eltern zur Nachhilfe geschickt. Das schadet mehr, als es nützt - denn die Kinder lernen dabei vor allem eines: Dass sie nicht scheitern dürfen.</description>
<category>SchulSPIEGEL</category>
<pubDate>Wed, 27 Jan 2016 18:02:00 +0100</pubDate>
<guid>http://www.spiegel.de/schulspiegel/nachhilfe-entspannte-schueler-brauchen-entspannte-eltern-a-1074197.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-396678-thumbsmall-dhws.jpg" hspace="5" align="left" >Selbst gute Schüler werden von ihren Eltern zur Nachhilfe geschickt. Das schadet mehr, als es nützt - denn die Kinder lernen dabei vor allem eines: Dass sie nicht scheitern dürfen.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-396678-thumbsmall-dhws.jpg"/>
</item>
<item>
<title>Germanwings-Katastrophe: Arbeitsgruppe regt Schleuse zwischen Kabine und Cockpit an</title>
<link>http://www.spiegel.de/panorama/germanwings-katastrophe-arbeitsgruppe-legt-abschlussbericht-vor-a-1074294.html#ref=rss</link>
<description>Wie sicher muss ein Flugzeugcockpit sein? Nach dem Germanwings-Absturz mit 150 Toten hat sich eine Arbeitsgruppe mit dieser Frage befasst - und nun ihren Abschlussbericht vorgelegt.</description>
<category>Panorama</category>
<pubDate>Wed, 27 Jan 2016 17:52:00 +0100</pubDate>
<guid>http://www.spiegel.de/panorama/germanwings-katastrophe-arbeitsgruppe-legt-abschlussbericht-vor-a-1074294.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-828832-thumbsmall-gjvf.jpg" hspace="5" align="left" >Wie sicher muss ein Flugzeugcockpit sein? Nach dem Germanwings-Absturz mit 150 Toten hat sich eine Arbeitsgruppe mit dieser Frage befasst - und nun ihren Abschlussbericht vorgelegt.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-828832-thumbsmall-gjvf.jpg"/>
</item>
<item>
<title>Polen: Händler wehren sich gegen Supermarktsteuer</title>
<link>http://www.spiegel.de/wirtschaft/soziales/polen-will-internationale-einzelhaendler-hoeher-besteuern-a-1074101.html#ref=rss</link>
<description>Polens Regierung plant, Einzelhändler höher zu besteuern - und will mit den Einnahmen soziale Wohltaten finanzieren. Besonders trifft es ausländische Unternehmen wie Kaufland und Metro.</description>
<category>Wirtschaft</category>
<pubDate>Wed, 27 Jan 2016 17:46:10 +0100</pubDate>
<guid>http://www.spiegel.de/wirtschaft/soziales/polen-will-internationale-einzelhaendler-hoeher-besteuern-a-1074101.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949308-thumbsmall-wwsr.jpg" hspace="5" align="left" >Polens Regierung plant, Einzelhändler höher zu besteuern - und will mit den Einnahmen soziale Wohltaten finanzieren. Besonders trifft es ausländische Unternehmen wie Kaufland und Metro.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949308-thumbsmall-wwsr.jpg"/>
</item>
<item>
<title>Übergriffe in Köln: Polizei erteilt Silvester-Verdächtigen Karnevalverbot</title>
<link>http://www.spiegel.de/panorama/justiz/koeln-polizei-erteilt-silvester-verdaechtigen-verbote-fuer-karneval-a-1074274.html#ref=rss</link>
<description>Kölns Polizei bereitet sich auf die Karnevalstage vor: Tatverdächtige aus der Silvesternacht sollen mit Zutrittsverboten von bestimmten Orten ferngehalten werden. Der Polizeipräsident forderte die Narren zudem auf, keine Spielzeugwaffen zu tragen.</description>
<category>Panorama</category>
<pubDate>Wed, 27 Jan 2016 17:23:00 +0100</pubDate>
<guid>http://www.spiegel.de/panorama/justiz/koeln-polizei-erteilt-silvester-verdaechtigen-verbote-fuer-karneval-a-1074274.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-942482-thumbsmall-qyge.jpg" hspace="5" align="left" >Kölns Polizei bereitet sich auf die Karnevalstage vor: Tatverdächtige aus der Silvesternacht sollen mit Zutrittsverboten von bestimmten Orten ferngehalten werden. Der Polizeipräsident forderte die Narren zudem auf, keine Spielzeugwaffen zu tragen.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-942482-thumbsmall-qyge.jpg"/>
</item>
<item>
<title>"The Hateful 8"-Stars im Interview: "Wahnsinn, was da alles passiert!"</title>
<link>http://www.spiegel.de/kultur/kino/the-hateful-8-quentin-tarantino-und-jennifer-jason-leigh-im-interview-a-1074202.html#ref=rss</link>
<description>Sieben Männer und eine Frau - in seinem Western "The Hateful 8" entwirft Quentin Tarantino ein brutales Abbild der US-Gesellschaft. Hier erklären der Regisseur und seine Hauptdarstellerin, warum es sich lohnt, den Film gleich mehrmals anzusehen.</description>
<category>Kultur</category>
<pubDate>Wed, 27 Jan 2016 17:08:00 +0100</pubDate>
<guid>http://www.spiegel.de/kultur/kino/the-hateful-8-quentin-tarantino-und-jennifer-jason-leigh-im-interview-a-1074202.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949256-thumbsmall-hbrj.jpg" hspace="5" align="left" >Sieben Männer und eine Frau - in seinem Western "The Hateful 8" entwirft Quentin Tarantino ein brutales Abbild der US-Gesellschaft. Hier erklären der Regisseur und seine Hauptdarstellerin, warum es sich lohnt, den Film gleich mehrmals anzusehen.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949256-thumbsmall-hbrj.jpg"/>
</item>
<item>
<title>Drama auf zugefrorenem Teich: Baby in akuter Lebensgefahr - Messer gefunden</title>
<link>http://www.spiegel.de/panorama/justiz/hamburg-vater-mit-baby-in-zugefrorenem-teich-eingebrochen-messer-gefunden-a-1074258.html#ref=rss</link>
<description>Der Fall gibt Rätsel auf: In Hamburg wird ein Vater mit seinem Baby aus einem zugefrorenen Teich gerettet - zwei Männer hätten ihn überfallen, sagt der 24-Jährige. Nun haben Ermittler in der Nähe des Gewässers ein Messer gefunden.</description>
<category>Panorama</category>
<pubDate>Wed, 27 Jan 2016 16:32:00 +0100</pubDate>
<guid>http://www.spiegel.de/panorama/justiz/hamburg-vater-mit-baby-in-zugefrorenem-teich-eingebrochen-messer-gefunden-a-1074258.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949367-thumbsmall-vpsq.jpg" hspace="5" align="left" >Der Fall gibt Rätsel auf: In Hamburg wird ein Vater mit seinem Baby aus einem zugefrorenen Teich gerettet - zwei Männer hätten ihn überfallen, sagt der 24-Jährige. Nun haben Ermittler in der Nähe des Gewässers ein Messer gefunden.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949367-thumbsmall-vpsq.jpg"/>
</item>
<item>
<title>Rheinland-Pfalz: Elefantenrunde soll mit sechs Parteien stattfinden</title>
<link>http://www.spiegel.de/politik/deutschland/swr-fernsehdebatte-jetzt-mit-sechs-parteien-a-1074262.html#ref=rss</link>
<description>Erst drei, dann eine, jetzt sechs Parteien: Die TV-Diskussion im Südwestrundfunk zur rheinland-pfälzischen Landtagswahl findet nun in ganz großer Runde statt.</description>
<category>Politik</category>
<pubDate>Wed, 27 Jan 2016 16:29:00 +0100</pubDate>
<guid>http://www.spiegel.de/politik/deutschland/swr-fernsehdebatte-jetzt-mit-sechs-parteien-a-1074262.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-946925-thumbsmall-icoq.jpg" hspace="5" align="left" >Erst drei, dann eine, jetzt sechs Parteien: Die TV-Diskussion im Südwestrundfunk zur rheinland-pfälzischen Landtagswahl findet nun in ganz großer Runde statt.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-946925-thumbsmall-icoq.jpg"/>
</item>
<item>
<title>Blauer Brief: Britische Schulleiterin mahnt Pyjama-Eltern ab</title>
<link>http://www.spiegel.de/schulspiegel/direktorin-appelliert-an-eltern-bringt-eure-kinder-nicht-im-schlafanzug-zur-schule-a-1074167.html#ref=rss</link>
<description>Rektorin Kate Chisholm hat genug: Ständig beobachtet sie Eltern, die noch im Schlafanzug stecken, wenn sie ihre Kinder an der Schule absetzen. Nun schrieb sie einen Brandbrief, die Elternschaft reagiert gespalten.</description>
<category>SchulSPIEGEL</category>
<pubDate>Wed, 27 Jan 2016 16:26:00 +0100</pubDate>
<guid>http://www.spiegel.de/schulspiegel/direktorin-appelliert-an-eltern-bringt-eure-kinder-nicht-im-schlafanzug-zur-schule-a-1074167.html</guid>
<content:encoded><![CDATA[Rektorin Kate Chisholm hat genug: Ständig beobachtet sie Eltern, die noch im Schlafanzug stecken, wenn sie ihre Kinder an der Schule absetzen. Nun schrieb sie einen Brandbrief, die Elternschaft reagiert gespalten.]]></content:encoded>
</item>
<item>
<title>Zwischenruf bei Merkel-Besuch: Hochschule verwirft juristische Schritte gegen Stör-Professor</title>
<link>http://www.spiegel.de/unispiegel/studium/zwischenruf-bei-merkel-besuch-hochschule-verwirft-juristische-schritte-gegen-professor-a-1074208.html#ref=rss</link>
<description>Seine politische Stör-Aktion während einer Rede von Kanzlerin Merkel ist für einen Merseburger Professor glimpflich ausgegangen. Die Hochschule sieht von juristischen Schritten ab. </description>
<category>UniSPIEGEL</category>
<pubDate>Wed, 27 Jan 2016 16:08:00 +0100</pubDate>
<guid>http://www.spiegel.de/unispiegel/studium/zwischenruf-bei-merkel-besuch-hochschule-verwirft-juristische-schritte-gegen-professor-a-1074208.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949364-thumbsmall-nnis.jpg" hspace="5" align="left" >Seine politische Stör-Aktion während einer Rede von Kanzlerin Merkel ist für einen Merseburger Professor glimpflich ausgegangen. Die Hochschule sieht von juristischen Schritten ab. ]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949364-thumbsmall-nnis.jpg"/>
</item>
<item>
<title>Bundesautobahngesellschaft: Verkehrsminister wehren sich gegen "Mammutbehörde"</title>
<link>http://www.spiegel.de/auto/aktuell/bundesautobahngesellschaft-widerstand-der-verkehrsminister-a-1074198.html#ref=rss</link>
<description>Der Bund könnte die Gründung einer Bundesautobahngesellschaft vorantreiben. Mehrere Verkehrsminister der Länder stellen sich dagegen - auch aus Furcht vor privaten Investoren beim Fernstraßenbau. </description>
<category>Auto</category>
<pubDate>Wed, 27 Jan 2016 15:54:00 +0100</pubDate>
<guid>http://www.spiegel.de/auto/aktuell/bundesautobahngesellschaft-widerstand-der-verkehrsminister-a-1074198.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949241-thumbsmall-cksv.jpg" hspace="5" align="left" >Der Bund könnte die Gründung einer Bundesautobahngesellschaft vorantreiben. Mehrere Verkehrsminister der Länder stellen sich dagegen - auch aus Furcht vor privaten Investoren beim Fernstraßenbau. ]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949241-thumbsmall-cksv.jpg"/>
</item>
<item>
<title>Glasfaser-Ausbau: Dobrindt will schnelles Netz unter die Autobahnen legen</title>
<link>http://www.spiegel.de/netzwelt/netzpolitik/alexander-dobrindt-will-schnelles-netz-unter-die-autobahnen-legen-a-1074151.html#ref=rss</link>
<description>Jede Baustelle soll Bandbreite bringen: Die Bundesregierung beschließt, dass künftig beim Straßenbau automatisch Glasfaserkabel verlegt werden müssen. Kommt Deutschland so schneller ins Netz?</description>
<category>Netzwelt</category>
<pubDate>Wed, 27 Jan 2016 15:52:00 +0100</pubDate>
<guid>http://www.spiegel.de/netzwelt/netzpolitik/alexander-dobrindt-will-schnelles-netz-unter-die-autobahnen-legen-a-1074151.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949166-thumbsmall-xrfd.jpg" hspace="5" align="left" >Jede Baustelle soll Bandbreite bringen: Die Bundesregierung beschließt, dass künftig beim Straßenbau automatisch Glasfaserkabel verlegt werden müssen. Kommt Deutschland so schneller ins Netz?]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949166-thumbsmall-xrfd.jpg"/>
</item>
<item>
<title>Handball-Insolvenz: Flensburg will den HSV verklagen</title>
<link>http://www.spiegel.de/sport/sonst/handball-bundesliga-sg-flensburg-handewitt-klagt-gegen-hsv-a-1074260.html#ref=rss</link>
<description>Einem nackten Mann kann man nicht in die Tasche greifen? Die SG Flensburg-Handewitt will den insolventen HSV Handball verklagen. Der Traditionsverein will Schadenersatz aus Hamburg haben.</description>
<category>Sport</category>
<pubDate>Wed, 27 Jan 2016 15:49:00 +0100</pubDate>
<guid>http://www.spiegel.de/sport/sonst/handball-bundesliga-sg-flensburg-handewitt-klagt-gegen-hsv-a-1074260.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-948459-thumbsmall-banl.jpg" hspace="5" align="left" >Einem nackten Mann kann man nicht in die Tasche greifen? Die SG Flensburg-Handewitt will den insolventen HSV Handball verklagen. Der Traditionsverein will Schadenersatz aus Hamburg haben.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-948459-thumbsmall-banl.jpg"/>
</item>
<item>
<title>Lage am Lageso: Berliner Senatsverwaltung bestreitet Tod eines Flüchtlings</title>
<link>http://www.spiegel.de/politik/deutschland/berlin-fluechtling-vom-lageso-tot-senat-widerspricht-a-1074255.html#ref=rss</link>
<description>Ist in Berlin ein syrischer Flüchtling gestorben, nachdem er lange vor dem Lageso warten musste? Der Helfer, der darüber berichtete, ist abgetaucht - die Senatsverwaltung widerspricht der Darstellung über den Todesfall.</description>
<category>Politik</category>
<pubDate>Wed, 27 Jan 2016 15:45:00 +0100</pubDate>
<guid>http://www.spiegel.de/politik/deutschland/berlin-fluechtling-vom-lageso-tot-senat-widerspricht-a-1074255.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949380-thumbsmall-umdf.jpg" hspace="5" align="left" >Ist in Berlin ein syrischer Flüchtling gestorben, nachdem er lange vor dem Lageso warten musste? Der Helfer, der darüber berichtete, ist abgetaucht - die Senatsverwaltung widerspricht der Darstellung über den Todesfall.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949380-thumbsmall-umdf.jpg"/>
</item>
<item>
<title>Tierarzt-Ikone: Evan Antin, der "heißeste Veterinär der Welt" </title>
<link>http://www.spiegel.de/panorama/leute/tierarzt-evan-antin-ist-der-sexiest-veterinaer-ever-laut-people-a-1074229.html#ref=rss</link>
<description>Evan Antin ist Tierarzt, Model und Personal Trainer. So irritierend gutaussehend, dass er zum "Sexiest Tierbetörer" avancierte. Trotz seiner Vorliebe für blutiges Gedärm und anatomische Anomalien.</description>
<category>Panorama</category>
<pubDate>Wed, 27 Jan 2016 15:31:00 +0100</pubDate>
<guid>http://www.spiegel.de/panorama/leute/tierarzt-evan-antin-ist-der-sexiest-veterinaer-ever-laut-people-a-1074229.html</guid>
<content:encoded><![CDATA[Evan Antin ist Tierarzt, Model und Personal Trainer. So irritierend gutaussehend, dass er zum "Sexiest Tierbetörer" avancierte. Trotz seiner Vorliebe für blutiges Gedärm und anatomische Anomalien.]]></content:encoded>
</item>
<item>
<title>Verteidigungshaushalt: Schäuble will mehr Geld für Bundeswehr ausgeben</title>
<link>http://www.spiegel.de/politik/deutschland/wolfgang-schaeuble-einverstanden-mit-mehr-geld-fuer-ruestung-a-1074242.html#ref=rss</link>
<description>Drei Milliarden Euro mehr pro Jahr für Waffen: Finanzminister Schäuble sieht die Aufrüstungspläne der Verteidigungsministerin von der Leyen positiv.</description>
<category>Politik</category>
<pubDate>Wed, 27 Jan 2016 15:29:00 +0100</pubDate>
<guid>http://www.spiegel.de/politik/deutschland/wolfgang-schaeuble-einverstanden-mit-mehr-geld-fuer-ruestung-a-1074242.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-947025-thumbsmall-qecb.jpg" hspace="5" align="left" >Drei Milliarden Euro mehr pro Jahr für Waffen: Finanzminister Schäuble sieht die Aufrüstungspläne der Verteidigungsministerin von der Leyen positiv.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-947025-thumbsmall-qecb.jpg"/>
</item>
<item>
<title>Doping-Vorwürfe: NFL leitet Untersuchung gegen Manning ein</title>
<link>http://www.spiegel.de/sport/sonst/nfl-peyton-manning-unter-doping-verdacht-a-1074230.html#ref=rss</link>
<description>Die NFL prüft Vorwürfe gegen einen Superstar: Die Football-Liga geht jetzt offiziell den Doping-Gerüchten um Peyton Manning nach. Der Quarterback soll über seine Frau Hormone geordert haben.</description>
<category>Sport</category>
<pubDate>Wed, 27 Jan 2016 15:23:00 +0100</pubDate>
<guid>http://www.spiegel.de/sport/sonst/nfl-peyton-manning-unter-doping-verdacht-a-1074230.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949287-thumbsmall-cwxj.jpg" hspace="5" align="left" >Die NFL prüft Vorwürfe gegen einen Superstar: Die Football-Liga geht jetzt offiziell den Doping-Gerüchten um Peyton Manning nach. Der Quarterback soll über seine Frau Hormone geordert haben.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949287-thumbsmall-cwxj.jpg"/>
</item>
<item>
<title>Posse um SWR-Elefantenrunde: Feigheit vor dem Feind</title>
<link>http://www.spiegel.de/politik/deutschland/spd-und-swr-posse-um-tv-auftritt-in-rheinland-pfalz-kommentar-a-1074235.html#ref=rss</link>
<description>Die Sozialdemokraten weigern sich, an einer TV-Debatte mit der AfD teilzunehmen, jetzt geht das Spektakel in eine neue Runde. Statt der Ministerpräsidentin soll der SPD-Landeschef ran. Wie absurd ist das denn? </description>
<category>Politik</category>
<pubDate>Wed, 27 Jan 2016 15:23:00 +0100</pubDate>
<guid>http://www.spiegel.de/politik/deutschland/spd-und-swr-posse-um-tv-auftritt-in-rheinland-pfalz-kommentar-a-1074235.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949309-thumbsmall-zhac.jpg" hspace="5" align="left" >Die Sozialdemokraten weigern sich, an einer TV-Debatte mit der AfD teilzunehmen, jetzt geht das Spektakel in eine neue Runde. Statt der Ministerpräsidentin soll der SPD-Landeschef ran. Wie absurd ist das denn? ]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949309-thumbsmall-zhac.jpg"/>
</item>
<item>
<title>Apple-Browser: Und plötzlich stürzt Safari ab</title>
<link>http://www.spiegel.de/netzwelt/apps/apple-safari-browser-stuerzt-ploetzlich-ab-a-1074217.html#ref=rss</link>
<description>Seit einigen Stunden haben Apple-Nutzer Probleme mit dem Safari-Browser. Wodurch die Abstürze ausgelöst werden, ist unklar. Doch mit einem kleinen Trick kann man sich helfen.</description>
<category>Netzwelt</category>
<pubDate>Wed, 27 Jan 2016 15:18:00 +0100</pubDate>
<guid>http://www.spiegel.de/netzwelt/apps/apple-safari-browser-stuerzt-ploetzlich-ab-a-1074217.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949312-thumbsmall-jqlt.jpg" hspace="5" align="left" >Seit einigen Stunden haben Apple-Nutzer Probleme mit dem Safari-Browser. Wodurch die Abstürze ausgelöst werden, ist unklar. Doch mit einem kleinen Trick kann man sich helfen.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949312-thumbsmall-jqlt.jpg"/>
</item>
<item>
<title>EU-Bericht zu Grenzsicherung: Griechenland droht Schengen-Rauswurf</title>
<link>http://www.spiegel.de/politik/ausland/griechenland-eu-kommission-droht-mit-schengen-rauswurf-a-1074201.html#ref=rss</link>
<description>Griechenland gerät in der Flüchtlingskrise unter massiven Druck der EU: Die Kommission will Athen Forderungen zum Grenzschutz schicken. Werden die nicht binnen drei Monaten erfüllt, droht der Ausschluss aus dem Schengen-Raum.</description>
<category>Politik</category>
<pubDate>Wed, 27 Jan 2016 15:04:00 +0100</pubDate>
<guid>http://www.spiegel.de/politik/ausland/griechenland-eu-kommission-droht-mit-schengen-rauswurf-a-1074201.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949347-thumbsmall-vbmi.jpg" hspace="5" align="left" >Griechenland gerät in der Flüchtlingskrise unter massiven Druck der EU: Die Kommission will Athen Forderungen zum Grenzschutz schicken. Werden die nicht binnen drei Monaten erfüllt, droht der Ausschluss aus dem Schengen-Raum.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949347-thumbsmall-vbmi.jpg"/>
</item>
<item>
<title>Protest gegen dänisches Asylrecht: Ai Weiwei schließt Ausstellung in Kopenhagen</title>
<link>http://www.spiegel.de/kultur/gesellschaft/protest-gegen-daenisches-asylrecht-ai-weiwei-schliesst-ausstellung-a-1074241.html#ref=rss</link>
<description>Ai Weiwei, Chinas wohl bekanntester Künstler, beendet seine Ausstellung in Kopenhagen vorzeitig. Grund ist eine Verschärfung der Asylregeln in Dänemark.</description>
<category>Kultur</category>
<pubDate>Wed, 27 Jan 2016 15:01:00 +0100</pubDate>
<guid>http://www.spiegel.de/kultur/gesellschaft/protest-gegen-daenisches-asylrecht-ai-weiwei-schliesst-ausstellung-a-1074241.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949292-thumbsmall-uhox.jpg" hspace="5" align="left" >Ai Weiwei, Chinas wohl bekanntester Künstler, beendet seine Ausstellung in Kopenhagen vorzeitig. Grund ist eine Verschärfung der Asylregeln in Dänemark.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949292-thumbsmall-uhox.jpg"/>
</item>
<item>
<title>Deutsche Handballer gegen Dänemark: Jetzt muss es schmutzig werden</title>
<link>http://www.spiegel.de/sport/sonst/handball-em-2016-jetzt-muss-es-schmutzig-werden-a-1074123.html#ref=rss</link>
<description>Noch ein Sieg bis zum Halbfinale: Die deutsche Handball-Nationalmannschaft hat bei der EM einen Lauf, sie ist gierig auf den Titel. Jetzt geht es gegen einen großen Favoriten - und Dänemark wirkt angeschlagen. </description>
<category>Sport</category>
<pubDate>Wed, 27 Jan 2016 14:59:00 +0100</pubDate>
<guid>http://www.spiegel.de/sport/sonst/handball-em-2016-jetzt-muss-es-schmutzig-werden-a-1074123.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949116-thumbsmall-fpcj.jpg" hspace="5" align="left" >Noch ein Sieg bis zum Halbfinale: Die deutsche Handball-Nationalmannschaft hat bei der EM einen Lauf, sie ist gierig auf den Titel. Jetzt geht es gegen einen großen Favoriten - und Dänemark wirkt angeschlagen. ]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949116-thumbsmall-fpcj.jpg"/>
</item>
<item>
<title>Sicherheitslage nach Anschlag: Russland spricht Reisewarnung für Türkei aus</title>
<link>http://www.spiegel.de/reise/aktuell/russland-spricht-reisewarnung-fuer-tuerkei-aus-a-1074225.html#ref=rss</link>
<description>Die russische Regierung warnt ihre Bürger vor Reisen in die Türkei. Damit schränkt sie den Tourismus in das Land weiter ein. Nach dem Anschlag in Istanbul sind auch die Buchungen von deutschen Urlaubern eingebrochen.</description>
<category>Reise</category>
<pubDate>Wed, 27 Jan 2016 14:58:00 +0100</pubDate>
<guid>http://www.spiegel.de/reise/aktuell/russland-spricht-reisewarnung-fuer-tuerkei-aus-a-1074225.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-378624-thumbsmall-xtnj.jpg" hspace="5" align="left" >Die russische Regierung warnt ihre Bürger vor Reisen in die Türkei. Damit schränkt sie den Tourismus in das Land weiter ein. Nach dem Anschlag in Istanbul sind auch die Buchungen von deutschen Urlaubern eingebrochen.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-378624-thumbsmall-xtnj.jpg"/>
</item>
<item>
<title>Bayern-Deal mit Katar: Scheich Di!</title>
<link>http://www.spiegel.de/sport/fussball/fc-bayern-muenchen-und-der-katar-deal-in-der-pflicht-kommentar-a-1074187.html#ref=rss</link>
<description>Der FC Bayern schließt einen Sponsoren-Deal mit Katar ab, die Kritik darüber ist ebenso berechtigt wie vorhersehbar. Dabei darf es nicht bleiben. Nehmen wir den Rekordmeister doch beim Wort.</description>
<category>Sport</category>
<pubDate>Wed, 27 Jan 2016 14:52:00 +0100</pubDate>
<guid>http://www.spiegel.de/sport/fussball/fc-bayern-muenchen-und-der-katar-deal-in-der-pflicht-kommentar-a-1074187.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949236-thumbsmall-hyyw.jpg" hspace="5" align="left" >Der FC Bayern schließt einen Sponsoren-Deal mit Katar ab, die Kritik darüber ist ebenso berechtigt wie vorhersehbar. Dabei darf es nicht bleiben. Nehmen wir den Rekordmeister doch beim Wort.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949236-thumbsmall-hyyw.jpg"/>
</item>
<item>
<title>Flüchtlingskrise: EU wirft Griechenland schwere Mängel bei Grenzkontrolle vor</title>
<link>http://www.spiegel.de/politik/ausland/fluechtlinge-eu-wirft-griechenland-maengel-bei-grenzkontrolle-vor-a-1074219.html#ref=rss</link>
<description>Die griechische Regierung verletzt ihre Pflichten bei der Grenzsicherung - zu diesem Schluss kommt ein Untersuchungsbericht der EU-Kommission. Brüssel spricht nun eine klare Drohung gegen Athen aus.</description>
<category>Politik</category>
<pubDate>Wed, 27 Jan 2016 14:47:00 +0100</pubDate>
<guid>http://www.spiegel.de/politik/ausland/fluechtlinge-eu-wirft-griechenland-maengel-bei-grenzkontrolle-vor-a-1074219.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949273-thumbsmall-ifxg.jpg" hspace="5" align="left" >Die griechische Regierung verletzt ihre Pflichten bei der Grenzsicherung - zu diesem Schluss kommt ein Untersuchungsbericht der EU-Kommission. Brüssel spricht nun eine klare Drohung gegen Athen aus.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949273-thumbsmall-ifxg.jpg"/>
</item>
<item>
<title>Abgasaffäre: Brüssel will Autokonzerne bestrafen können</title>
<link>http://www.spiegel.de/wirtschaft/soziales/abgasaffaere-bruessel-will-autokonzerne-bestrafen-koennen-a-1074228.html#ref=rss</link>
<description>Im Abgas-Skandal ist der VW-Konzern Schuldiger - aber auch die Aufseher in Brüssel sind blamiert. Denn US-Behörden enthüllten, was ihnen jahrelang durch die Lappen ging. Die EU-Kommission will jetzt dafür sorgen, dass sich das nicht wiederholt.</description>
<category>Wirtschaft</category>
<pubDate>Wed, 27 Jan 2016 14:46:00 +0100</pubDate>
<guid>http://www.spiegel.de/wirtschaft/soziales/abgasaffaere-bruessel-will-autokonzerne-bestrafen-koennen-a-1074228.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-938136-thumbsmall-hxbc.jpg" hspace="5" align="left" >Im Abgas-Skandal ist der VW-Konzern Schuldiger - aber auch die Aufseher in Brüssel sind blamiert. Denn US-Behörden enthüllten, was ihnen jahrelang durch die Lappen ging. Die EU-Kommission will jetzt dafür sorgen, dass sich das nicht wiederholt.]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-938136-thumbsmall-hxbc.jpg"/>
</item>
<item>
<title>Bundesverfassungsgericht: Wer alles gegen die Vorratsdatenspeicherung klagt</title>
<link>http://www.spiegel.de/netzwelt/netzpolitik/vorratsdatenspeicherung-wer-klagt-vor-dem-bundesverfassungsgericht-a-1074152.html#ref=rss</link>
<description>Widerstand gegen Vorratsdatenspeicherung: Die FDP hat Klage in Karlsruhe eingereicht, und auch weitere Gegner versuchen, das Gesetz vor Gericht noch zu kippen. Der Überblick. </description>
<category>Netzwelt</category>
<pubDate>Wed, 27 Jan 2016 14:42:00 +0100</pubDate>
<guid>http://www.spiegel.de/netzwelt/netzpolitik/vorratsdatenspeicherung-wer-klagt-vor-dem-bundesverfassungsgericht-a-1074152.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-925932-thumbsmall-zbbn.jpg" hspace="5" align="left" >Widerstand gegen Vorratsdatenspeicherung: Die FDP hat Klage in Karlsruhe eingereicht, und auch weitere Gegner versuchen, das Gesetz vor Gericht noch zu kippen. Der Überblick. ]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-925932-thumbsmall-zbbn.jpg"/>
</item>
<item>
<title>Berliner Flüchtlingsamt: Das Scheitern des Lageso - das Protokoll</title>
<link>http://www.spiegel.de/politik/deutschland/berlin-das-scheitern-des-lageso-eine-chronik-a-1074186.html#ref=rss</link>
<description>Tagelanges Warten, keine Auszahlung von Essensgeld, Gewalt - jetzt angeblich ein Toter: Seit Monaten steht das Berliner Flüchtlingsamt Lageso in den Schlagzeilen. Die Chronologie des Scheiterns. </description>
<category>Politik</category>
<pubDate>Wed, 27 Jan 2016 14:22:00 +0100</pubDate>
<guid>http://www.spiegel.de/politik/deutschland/berlin-das-scheitern-des-lageso-eine-chronik-a-1074186.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949137-thumbsmall-pgoa.jpg" hspace="5" align="left" >Tagelanges Warten, keine Auszahlung von Essensgeld, Gewalt - jetzt angeblich ein Toter: Seit Monaten steht das Berliner Flüchtlingsamt Lageso in den Schlagzeilen. Die Chronologie des Scheiterns. ]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949137-thumbsmall-pgoa.jpg"/>
</item>
<item>
<title>Apple-Gerüchte: So könnte das neue iPhone aussehen. Aber was wünschen Sie sich?</title>
<link>http://www.spiegel.de/netzwelt/gadgets/apple-so-gut-muss-das-iphone-7-sein-a-1074158.html#ref=rss</link>
<description>Ist der iPhone-Boom vorbei? Nicht unbedingt - das nächste Gerät könnte starke neue Features haben. Hier der Stand der Gerüchte. Und Sie können abstimmen: Was brauchen Sie wirklich?</description>
<category>Netzwelt</category>
<pubDate>Wed, 27 Jan 2016 14:17:00 +0100</pubDate>
<guid>http://www.spiegel.de/netzwelt/gadgets/apple-so-gut-muss-das-iphone-7-sein-a-1074158.html</guid>
<content:encoded><![CDATA[<img src="http://www.spiegel.de/images/image-949140-thumbsmall-bdof.jpg" hspace="5" align="left" >Ist der iPhone-Boom vorbei? Nicht unbedingt - das nächste Gerät könnte starke neue Features haben. Hier der Stand der Gerüchte. Und Sie können abstimmen: Was brauchen Sie wirklich?]]></content:encoded>
<enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-949140-thumbsmall-bdof.jpg"/>
</item>
</channel>
</rss>

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
https://en.wikipedia.org/wiki/RSS#Example
-->
<rss version="2.0">
<channel>
<title>RSS Title</title>
<description>This is an example of an RSS feed</description>
<link>http://www.example.com/main.html</link>
<lastBuildDate>Mon, 06 Sep 2010 00:01:00 +0000 </lastBuildDate>
<pubDate>Sun, 06 Sep 2009 16:20:00 +0000</pubDate>
<ttl>1800</ttl>
<item>
<title>Example entry</title>
<description>Here is some text containing an interesting description.</description>
<link>http://www.example.com/blog/post/1</link>
<guid isPermaLink="true">7bd204c6-1655-4c27-aeee-53f933c5395f</guid>
<pubDate>Sun, 06 Sep 2009 16:20:00 +0000</pubDate>
</item>
</channel>
</rss>

Просмотреть файл

@ -0,0 +1,276 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.feeds.parser;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mozilla.gecko.background.testhelpers.TestRunner;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URL;
@RunWith(TestRunner.class)
public class TestSimpleFeedParser {
/**
* Parse and verify the RSS example from Wikipedia:
* https://en.wikipedia.org/wiki/RSS#Example
*/
@Test
public void testRSSExample() throws Exception {
InputStream stream = openFeed("feed_rss_wikipedia.xml");
SimpleFeedParser parser = new SimpleFeedParser();
Feed feed = parser.parse(stream);
Assert.assertNotNull(feed);
Assert.assertEquals("RSS Title", feed.getTitle());
Assert.assertEquals("http://www.example.com/main.html", feed.getWebsiteURL());
Assert.assertNull(feed.getFeedURL());
Assert.assertTrue(feed.isSufficientlyComplete());
Item item = feed.getLastItem();
Assert.assertNotNull(item);
Assert.assertEquals("Example entry", item.getTitle());
Assert.assertEquals("http://www.example.com/blog/post/1", item.getURL());
Assert.assertEquals(1252254000000L, item.getTimestamp());
}
/**
* Parse and verify the ATOM example from Wikipedia:
* https://en.wikipedia.org/wiki/Atom_%28standard%29#Example_of_an_Atom_1.0_feed
*/
@Test
public void testATOMExample() throws Exception {
InputStream stream = openFeed("feed_atom_wikipedia.xml");
SimpleFeedParser parser = new SimpleFeedParser();
Feed feed = parser.parse(stream);
Assert.assertNotNull(feed);
Assert.assertEquals("Example Feed", feed.getTitle());
Assert.assertEquals("http://example.org/", feed.getWebsiteURL());
Assert.assertEquals("http://example.org/feed/", feed.getFeedURL());
Assert.assertTrue(feed.isSufficientlyComplete());
Item item = feed.getLastItem();
Assert.assertNotNull(item);
Assert.assertEquals("Atom-Powered Robots Run Amok", item.getTitle());
Assert.assertEquals("http://example.org/2003/12/13/atom03.html", item.getURL());
Assert.assertEquals(1071340202000L, item.getTimestamp());
}
/**
* Parse and verify a snapshot of a Medium feed.
*/
@Test
public void testMediumFeed() throws Exception {
InputStream stream = openFeed("feed_rss_medium.xml");
SimpleFeedParser parser = new SimpleFeedParser();
Feed feed = parser.parse(stream);
Assert.assertNotNull(feed);
Assert.assertEquals("Anthony Lam on Medium", feed.getTitle());
Assert.assertEquals("https://medium.com/@antlam?source=rss-59f49b9e4b19------2", feed.getWebsiteURL());
Assert.assertEquals("https://medium.com/feed/@antlam", feed.getFeedURL());
Assert.assertTrue(feed.isSufficientlyComplete());
Item item = feed.getLastItem();
Assert.assertNotNull(item);
Assert.assertEquals("UX thoughts for 2016", item.getTitle());
Assert.assertEquals("https://medium.com/@antlam/ux-thoughts-for-2016-1fc1d6e515e8?source=rss-59f49b9e4b19------2", item.getURL());
Assert.assertEquals(1452537838000L, item.getTimestamp());
}
/**
* Parse and verify a snapshot of planet.mozilla.org ATOM feed.
*/
@Test
public void testPlanetMozillaATOMFeed() throws Exception {
InputStream stream = openFeed("feed_atom_planetmozilla.xml");
SimpleFeedParser parser = new SimpleFeedParser();
Feed feed = parser.parse(stream);
Assert.assertNotNull(feed);
Assert.assertEquals("Planet Mozilla", feed.getTitle());
Assert.assertEquals("http://planet.mozilla.org/", feed.getWebsiteURL());
Assert.assertEquals("http://planet.mozilla.org/atom.xml", feed.getFeedURL());
Assert.assertTrue(feed.isSufficientlyComplete());
Item item = feed.getLastItem();
Assert.assertNotNull(item);
Assert.assertEquals("Firefox 45.0 Beta 3 Testday, February 5th", item.getTitle());
Assert.assertEquals("https://quality.mozilla.org/2016/01/firefox-45-0-beta-3-testday-february-5th/", item.getURL());
Assert.assertEquals(1453819255000L, item.getTimestamp());
}
/**
* Parse and verify a snapshot of planet.mozilla.org RSS 2.0 feed.
*/
@Test
public void testPlanetMozillaRSS20Feed() throws Exception {
InputStream stream = openFeed("feed_rss20_planetmozilla.xml");
SimpleFeedParser parser = new SimpleFeedParser();
Feed feed = parser.parse(stream);
Assert.assertNotNull(feed);
Assert.assertEquals("Planet Mozilla", feed.getTitle());
Assert.assertEquals("http://planet.mozilla.org/", feed.getWebsiteURL());
Assert.assertEquals("http://planet.mozilla.org/rss20.xml", feed.getFeedURL());
Assert.assertTrue(feed.isSufficientlyComplete());
Item item = feed.getLastItem();
Assert.assertNotNull(item);
Assert.assertEquals("Aaron Klotz: Announcing Mozdbgext", item.getTitle());
Assert.assertEquals("http://dblohm7.ca/blog/2016/01/26/announcing-mozdbgext/", item.getURL());
Assert.assertEquals(1453837500000L, item.getTimestamp());
}
/**
* Parse and verify a snapshot of planet.mozilla.org RSS 1.0 feed.
*/
@Test
public void testPlanetMozillaRSS10Feed() throws Exception {
InputStream stream = openFeed("feed_rss10_planetmozilla.xml");
SimpleFeedParser parser = new SimpleFeedParser();
Feed feed = parser.parse(stream);
Assert.assertNotNull(feed);
Assert.assertEquals("Planet Mozilla", feed.getTitle());
Assert.assertEquals("http://planet.mozilla.org/", feed.getWebsiteURL());
Assert.assertEquals("http://planet.mozilla.org/rss10.xml", feed.getFeedURL());
Assert.assertTrue(feed.isSufficientlyComplete());
Item item = feed.getLastItem();
Assert.assertNotNull(item);
Assert.assertEquals("Aaron Klotz: Announcing Mozdbgext", item.getTitle());
Assert.assertEquals("http://dblohm7.ca/blog/2016/01/26/announcing-mozdbgext/", item.getURL());
Assert.assertEquals(1453837500000L, item.getTimestamp());
}
/**
* Parse an verify a snapshot of a feedburner ATOM feed.
*/
@Test
public void testFeedburnerAtomFeed() throws Exception {
InputStream stream = openFeed("feed_atom_feedburner.xml");
SimpleFeedParser parser = new SimpleFeedParser();
Feed feed = parser.parse(stream);
Assert.assertNotNull(feed);
Assert.assertEquals("Android Zeitgeist", feed.getTitle());
Assert.assertEquals("http://www.androidzeitgeist.com/", feed.getWebsiteURL());
Assert.assertEquals("http://feeds.feedburner.com/AndroidZeitgeist", feed.getFeedURL());
Assert.assertTrue(feed.isSufficientlyComplete());
Item item = feed.getLastItem();
Assert.assertNotNull(item);
Assert.assertEquals("Support for restricted profiles in Firefox 42", item.getTitle());
Assert.assertEquals("http://feedproxy.google.com/~r/AndroidZeitgeist/~3/xaSicfGuwOU/support-restricted-profiles-firefox.html", item.getURL());
Assert.assertEquals(1442511968239L, item.getTimestamp());
}
/**
* Parse and verify a snapshot of a Tumblr RSS feed.
*/
@Test
public void testTumblrRssFeed() throws Exception {
InputStream stream = openFeed("feed_rss_tumblr.xml");
SimpleFeedParser parser = new SimpleFeedParser();
Feed feed = parser.parse(stream);
Assert.assertNotNull(feed);
Assert.assertEquals("Tumblr Staff", feed.getTitle());
Assert.assertEquals("http://staff.tumblr.com/", feed.getWebsiteURL());
Assert.assertNull(feed.getFeedURL());
Assert.assertTrue(feed.isSufficientlyComplete());
Item item = feed.getLastItem();
Assert.assertNotNull(item);
Assert.assertEquals("hardyboyscovers: Can Nancy Drew see things through and solve...", item.getTitle());
Assert.assertEquals("http://staff.tumblr.com/post/138124026275", item.getURL());
Assert.assertEquals(1453861812000L, item.getTimestamp());
}
/**
* Parse and verify a snapshot of a Spiegel (German news magazine) RSS feed.
*/
@Test
public void testSpiegelRssFeed() throws Exception {
InputStream stream = openFeed("feed_rss_spon.xml");
SimpleFeedParser parser = new SimpleFeedParser();
Feed feed = parser.parse(stream);
Assert.assertNotNull(feed);
Assert.assertEquals("SPIEGEL ONLINE - Schlagzeilen", feed.getTitle());
Assert.assertEquals("http://www.spiegel.de", feed.getWebsiteURL());
Assert.assertNull(feed.getFeedURL());
Assert.assertTrue(feed.isSufficientlyComplete());
Item item = feed.getLastItem();
Assert.assertNotNull(item);
Assert.assertEquals("Angebliche Vergewaltigung einer 13-Jährigen: Steinmeier kanzelt russischen Minister Lawrow ab", item.getTitle());
Assert.assertEquals("http://www.spiegel.de/politik/ausland/steinmeier-kanzelt-lawrow-ab-aerger-um-angebliche-vergewaltigung-a-1074292.html#ref=rss", item.getURL());
Assert.assertEquals(1453914976000L, item.getTimestamp());
}
/**
* Parse and verify a snapshot of a Heise (German tech news) RSS feed.
*/
@Test
public void testHeiseRssFeed() throws Exception {
InputStream stream = openFeed("feed_rss_heise.xml");
SimpleFeedParser parser = new SimpleFeedParser();
Feed feed = parser.parse(stream);
Assert.assertNotNull(feed);
Assert.assertEquals("heise online News", feed.getTitle());
Assert.assertEquals("http://www.heise.de/newsticker/", feed.getWebsiteURL());
Assert.assertNull(feed.getFeedURL());
Assert.assertTrue(feed.isSufficientlyComplete());
Item item = feed.getLastItem();
Assert.assertNotNull(item);
Assert.assertEquals("Google: “Dramatische Verbesserungen” für Chrome in iOS", item.getTitle());
Assert.assertEquals("http://www.heise.de/newsticker/meldung/Google-Dramatische-Verbesserungen-fuer-Chrome-in-iOS-3085808.html?wt_mc=rss.ho.beitrag.atom", item.getURL());
Assert.assertEquals(1453915920000L, item.getTimestamp());
}
private InputStream openFeed(String fileName) throws URISyntaxException, FileNotFoundException, UnsupportedEncodingException {
URL url = getClass().getResource("/" + fileName);
if (url == null) {
throw new FileNotFoundException(fileName);
}
return new BufferedInputStream(new FileInputStream(url.getPath()));
}
}