| @@ -0,0 +1,16 @@ | |||||
| import 'package:xml/xml.dart'; | |||||
| class AtomCategory { | |||||
| String term; | |||||
| String scheme; | |||||
| String label; | |||||
| AtomCategory(this.term, this.scheme, this.label); | |||||
| factory AtomCategory.parse(XmlElement element) { | |||||
| var term = element.getAttribute("term"); | |||||
| var scheme = element.getAttribute("scheme"); | |||||
| var label = element.getAttribute("label"); | |||||
| return new AtomCategory(term, scheme, label); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,81 @@ | |||||
| import 'package:webfeed/domain/atom_category.dart'; | |||||
| import 'package:webfeed/domain/atom_generator.dart'; | |||||
| import 'package:webfeed/domain/atom_item.dart'; | |||||
| import 'package:webfeed/domain/atom_link.dart'; | |||||
| import 'package:webfeed/domain/atom_person.dart'; | |||||
| import 'package:xml/xml.dart'; | |||||
| import 'package:webfeed/util/helpers.dart'; | |||||
| class AtomFeed { | |||||
| String id; | |||||
| String title; | |||||
| String updated; | |||||
| List<AtomItem> items; | |||||
| List<AtomLink> links; | |||||
| List<AtomPerson> authors; | |||||
| List<AtomPerson> contributors; | |||||
| List<AtomCategory> categories; | |||||
| AtomGenerator generator; | |||||
| String icon; | |||||
| String logo; | |||||
| String rights; | |||||
| String subtitle; | |||||
| AtomFeed(this.id, this.title, this.updated, this.items, | |||||
| {this.links, this.authors, this.contributors, this.categories, this.generator, this.icon, this.logo, this.rights, this.subtitle}); | |||||
| factory AtomFeed.parse(String xmlString) { | |||||
| var document = parse(xmlString); | |||||
| XmlElement feedElement; | |||||
| try { | |||||
| feedElement = document.findElements("feed").first; | |||||
| } on StateError { | |||||
| throw new ArgumentError("feed not found"); | |||||
| } | |||||
| var id = xmlGetString(feedElement, "id"); | |||||
| var title = xmlGetString(feedElement, "title"); | |||||
| var updated = xmlGetString(feedElement, "updated"); | |||||
| var items = feedElement.findElements("entry").map((element) { | |||||
| return new AtomItem.parse(element); | |||||
| }).toList(); | |||||
| var links = feedElement.findElements("link").map((element) { | |||||
| return new AtomLink.parse(element); | |||||
| }).toList(); | |||||
| var authors = feedElement.findElements("author").map((element) { | |||||
| return new AtomPerson.parse(element); | |||||
| }).toList(); | |||||
| var contributors = feedElement.findElements("contributor").map((element) { | |||||
| return new AtomPerson.parse(element); | |||||
| }).toList(); | |||||
| var categories = feedElement.findElements("category").map((element) { | |||||
| return new AtomCategory.parse(element); | |||||
| }).toList(); | |||||
| AtomGenerator generator; | |||||
| try { | |||||
| generator = new AtomGenerator.parse(feedElement.findElements("generator").first); | |||||
| } on StateError {} | |||||
| var icon = xmlGetString(feedElement, "icon", strict: false); | |||||
| var logo = xmlGetString(feedElement, "logo", strict: false); | |||||
| var rights = xmlGetString(feedElement, "rights", strict: false); | |||||
| var subtitle = xmlGetString(feedElement, "subtitle", strict: false); | |||||
| return new AtomFeed(id, title, updated, items, | |||||
| links: links, | |||||
| authors: authors, | |||||
| contributors: contributors, | |||||
| categories: categories, | |||||
| generator: generator, | |||||
| icon: icon, | |||||
| logo: logo, | |||||
| rights: rights, | |||||
| subtitle: subtitle); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,16 @@ | |||||
| import 'package:xml/xml.dart'; | |||||
| class AtomGenerator { | |||||
| String uri; | |||||
| String version; | |||||
| String value; | |||||
| AtomGenerator(this.uri, this.version, this.value); | |||||
| factory AtomGenerator.parse(XmlElement element) { | |||||
| var uri = element.getAttribute("uri"); | |||||
| var version = element.getAttribute("version"); | |||||
| var value = element.text; | |||||
| return new AtomGenerator(uri, version, value); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,76 @@ | |||||
| import 'package:webfeed/domain/atom_category.dart'; | |||||
| import 'package:webfeed/domain/atom_link.dart'; | |||||
| import 'package:webfeed/domain/atom_person.dart'; | |||||
| import 'package:webfeed/domain/atom_source.dart'; | |||||
| import 'package:xml/xml.dart'; | |||||
| import 'package:webfeed/util/helpers.dart'; | |||||
| class AtomItem { | |||||
| String id; | |||||
| String title; | |||||
| String updated; | |||||
| List<AtomPerson> authors; | |||||
| List<AtomLink> links; | |||||
| List<AtomCategory> categories; | |||||
| List<AtomPerson> contributors; | |||||
| AtomSource source; | |||||
| String published; | |||||
| String content; | |||||
| String summary; | |||||
| String rights; | |||||
| AtomItem(this.id, this.title, this.updated, | |||||
| {this.authors, | |||||
| this.links, | |||||
| this.categories, | |||||
| this.contributors, | |||||
| this.source, | |||||
| this.published, | |||||
| this.content, | |||||
| this.summary, | |||||
| this.rights}); | |||||
| factory AtomItem.parse(XmlElement element) { | |||||
| var id = xmlGetString(element, "id"); | |||||
| var title = xmlGetString(element, "title"); | |||||
| var updated = xmlGetString(element, "updated"); | |||||
| var authors = element.findElements("author").map((element) { | |||||
| return new AtomPerson.parse(element); | |||||
| }).toList(); | |||||
| var links = element.findElements("link").map((element) { | |||||
| return new AtomLink.parse(element); | |||||
| }).toList(); | |||||
| var categories = element.findElements("category").map((element) { | |||||
| return new AtomCategory.parse(element); | |||||
| }).toList(); | |||||
| var contributors = element.findElements("contributor").map((element) { | |||||
| return new AtomPerson.parse(element); | |||||
| }).toList(); | |||||
| AtomSource source; | |||||
| try { | |||||
| source = new AtomSource.parse(element.findElements("source").first); | |||||
| } on StateError {} | |||||
| var published = xmlGetString(element, "published", strict: false); | |||||
| var content = xmlGetString(element, "content", strict: false); | |||||
| var summary = xmlGetString(element, "summary", strict: false); | |||||
| var rights = xmlGetString(element, "rights", strict: false); | |||||
| return new AtomItem(id, title, updated, | |||||
| authors: authors, | |||||
| links: links, | |||||
| categories: categories, | |||||
| contributors: contributors, | |||||
| source: source, | |||||
| published: published, | |||||
| content: content, | |||||
| summary: summary, | |||||
| rights: rights); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,25 @@ | |||||
| import 'package:xml/xml.dart'; | |||||
| class AtomLink { | |||||
| String href; | |||||
| String rel; | |||||
| String type; | |||||
| String hreflang; | |||||
| String title; | |||||
| int length; | |||||
| AtomLink(this.href, this.rel, this.type, this.hreflang, this.title, this.length); | |||||
| factory AtomLink.parse(XmlElement element) { | |||||
| var href = element.getAttribute("href"); | |||||
| var rel = element.getAttribute("rel"); | |||||
| var type = element.getAttribute("type"); | |||||
| var title = element.getAttribute("title"); | |||||
| var hreflang = element.getAttribute("hreflang"); | |||||
| var length = 0; | |||||
| if (element.getAttribute("length") != null) { | |||||
| length = int.parse(element.getAttribute("length")); | |||||
| } | |||||
| return new AtomLink(href, rel, type, hreflang, title, length); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,17 @@ | |||||
| import 'package:xml/xml.dart'; | |||||
| import 'package:webfeed/util/helpers.dart'; | |||||
| class AtomPerson { | |||||
| String name; | |||||
| String uri; | |||||
| String email; | |||||
| AtomPerson(this.name, this.uri, this.email); | |||||
| factory AtomPerson.parse(XmlElement element) { | |||||
| var name = xmlGetString(element, "name"); | |||||
| var uri = xmlGetString(element, "uri", strict: false); | |||||
| var email = xmlGetString(element, "email", strict: false); | |||||
| return new AtomPerson(name, uri, email); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,18 @@ | |||||
| import 'package:webfeed/util/helpers.dart'; | |||||
| import 'package:xml/xml.dart'; | |||||
| class AtomSource { | |||||
| String id; | |||||
| String title; | |||||
| String updated; | |||||
| AtomSource(this.id, this.title, this.updated); | |||||
| factory AtomSource.parse(XmlElement element) { | |||||
| var id = xmlGetString(element, "id", strict: false); | |||||
| var title = xmlGetString(element, "title", strict: false); | |||||
| var updated = xmlGetString(element, "updated", strict: false); | |||||
| return new AtomSource(id, title, updated); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,90 @@ | |||||
| import 'dart:io'; | |||||
| import 'dart:core'; | |||||
| import 'package:test/test.dart'; | |||||
| import 'package:webfeed/domain/atom_feed.dart'; | |||||
| void main() { | |||||
| test("parsing Invalid.xml", () { | |||||
| var xmlString = new File("test/xml/Invalid.xml").readAsStringSync(); | |||||
| try { | |||||
| new AtomFeed.parse(xmlString); | |||||
| fail("Should throw Argument Error"); | |||||
| } on ArgumentError {} | |||||
| }); | |||||
| test("parsing Atom.xml", () { | |||||
| var xmlString = new File("test/xml/Atom.xml").readAsStringSync(); | |||||
| var feed = new AtomFeed.parse(xmlString); | |||||
| expect(feed.id, "foo-bar-id"); | |||||
| expect(feed.title, "Foo bar news"); | |||||
| expect(feed.updated, "2018-04-06T13:02:46Z"); | |||||
| expect(feed.links.length, 2); | |||||
| expect(feed.links.first.rel, "foo"); | |||||
| expect(feed.links.first.type, "text/html"); | |||||
| expect(feed.links.first.hreflang, "en"); | |||||
| expect(feed.links.first.href, "http://foo.bar.news/"); | |||||
| expect(feed.links.first.title, "Foo bar news html"); | |||||
| expect(feed.links.first.length, 1000); | |||||
| expect(feed.authors.length, 2); | |||||
| expect(feed.authors.first.name, "Alice"); | |||||
| expect(feed.authors.first.uri, "http://foo.bar.news/people/alice"); | |||||
| expect(feed.authors.first.email, "alice@foo.bar.news"); | |||||
| expect(feed.contributors.length, 2); | |||||
| expect(feed.contributors.first.name, "Charlie"); | |||||
| expect(feed.contributors.first.uri, "http://foo.bar.news/people/charlie"); | |||||
| expect(feed.contributors.first.email, "charlie@foo.bar.news"); | |||||
| expect(feed.categories.length, 2); | |||||
| expect(feed.categories.first.term, "foo category"); | |||||
| expect(feed.categories.first.scheme, "this-is-foo-scheme"); | |||||
| expect(feed.categories.first.label, "this is foo label"); | |||||
| expect(feed.generator.uri, "http://foo.bar.news/generator"); | |||||
| expect(feed.generator.version, "1.0"); | |||||
| expect(feed.generator.value, "Foo bar generator"); | |||||
| expect(feed.icon, "http://foo.bar.news/icon.png"); | |||||
| expect(feed.logo, "http://foo.bar.news/logo.png"); | |||||
| expect(feed.subtitle, "This is subtitle"); | |||||
| expect(feed.items.length, 2); | |||||
| var item = feed.items.first; | |||||
| expect(item.id, "foo-bar-entry-id-1"); | |||||
| expect(item.title, "Foo bar item 1"); | |||||
| expect(item.updated, "2018-04-06T13:02:47Z"); | |||||
| expect(item.authors.length, 2); | |||||
| expect(item.authors.first.name, "Ellie"); | |||||
| expect(item.authors.first.uri, "http://foo.bar.news/people/ellie"); | |||||
| expect(item.authors.first.email, "ellie@foo.bar.news"); | |||||
| expect(item.links.length, 2); | |||||
| expect(item.links.first.rel, "foo entry"); | |||||
| expect(item.links.first.type, "text/html"); | |||||
| expect(item.links.first.hreflang, "en"); | |||||
| expect(item.links.first.href, "http://foo.bar.news/entry"); | |||||
| expect(item.links.first.title, "Foo bar news html"); | |||||
| expect(item.links.first.length, 1000); | |||||
| expect(item.categories.length, 2); | |||||
| expect(item.categories.first.term, "foo entry category"); | |||||
| expect(item.categories.first.scheme, "this-is-foo-entry-scheme"); | |||||
| expect(item.categories.first.label, "this is foo entry label"); | |||||
| expect(item.contributors.length, 2); | |||||
| expect(item.contributors.first.name, "Gin"); | |||||
| expect(item.contributors.first.uri, "http://foo.bar.news/people/gin"); | |||||
| expect(item.contributors.first.email, "gin@foo.bar.news"); | |||||
| expect(item.published, "2018-04-06T13:02:49Z"); | |||||
| expect(item.summary, "This is summary 1"); | |||||
| expect(item.content, "This is content 1"); | |||||
| expect(item.rights, "This is rights 1"); | |||||
| }); | |||||
| } | |||||
| @@ -0,0 +1,117 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <feed xmlns="http://www.w3.org/2005/Atom"> | |||||
| <id>foo-bar-id</id> | |||||
| <title type="text">Foo bar news</title> | |||||
| <updated>2018-04-06T13:02:46Z</updated> | |||||
| <link rel="foo" type="text/html" hreflang="en" href="http://foo.bar.news/" title="Foo bar news html" length="1000"/> | |||||
| <link rel="bar" type="application/atom+xml" hreflang="pt" href="http://foo.bar.news/feed.atom" | |||||
| title="Foo bar news atom" length="100"/> | |||||
| <author> | |||||
| <name>Alice</name> | |||||
| <uri>http://foo.bar.news/people/alice</uri> | |||||
| <email>alice@foo.bar.news</email> | |||||
| </author> | |||||
| <author> | |||||
| <name>Bob</name> | |||||
| <uri>http://foo.bar.news/people/bob</uri> | |||||
| <email>bob@foo.bar.news</email> | |||||
| </author> | |||||
| <contributor> | |||||
| <name>Charlie</name> | |||||
| <uri>http://foo.bar.news/people/charlie</uri> | |||||
| <email>charlie@foo.bar.news</email> | |||||
| </contributor> | |||||
| <contributor> | |||||
| <name>David</name> | |||||
| <uri>http://foo.bar.news/people/david</uri> | |||||
| <email>david@foo.bar.news</email> | |||||
| </contributor> | |||||
| <category term="foo category" scheme="this-is-foo-scheme" label="this is foo label"/> | |||||
| <category term="bar category" scheme="this-is-bar-scheme" label="this is bar label"/> | |||||
| <generator uri="http://foo.bar.news/generator" version="1.0">Foo bar generator</generator> | |||||
| <icon>http://foo.bar.news/icon.png</icon> | |||||
| <logo>http://foo.bar.news/logo.png</logo> | |||||
| <subtitle>This is subtitle</subtitle> | |||||
| <entry> | |||||
| <id>foo-bar-entry-id-1</id> | |||||
| <title>Foo bar item 1</title> | |||||
| <updated>2018-04-06T13:02:47Z</updated> | |||||
| <author> | |||||
| <name>Ellie</name> | |||||
| <uri>http://foo.bar.news/people/ellie</uri> | |||||
| <email>ellie@foo.bar.news</email> | |||||
| </author> | |||||
| <author> | |||||
| <name>Franz</name> | |||||
| <uri>http://foo.bar.news/people/franz</uri> | |||||
| <email>franz@foo.bar.news</email> | |||||
| </author> | |||||
| <link rel="foo entry" type="text/html" hreflang="en" href="http://foo.bar.news/entry" title="Foo bar news html" | |||||
| length="1000"/> | |||||
| <link rel="bar entry" type="application/atom+xml" hreflang="pt" href="http://foo.bar.news/entry/feed.atom" | |||||
| title="Foo bar entry atom" length="100"/> | |||||
| <category term="foo entry category" scheme="this-is-foo-entry-scheme" label="this is foo entry label"/> | |||||
| <category term="bar entry category" scheme="this-is-bar-entry-scheme" label="this is bar entry label"/> | |||||
| <contributor> | |||||
| <name>Gin</name> | |||||
| <uri>http://foo.bar.news/people/gin</uri> | |||||
| <email>gin@foo.bar.news</email> | |||||
| </contributor> | |||||
| <contributor> | |||||
| <name>Hanz</name> | |||||
| <uri>http://foo.bar.news/people/hanz</uri> | |||||
| <email>hanz@foo.bar.news</email> | |||||
| </contributor> | |||||
| <source> | |||||
| <id>http://foo.bar.news/source</id> | |||||
| <title>Foo bar source</title> | |||||
| <updated>2018-04-06T13:02:48Z</updated> | |||||
| </source> | |||||
| <published>2018-04-06T13:02:49Z</published> | |||||
| <summary type="text">This is summary 1</summary> | |||||
| <content>This is content 1</content> | |||||
| <rights>This is rights 1</rights> | |||||
| </entry> | |||||
| <entry> | |||||
| <id>foo-bar-entry-id-2</id> | |||||
| <title>Foo bar item 2</title> | |||||
| <updated>2018-04-06T13:02:50Z</updated> | |||||
| <author> | |||||
| <name>Iris</name> | |||||
| <uri>http://foo.bar.news/people/iris</uri> | |||||
| <email>iris@foo.bar.news</email> | |||||
| </author> | |||||
| <author> | |||||
| <name>Jhon</name> | |||||
| <uri>http://foo.bar.news/people/jhon</uri> | |||||
| <email>jhon@foo.bar.news</email> | |||||
| </author> | |||||
| <link rel="foo entry" type="text/html" hreflang="en" href="http://foo.bar.news/entry" title="Foo bar news html" | |||||
| length="1000"/> | |||||
| <link rel="bar entry" type="application/atom+xml" hreflang="pt" href="http://foo.bar.news/entry/feed.atom" | |||||
| title="Foo bar entry atom" length="100"/> | |||||
| <category term="foo entry category"/> | |||||
| <category term="bar entry category"/> | |||||
| <contributor> | |||||
| <name>Kevin</name> | |||||
| <uri>http://foo.bar.news/people/kevin</uri> | |||||
| <email>kevin@foo.bar.news</email> | |||||
| </contributor> | |||||
| <contributor> | |||||
| <name>Lucy</name> | |||||
| <uri>http://foo.bar.news/people/lucy</uri> | |||||
| <email>lucy@foo.bar.news</email> | |||||
| </contributor> | |||||
| <source> | |||||
| <id>http://foo.bar.news/source</id> | |||||
| <title>Foo bar source</title> | |||||
| <updated>2018-04-06T13:02:51Z</updated> | |||||
| </source> | |||||
| <published>2018-04-06T13:02:52Z</published> | |||||
| <summary type="text">This is summary 2</summary> | |||||
| <content>This is content 2</content> | |||||
| <rights>This is rights 2</rights> | |||||
| </entry> | |||||
| </feed> | |||||