| @@ -1,23 +1,18 @@ | |||
| import 'package:xml/xml.dart'; | |||
| class RssCategory { | |||
| String domain; | |||
| String value; | |||
| final String domain; | |||
| final String 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); | |||
| } | |||
| @override | |||
| String toString() { | |||
| return ''' | |||
| domain: $domain | |||
| value: $value | |||
| '''; | |||
| } | |||
| } | |||
| @@ -16,8 +16,11 @@ class RssContent { | |||
| 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>[]; | |||
| _imagesRegExp.allMatches(content).forEach((match) { | |||
| 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/rss_category.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/util/helpers.dart'; | |||
| import 'package:xml/xml.dart'; | |||
| import 'package:webfeed/util/helpers.dart'; | |||
| class RssItem { | |||
| final String title; | |||
| @@ -18,6 +20,7 @@ class RssItem { | |||
| final RssSource source; | |||
| final RssContent content; | |||
| final Media media; | |||
| final RssEnclosure enclosure; | |||
| RssItem({ | |||
| this.title, | |||
| @@ -31,45 +34,25 @@ class RssItem { | |||
| this.source, | |||
| this.content, | |||
| this.media, | |||
| this.enclosure, | |||
| }); | |||
| 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( | |||
| 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), | |||
| enclosure: RssEnclosure.parse(findElementOrNull(element, "enclosure")), | |||
| ); | |||
| } | |||
| @@ -6,18 +6,13 @@ class RssSource { | |||
| 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); | |||
| } | |||
| @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.value, "Foo Bar"); | |||
| 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.images.first, "https://test.com/image_link"); | |||
| @@ -47,6 +47,7 @@ | |||
| <source url="https://foo.bar.news/1?source">Foo Bar</source> | |||
| <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> | |||
| <enclosure url="http://www.scripting.com/mp3s/weatherReportSuite.mp3" length="12216320" type="audio/mpeg" /> | |||
| </item> | |||
| <item> | |||
| <title>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC</title> | |||