| @@ -1,23 +1,18 @@ | |||||
| import 'package:xml/xml.dart'; | import 'package:xml/xml.dart'; | ||||
| class RssCategory { | class RssCategory { | ||||
| String domain; | |||||
| String value; | |||||
| final String domain; | |||||
| final String value; | |||||
| RssCategory(this.domain, this.value); | RssCategory(this.domain, this.value); | ||||
| factory RssCategory.parse(XmlElement node) { | |||||
| var domain = node.getAttribute("domain"); | |||||
| var value = node.text; | |||||
| factory RssCategory.parse(XmlElement element) { | |||||
| if (element == null) { | |||||
| return null; | |||||
| } | |||||
| var domain = element.getAttribute("domain"); | |||||
| var value = element.text; | |||||
| return new RssCategory(domain, value); | return new RssCategory(domain, value); | ||||
| } | } | ||||
| @override | |||||
| String toString() { | |||||
| return ''' | |||||
| domain: $domain | |||||
| value: $value | |||||
| '''; | |||||
| } | |||||
| } | } | ||||
| @@ -16,8 +16,11 @@ class RssContent { | |||||
| RssContent(this.value, this.images); | RssContent(this.value, this.images); | ||||
| factory RssContent.parse(XmlElement node) { | |||||
| final content = node.text; | |||||
| factory RssContent.parse(XmlElement element) { | |||||
| if (element == null) { | |||||
| return null; | |||||
| } | |||||
| final content = element.text; | |||||
| final images = <String>[]; | final images = <String>[]; | ||||
| _imagesRegExp.allMatches(content).forEach((match) { | _imagesRegExp.allMatches(content).forEach((match) { | ||||
| images.add(match.group(1)); | images.add(match.group(1)); | ||||
| @@ -0,0 +1,19 @@ | |||||
| import 'package:xml/xml.dart'; | |||||
| class RssEnclosure { | |||||
| final String url; | |||||
| final String type; | |||||
| final int length; | |||||
| RssEnclosure(this.url, this.type, this.length); | |||||
| factory RssEnclosure.parse(XmlElement element) { | |||||
| if (element == null) { | |||||
| return null; | |||||
| } | |||||
| var url = element.getAttribute("url"); | |||||
| var type = element.getAttribute("type"); | |||||
| var length = int.tryParse(element.getAttribute("length") ?? "0"); | |||||
| return new RssEnclosure(url, type, length); | |||||
| } | |||||
| } | |||||
| @@ -1,9 +1,11 @@ | |||||
| import 'package:webfeed/domain/media/media.dart'; | import 'package:webfeed/domain/media/media.dart'; | ||||
| import 'package:webfeed/domain/rss_category.dart'; | import 'package:webfeed/domain/rss_category.dart'; | ||||
| import 'package:webfeed/domain/rss_content.dart'; | import 'package:webfeed/domain/rss_content.dart'; | ||||
| import 'package:webfeed/domain/rss_enclosure.dart'; | |||||
| import 'package:webfeed/domain/rss_source.dart'; | import 'package:webfeed/domain/rss_source.dart'; | ||||
| import 'package:webfeed/util/helpers.dart'; | import 'package:webfeed/util/helpers.dart'; | ||||
| import 'package:xml/xml.dart'; | import 'package:xml/xml.dart'; | ||||
| import 'package:webfeed/util/helpers.dart'; | |||||
| class RssItem { | class RssItem { | ||||
| final String title; | final String title; | ||||
| @@ -18,6 +20,7 @@ class RssItem { | |||||
| final RssSource source; | final RssSource source; | ||||
| final RssContent content; | final RssContent content; | ||||
| final Media media; | final Media media; | ||||
| final RssEnclosure enclosure; | |||||
| RssItem({ | RssItem({ | ||||
| this.title, | this.title, | ||||
| @@ -31,45 +34,25 @@ class RssItem { | |||||
| this.source, | this.source, | ||||
| this.content, | this.content, | ||||
| this.media, | this.media, | ||||
| this.enclosure, | |||||
| }); | }); | ||||
| factory RssItem.parse(XmlElement element) { | factory RssItem.parse(XmlElement element) { | ||||
| var title = xmlGetString(element, "title", strict: false); | |||||
| var description = xmlGetString(element, "description", strict: false); | |||||
| var link = xmlGetString(element, "link", strict: false); | |||||
| var categories = element.findElements("category").map((element) { | |||||
| return new RssCategory.parse(element); | |||||
| }).toList(); | |||||
| var guid = xmlGetString(element, "guid", strict: false); | |||||
| var pubDate = xmlGetString(element, "pubDate", strict: false); | |||||
| var author = xmlGetString(element, "author", strict: false); | |||||
| var comments = xmlGetString(element, "comments", strict: false); | |||||
| RssSource source; | |||||
| try { | |||||
| source = new RssSource.parse(element.findElements("source").first); | |||||
| } on StateError {} | |||||
| RssContent content; | |||||
| try { | |||||
| content = | |||||
| new RssContent.parse(element.findElements("content:encoded").first); | |||||
| } on StateError {} | |||||
| return new RssItem( | return new RssItem( | ||||
| title: title, | |||||
| description: description, | |||||
| link: link, | |||||
| categories: categories, | |||||
| guid: guid, | |||||
| pubDate: pubDate, | |||||
| author: author, | |||||
| comments: comments, | |||||
| source: source, | |||||
| content: content, | |||||
| title: findElementOrNull(element, "title")?.text, | |||||
| description: findElementOrNull(element, "description")?.text, | |||||
| link: findElementOrNull(element, "link")?.text, | |||||
| categories: element.findElements("category").map((element) { | |||||
| return new RssCategory.parse(element); | |||||
| }).toList(), | |||||
| guid: findElementOrNull(element, "guid")?.text, | |||||
| pubDate: findElementOrNull(element, "pubDate")?.text, | |||||
| author: findElementOrNull(element, "author")?.text, | |||||
| comments: findElementOrNull(element, "comments")?.text, | |||||
| source: RssSource.parse(findElementOrNull(element, "source")), | |||||
| content: RssContent.parse(findElementOrNull(element, "content:encoded")), | |||||
| media: Media.parse(element), | media: Media.parse(element), | ||||
| enclosure: RssEnclosure.parse(findElementOrNull(element, "enclosure")), | |||||
| ); | ); | ||||
| } | } | ||||
| @@ -6,18 +6,13 @@ class RssSource { | |||||
| RssSource(this.url, this.value); | RssSource(this.url, this.value); | ||||
| factory RssSource.parse(XmlElement node) { | |||||
| var url = node.getAttribute("url"); | |||||
| var value = node.text; | |||||
| factory RssSource.parse(XmlElement element) { | |||||
| if (element == null) { | |||||
| return null; | |||||
| } | |||||
| var url = element.getAttribute("url"); | |||||
| var value = element.text; | |||||
| return new RssSource(url, value); | return new RssSource(url, value); | ||||
| } | } | ||||
| @override | |||||
| String toString() { | |||||
| return ''' | |||||
| url: $url | |||||
| value: $value | |||||
| '''; | |||||
| } | |||||
| } | } | ||||
| @@ -72,6 +72,9 @@ void main() { | |||||
| expect(feed.items.first.source.url, "https://foo.bar.news/1?source"); | expect(feed.items.first.source.url, "https://foo.bar.news/1?source"); | ||||
| expect(feed.items.first.source.value, "Foo Bar"); | expect(feed.items.first.source.value, "Foo Bar"); | ||||
| expect(feed.items.first.comments, "https://foo.bar.news/1/comments"); | expect(feed.items.first.comments, "https://foo.bar.news/1/comments"); | ||||
| expect(feed.items.first.enclosure.url, "http://www.scripting.com/mp3s/weatherReportSuite.mp3"); | |||||
| expect(feed.items.first.enclosure.length, 12216320); | |||||
| expect(feed.items.first.enclosure.type, "audio/mpeg"); | |||||
| expect(feed.items.first.content.value, "<img width=\"1000\" height=\"690\" src=\"https://test.com/image_link\"/> Test content<br />"); | expect(feed.items.first.content.value, "<img width=\"1000\" height=\"690\" src=\"https://test.com/image_link\"/> Test content<br />"); | ||||
| expect(feed.items.first.content.images.first, "https://test.com/image_link"); | expect(feed.items.first.content.images.first, "https://test.com/image_link"); | ||||
| @@ -47,6 +47,7 @@ | |||||
| <source url="https://foo.bar.news/1?source">Foo Bar</source> | <source url="https://foo.bar.news/1?source">Foo Bar</source> | ||||
| <comments>https://foo.bar.news/1/comments</comments> | <comments>https://foo.bar.news/1/comments</comments> | ||||
| <content:encoded><![CDATA[<img width="1000" height="690" src="https://test.com/image_link"/> Test content<br />]]></content:encoded> | <content:encoded><![CDATA[<img width="1000" height="690" src="https://test.com/image_link"/> Test content<br />]]></content:encoded> | ||||
| <enclosure url="http://www.scripting.com/mp3s/weatherReportSuite.mp3" length="12216320" type="audio/mpeg" /> | |||||
| </item> | </item> | ||||
| <item> | <item> | ||||
| <title>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC</title> | <title>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC</title> | ||||