| @@ -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_content.dart'; | |||
| import 'package:webfeed/domain/rss_source.dart'; | |||
| @@ -16,11 +17,12 @@ class RssItem { | |||
| final String comments; | |||
| final RssSource source; | |||
| final RssContent content; | |||
| final Media media; | |||
| RssItem( | |||
| RssItem({ | |||
| this.title, | |||
| this.description, | |||
| this.link, { | |||
| this.link, | |||
| this.categories, | |||
| this.guid, | |||
| this.pubDate, | |||
| @@ -28,10 +30,11 @@ class RssItem { | |||
| this.comments, | |||
| this.source, | |||
| this.content, | |||
| this.media, | |||
| }); | |||
| 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 link = xmlGetString(element, "link", strict: false); | |||
| @@ -56,9 +59,9 @@ class RssItem { | |||
| } on StateError {} | |||
| return new RssItem( | |||
| title, | |||
| description, | |||
| link, | |||
| title: title, | |||
| description: description, | |||
| link: link, | |||
| categories: categories, | |||
| guid: guid, | |||
| pubDate: pubDate, | |||
| @@ -66,6 +69,7 @@ class RssItem { | |||
| comments: comments, | |||
| source: source, | |||
| 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.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> | |||