| @@ -0,0 +1,56 @@ | |||||
| import 'package:xml/xml.dart'; | |||||
| class Content { | |||||
| final String url; | |||||
| final String type; | |||||
| final int fileSize; | |||||
| final String medium; | |||||
| final bool isDefault; | |||||
| final String expression; | |||||
| final int bitrate; | |||||
| final double framerate; | |||||
| final double samplingrate; | |||||
| final int channels; | |||||
| final int duration; | |||||
| final int height; | |||||
| final int width; | |||||
| final String lang; | |||||
| Content({ | |||||
| this.url, | |||||
| this.type, | |||||
| this.fileSize, | |||||
| this.medium, | |||||
| this.isDefault, | |||||
| this.expression, | |||||
| this.bitrate, | |||||
| this.framerate, | |||||
| this.samplingrate, | |||||
| this.channels, | |||||
| this.duration, | |||||
| this.height, | |||||
| this.width, | |||||
| this.lang, | |||||
| }); | |||||
| factory Content.parse(XmlElement element) { | |||||
| return new Content( | |||||
| url: element.getAttribute("url"), | |||||
| type: element.getAttribute("type"), | |||||
| fileSize: int.tryParse(element.getAttribute("fileSize") ?? "0"), | |||||
| medium: element.getAttribute("medium"), | |||||
| isDefault: element.getAttribute("isDefault") == "true", | |||||
| expression: element.getAttribute("expression"), | |||||
| bitrate: int.tryParse(element.getAttribute("bitrate") ?? "0"), | |||||
| framerate: double.tryParse(element.getAttribute("framerate") ?? "0"), | |||||
| samplingrate: double.tryParse( | |||||
| element.getAttribute("samplingrate") ?? "0", | |||||
| ), | |||||
| channels: int.tryParse(element.getAttribute("channels") ?? "0"), | |||||
| duration: int.tryParse(element.getAttribute("duration") ?? "0"), | |||||
| height: int.tryParse(element.getAttribute("height") ?? "0"), | |||||
| width: int.tryParse(element.getAttribute("width") ?? "0"), | |||||
| lang: element.getAttribute("lang"), | |||||
| ); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,17 @@ | |||||
| import 'package:webfeed/domain/media/content.dart'; | |||||
| import 'package:xml/xml.dart'; | |||||
| class Media { | |||||
| final List<Content> contents; | |||||
| Media({this.contents}); | |||||
| factory Media.parse(XmlElement element) { | |||||
| var contents = element.findAllElements("media:content").map((e) { | |||||
| return new Content.parse(e); | |||||
| }).toList(); | |||||
| return new Media( | |||||
| contents: contents, | |||||
| ); | |||||
| } | |||||
| } | |||||
| @@ -1,3 +1,4 @@ | |||||
| 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_source.dart'; | import 'package:webfeed/domain/rss_source.dart'; | ||||
| @@ -16,11 +17,12 @@ class RssItem { | |||||
| final String comments; | final String comments; | ||||
| final RssSource source; | final RssSource source; | ||||
| final RssContent content; | final RssContent content; | ||||
| final Media media; | |||||
| RssItem( | |||||
| RssItem({ | |||||
| this.title, | this.title, | ||||
| this.description, | this.description, | ||||
| this.link, { | |||||
| this.link, | |||||
| this.categories, | this.categories, | ||||
| this.guid, | this.guid, | ||||
| this.pubDate, | this.pubDate, | ||||
| @@ -28,10 +30,11 @@ class RssItem { | |||||
| this.comments, | this.comments, | ||||
| this.source, | this.source, | ||||
| this.content, | this.content, | ||||
| this.media, | |||||
| }); | }); | ||||
| factory RssItem.parse(XmlElement element) { | factory RssItem.parse(XmlElement element) { | ||||
| var title = xmlGetString(element, "title"); | |||||
| var title = xmlGetString(element, "title", strict: false); | |||||
| var description = xmlGetString(element, "description", strict: false); | var description = xmlGetString(element, "description", strict: false); | ||||
| var link = xmlGetString(element, "link", strict: false); | var link = xmlGetString(element, "link", strict: false); | ||||
| @@ -56,9 +59,9 @@ class RssItem { | |||||
| } on StateError {} | } on StateError {} | ||||
| return new RssItem( | return new RssItem( | ||||
| title, | |||||
| description, | |||||
| link, | |||||
| title: title, | |||||
| description: description, | |||||
| link: link, | |||||
| categories: categories, | categories: categories, | ||||
| guid: guid, | guid: guid, | ||||
| pubDate: pubDate, | pubDate: pubDate, | ||||
| @@ -66,6 +69,7 @@ class RssItem { | |||||
| comments: comments, | comments: comments, | ||||
| source: source, | source: source, | ||||
| content: content, | content: content, | ||||
| media: Media.parse(element), | |||||
| ); | ); | ||||
| } | } | ||||
| @@ -76,4 +76,31 @@ void main() { | |||||
| 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"); | ||||
| }); | }); | ||||
| test("parsing RSS-Media.xml", (){ | |||||
| var xmlString = new File("test/xml/RSS-Media.xml").readAsStringSync(); | |||||
| var feed = new RssFeed.parse(xmlString); | |||||
| expect(feed.title, "Song Site"); | |||||
| expect(feed.description, "Media RSS example with new fields added in v1.5.0"); | |||||
| expect(feed.items.length, 1); | |||||
| var item = feed.items.first; | |||||
| expect(item.title, null); | |||||
| expect(item.link, "http://www.foo.com"); | |||||
| expect(item.pubDate, "Mon, 27 Aug 2001 16:08:56 PST"); | |||||
| expect(item.media.contents.length, 2); | |||||
| var mediaContent = item.media.contents.first; | |||||
| expect(mediaContent.url, "http://www.foo.com/video.mov"); | |||||
| expect(mediaContent.type, "video/quicktime"); | |||||
| expect(mediaContent.fileSize, 2000); | |||||
| expect(mediaContent.medium, "video"); | |||||
| expect(mediaContent.isDefault, true); | |||||
| expect(mediaContent.expression, "full"); | |||||
| expect(mediaContent.bitrate, 128); | |||||
| expect(mediaContent.framerate, 25); | |||||
| expect(mediaContent.samplingrate, 44.1); | |||||
| expect(mediaContent.channels, 2); | |||||
| }); | |||||
| } | } | ||||
| @@ -0,0 +1,62 @@ | |||||
| <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" | |||||
| xmlns:georss="http://www.georss.org/georss" | |||||
| xmlns:gml="http://www.opengis.net/gml"> | |||||
| <channel> | |||||
| <title>Song Site</title> | |||||
| <description>Media RSS example with new fields added in v1.5.0</description> | |||||
| <item> | |||||
| <link>http://www.foo.com</link> | |||||
| <pubDate>Mon, 27 Aug 2001 16:08:56 PST</pubDate> | |||||
| <media:content url="http://www.foo.com/video.mov" fileSize="2000" medium="video" isDefault="true" expression="full" bitrate="128" framerate="25" samplingrate="44.1" channels="2" type="video/quicktime" /> | |||||
| <media:content url="http://www.foo.com/video2.mov" fileSize="2000" bitrate="128" type="video/quicktime" expression="full" /> | |||||
| <media:community> | |||||
| <media:starRating average="3.5" count="20" min="1" max="10" /> | |||||
| <media:statistics views="5" favorites="5" /> | |||||
| <media:tags>news: 5, abc:3</media:tags> | |||||
| </media:community> | |||||
| <media:comments> | |||||
| <media:comment>comment1</media:comment> | |||||
| <media:comment>comment2</media:comment> | |||||
| </media:comments> | |||||
| <media:embed url="http://www.foo.com/player.swf" width="512" height="323"> | |||||
| <media:param name="type">application/x-shockwave-flash</media:param> | |||||
| <media:param name="width">512</media:param> | |||||
| <media:param name="height">323</media:param> | |||||
| <media:param name="allowFullScreen">true</media:param> | |||||
| <media:param name="flashVars"> | |||||
| id=12345&vid=678912i&lang=en-us&intl=us&thumbUrl=http://www.foo.com/thumbnail.jpg | |||||
| </media:param> | |||||
| </media:embed> | |||||
| <media:responses> | |||||
| <media:response>http://www.response1.com</media:response> | |||||
| <media:response>http://www.response2.com</media:response> | |||||
| </media:responses> | |||||
| <media:backLinks> | |||||
| <media:backLink>http://www.backlink1.com</media:backLink> | |||||
| <media:backLink>http://www.backlink2.com</media:backLink> | |||||
| </media:backLinks> | |||||
| <media:status state="active" /> | |||||
| <media:price type="rent" price="19.99" currency="EUR" /> | |||||
| <media:license type="text/html" href="http://www.licensehost.com/license"> Sample license for a video</media:license> | |||||
| <media:subTitle type="application/smil" lang="en-us" href="http://www.foo.org/subtitle.smil" /> | |||||
| <media:peerLink type="application/x-bittorrent " href="http://www.foo.org/sampleFile.torrent" /> | |||||
| <media:location description="My house" start="00:01" end="01:00"> | |||||
| <georss:where> | |||||
| <gml:Point> | |||||
| <gml:pos>35.669998 139.770004</gml:pos> | |||||
| </gml:Point> | |||||
| </georss:where> | |||||
| </media:location> | |||||
| <media:restriction type="sharing" relationship="deny" /> | |||||
| <media:scenes> | |||||
| <media:scene> | |||||
| <sceneTitle>sceneTitle1</sceneTitle> | |||||
| <sceneDescription>sceneDesc1</sceneDescription> | |||||
| <sceneStartTime>00:15</sceneStartTime> | |||||
| <sceneEndTime>00:45</sceneEndTime> | |||||
| </media:scene> | |||||
| </media:scenes> | |||||
| </item> | |||||
| </channel> | |||||
| </rss> | |||||