| @@ -49,9 +49,9 @@ class AtomFeed { | |||
| } | |||
| return AtomFeed( | |||
| id: findElementOrNull(feedElement, 'id')?.text, | |||
| title: findElementOrNull(feedElement, 'title')?.text, | |||
| updated: parseDateTime(findElementOrNull(feedElement, 'updated')?.text), | |||
| id: findFirstElement(feedElement, 'id')?.text, | |||
| title: findFirstElement(feedElement, 'title')?.text, | |||
| updated: parseDateTime(findFirstElement(feedElement, 'updated')?.text), | |||
| items: feedElement.findElements('entry').map((element) { | |||
| return AtomItem.parse(element); | |||
| }).toList(), | |||
| @@ -68,11 +68,11 @@ class AtomFeed { | |||
| return AtomCategory.parse(element); | |||
| }).toList(), | |||
| generator: | |||
| AtomGenerator.parse(findElementOrNull(feedElement, 'generator')), | |||
| icon: findElementOrNull(feedElement, 'icon')?.text, | |||
| logo: findElementOrNull(feedElement, 'logo')?.text, | |||
| rights: findElementOrNull(feedElement, 'rights')?.text, | |||
| subtitle: findElementOrNull(feedElement, 'subtitle')?.text, | |||
| AtomGenerator.parse(findFirstElement(feedElement, 'generator')), | |||
| icon: findFirstElement(feedElement, 'icon')?.text, | |||
| logo: findFirstElement(feedElement, 'logo')?.text, | |||
| rights: findFirstElement(feedElement, 'rights')?.text, | |||
| subtitle: findFirstElement(feedElement, 'subtitle')?.text, | |||
| ); | |||
| } | |||
| } | |||
| @@ -41,26 +41,28 @@ class AtomItem { | |||
| factory AtomItem.parse(XmlElement element) { | |||
| return AtomItem( | |||
| id: findElementOrNull(element, 'id')?.text, | |||
| title: findElementOrNull(element, 'title')?.text, | |||
| updated: parseDateTime(findElementOrNull(element, 'updated')?.text), | |||
| authors: element.findElements('author').map((element) { | |||
| return AtomPerson.parse(element); | |||
| }).toList(), | |||
| links: element.findElements('link').map((element) { | |||
| return AtomLink.parse(element); | |||
| }).toList(), | |||
| categories: element.findElements('category').map((element) { | |||
| return AtomCategory.parse(element); | |||
| }).toList(), | |||
| contributors: element.findElements('contributor').map((element) { | |||
| return AtomPerson.parse(element); | |||
| }).toList(), | |||
| source: AtomSource.parse(findElementOrNull(element, 'source')), | |||
| published: findElementOrNull(element, 'published')?.text, | |||
| content: findElementOrNull(element, 'content')?.text, | |||
| summary: findElementOrNull(element, 'summary')?.text, | |||
| rights: findElementOrNull(element, 'rights')?.text, | |||
| id: findFirstElement(element, 'id')?.text, | |||
| title: findFirstElement(element, 'title')?.text, | |||
| updated: parseDateTime(findFirstElement(element, 'updated')?.text), | |||
| authors: element | |||
| .findElements('author') | |||
| .map((e) => AtomPerson.parse(e)) | |||
| .toList(), | |||
| links: | |||
| element.findElements('link').map((e) => AtomLink.parse(e)).toList(), | |||
| categories: element | |||
| .findElements('category') | |||
| .map((e) => AtomCategory.parse(e)) | |||
| .toList(), | |||
| contributors: element | |||
| .findElements('contributor') | |||
| .map((e) => AtomPerson.parse(e)) | |||
| .toList(), | |||
| source: AtomSource.parse(findFirstElement(element, 'source')), | |||
| published: findFirstElement(element, 'published')?.text, | |||
| content: findFirstElement(element, 'content')?.text, | |||
| summary: findFirstElement(element, 'summary')?.text, | |||
| rights: findFirstElement(element, 'rights')?.text, | |||
| media: Media.parse(element), | |||
| ); | |||
| } | |||
| @@ -6,12 +6,13 @@ class AtomPerson { | |||
| final String uri; | |||
| final String email; | |||
| AtomPerson(this.name, this.uri, this.email); | |||
| AtomPerson({this.name, this.uri, this.email}); | |||
| factory AtomPerson.parse(XmlElement element) { | |||
| var name = findElementOrNull(element, 'name')?.text; | |||
| var uri = findElementOrNull(element, 'uri')?.text; | |||
| var email = findElementOrNull(element, 'email')?.text; | |||
| return AtomPerson(name, uri, email); | |||
| return AtomPerson( | |||
| name: findFirstElement(element, 'name')?.text, | |||
| uri: findFirstElement(element, 'uri')?.text, | |||
| email: findFirstElement(element, 'email')?.text, | |||
| ); | |||
| } | |||
| } | |||
| @@ -6,16 +6,20 @@ class AtomSource { | |||
| final String title; | |||
| final String updated; | |||
| AtomSource(this.id, this.title, this.updated); | |||
| AtomSource({ | |||
| this.id, | |||
| this.title, | |||
| this.updated, | |||
| }); | |||
| factory AtomSource.parse(XmlElement element) { | |||
| if (element == null) { | |||
| return null; | |||
| } | |||
| var id = findElementOrNull(element, 'id')?.text; | |||
| var title = findElementOrNull(element, 'title')?.text; | |||
| var updated = findElementOrNull(element, 'updated')?.text; | |||
| return AtomSource(id, title, updated); | |||
| return AtomSource( | |||
| id: findFirstElement(element, 'id')?.text, | |||
| title: findFirstElement(element, 'title')?.text, | |||
| updated: findFirstElement(element, 'updated')?.text, | |||
| ); | |||
| } | |||
| } | |||
| @@ -46,23 +46,23 @@ class DublinCore { | |||
| return null; | |||
| } | |||
| return DublinCore( | |||
| title: findElementOrNull(element, 'dc:title')?.text, | |||
| description: findElementOrNull(element, 'dc:description')?.text, | |||
| creator: findElementOrNull(element, 'dc:creator')?.text, | |||
| subject: findElementOrNull(element, 'dc:subject')?.text, | |||
| publisher: findElementOrNull(element, 'dc:publisher')?.text, | |||
| contributor: findElementOrNull(element, 'dc:contributor')?.text, | |||
| date: parseDateTime(findElementOrNull(element, 'dc:date')?.text), | |||
| created: parseDateTime(findElementOrNull(element, 'dc:created')?.text), | |||
| modified: parseDateTime(findElementOrNull(element, 'dc:modified')?.text), | |||
| type: findElementOrNull(element, 'dc:type')?.text, | |||
| format: findElementOrNull(element, 'dc:format')?.text, | |||
| identifier: findElementOrNull(element, 'dc:identifier')?.text, | |||
| source: findElementOrNull(element, 'dc:source')?.text, | |||
| language: findElementOrNull(element, 'dc:language')?.text, | |||
| relation: findElementOrNull(element, 'dc:relation')?.text, | |||
| coverage: findElementOrNull(element, 'dc:coverage')?.text, | |||
| rights: findElementOrNull(element, 'dc:rights')?.text, | |||
| title: findFirstElement(element, 'dc:title')?.text, | |||
| description: findFirstElement(element, 'dc:description')?.text, | |||
| creator: findFirstElement(element, 'dc:creator')?.text, | |||
| subject: findFirstElement(element, 'dc:subject')?.text, | |||
| publisher: findFirstElement(element, 'dc:publisher')?.text, | |||
| contributor: findFirstElement(element, 'dc:contributor')?.text, | |||
| date: parseDateTime(findFirstElement(element, 'dc:date')?.text), | |||
| created: parseDateTime(findFirstElement(element, 'dc:created')?.text), | |||
| modified: parseDateTime(findFirstElement(element, 'dc:modified')?.text), | |||
| type: findFirstElement(element, 'dc:type')?.text, | |||
| format: findFirstElement(element, 'dc:format')?.text, | |||
| identifier: findFirstElement(element, 'dc:identifier')?.text, | |||
| source: findFirstElement(element, 'dc:source')?.text, | |||
| language: findFirstElement(element, 'dc:language')?.text, | |||
| relation: findFirstElement(element, 'dc:relation')?.text, | |||
| coverage: findFirstElement(element, 'dc:coverage')?.text, | |||
| rights: findFirstElement(element, 'dc:rights')?.text, | |||
| ); | |||
| } | |||
| } | |||
| @@ -49,36 +49,35 @@ class Itunes { | |||
| if (element == null) { | |||
| return null; | |||
| } | |||
| var episodeStr = findElementOrNull(element, 'itunes:episode')?.text?.trim(); | |||
| var seasonStr = findElementOrNull(element, 'itunes:season')?.text?.trim(); | |||
| var durationStr = | |||
| findElementOrNull(element, 'itunes:duration')?.text?.trim(); | |||
| var episodeStr = findFirstElement(element, 'itunes:episode')?.text; | |||
| var seasonStr = findFirstElement(element, 'itunes:season')?.text; | |||
| var durationStr = findFirstElement(element, 'itunes:duration')?.text; | |||
| return Itunes( | |||
| author: findElementOrNull(element, 'itunes:author')?.text?.trim(), | |||
| summary: findElementOrNull(element, 'itunes:summary')?.text?.trim(), | |||
| author: findFirstElement(element, 'itunes:author')?.text, | |||
| summary: findFirstElement(element, 'itunes:summary')?.text, | |||
| explicit: parseBoolLiteral(element, 'itunes:explicit'), | |||
| title: findElementOrNull(element, 'itunes:title')?.text?.trim(), | |||
| subtitle: findElementOrNull(element, 'itunes:subtitle')?.text?.trim(), | |||
| owner: ItunesOwner.parse(findElementOrNull(element, 'itunes:owner')), | |||
| keywords: findElementOrNull(element, 'itunes:keywords') | |||
| ?.text | |||
| ?.split(',') | |||
| ?.map((keyword) => keyword.trim()) | |||
| ?.toList(), | |||
| image: ItunesImage.parse(findElementOrNull(element, 'itunes:image')), | |||
| categories: findAllDirectElementsOrNull(element, 'itunes:category') | |||
| .map((ele) => ItunesCategory.parse(ele)) | |||
| title: findFirstElement(element, 'itunes:title')?.text, | |||
| subtitle: findFirstElement(element, 'itunes:subtitle')?.text, | |||
| owner: ItunesOwner.parse(findFirstElement(element, 'itunes:owner')), | |||
| keywords: findFirstElement(element, 'itunes:keywords') | |||
| ?.text | |||
| ?.split(',') | |||
| ?.map((keyword) => keyword.trim()) | |||
| ?.toList() ?? | |||
| [], | |||
| image: ItunesImage.parse(findFirstElement(element, 'itunes:image')), | |||
| categories: findElements(element, 'itunes:category') | |||
| .map((e) => ItunesCategory.parse(e)) | |||
| .toList(), | |||
| type: newItunesType(findElementOrNull(element, 'itunes:type')), | |||
| newFeedUrl: | |||
| findElementOrNull(element, 'itunes:new-feed-url')?.text?.trim(), | |||
| type: newItunesType(findFirstElement(element, 'itunes:type')), | |||
| newFeedUrl: findFirstElement(element, 'itunes:new-feed-url')?.text, | |||
| block: parseBoolLiteral(element, 'itunes:block'), | |||
| complete: parseBoolLiteral(element, 'itunes:complete'), | |||
| episode: episodeStr == null ? null : int.parse(episodeStr), | |||
| season: seasonStr == null ? null : int.parse(seasonStr), | |||
| duration: durationStr == null ? null : _parseDuration(durationStr), | |||
| episodeType: newItunesEpisodeType( | |||
| findElementOrNull(element, 'itunes:episodeType')), | |||
| episodeType: | |||
| newItunesEpisodeType(findFirstElement(element, 'itunes:episodeType')), | |||
| ); | |||
| } | |||
| @@ -8,18 +8,13 @@ class ItunesCategory { | |||
| factory ItunesCategory.parse(XmlElement element) { | |||
| if (element == null) return null; | |||
| Iterable<XmlElement> subCategories; | |||
| try { | |||
| subCategories = element.findElements('itunes:category'); | |||
| } on StateError { | |||
| subCategories = null; | |||
| } | |||
| return ItunesCategory( | |||
| category: element.getAttribute('text')?.trim(), | |||
| subCategories: subCategories | |||
| ?.map((ele) => ele.getAttribute('text')?.trim()) | |||
| ?.toList(), | |||
| subCategories: element | |||
| .findElements('itunes:category') | |||
| ?.map((e) => e.getAttribute('text')?.trim()) | |||
| ?.toList() ?? | |||
| [], | |||
| ); | |||
| } | |||
| } | |||
| @@ -10,8 +10,8 @@ class ItunesOwner { | |||
| factory ItunesOwner.parse(XmlElement element) { | |||
| if (element == null) return null; | |||
| return ItunesOwner( | |||
| name: findElementOrNull(element, 'itunes:name')?.text?.trim(), | |||
| email: findElementOrNull(element, 'itunes:email')?.text?.trim(), | |||
| name: findFirstElement(element, 'itunes:name')?.text?.trim(), | |||
| email: findFirstElement(element, 'itunes:email')?.text?.trim(), | |||
| ); | |||
| } | |||
| } | |||
| @@ -21,13 +21,13 @@ class Community { | |||
| } | |||
| return Community( | |||
| starRating: StarRating.parse( | |||
| findElementOrNull(element, 'media:starRating'), | |||
| findFirstElement(element, 'media:starRating'), | |||
| ), | |||
| statistics: Statistics.parse( | |||
| findElementOrNull(element, 'media:statistics'), | |||
| findFirstElement(element, 'media:statistics'), | |||
| ), | |||
| tags: Tags.parse( | |||
| findElementOrNull(element, 'media:tags'), | |||
| findFirstElement(element, 'media:tags'), | |||
| ), | |||
| ); | |||
| } | |||
| @@ -30,10 +30,10 @@ class Group { | |||
| return Credit.parse(e); | |||
| }).toList(), | |||
| category: Category.parse( | |||
| findElementOrNull(element, 'media:category'), | |||
| findFirstElement(element, 'media:category'), | |||
| ), | |||
| rating: Rating.parse( | |||
| findElementOrNull(element, 'media:rating'), | |||
| findFirstElement(element, 'media:rating'), | |||
| ), | |||
| ); | |||
| } | |||
| @@ -80,7 +80,7 @@ class Media { | |||
| factory Media.parse(XmlElement element) { | |||
| return Media( | |||
| group: Group.parse( | |||
| findElementOrNull(element, 'media:group'), | |||
| findFirstElement(element, 'media:group'), | |||
| ), | |||
| contents: element.findElements('media:content').map((e) { | |||
| return Content.parse(e); | |||
| @@ -89,76 +89,76 @@ class Media { | |||
| return Credit.parse(e); | |||
| }).toList(), | |||
| category: Category.parse( | |||
| findElementOrNull(element, 'media:category'), | |||
| findFirstElement(element, 'media:category'), | |||
| ), | |||
| rating: Rating.parse( | |||
| findElementOrNull(element, 'media:rating'), | |||
| findFirstElement(element, 'media:rating'), | |||
| ), | |||
| title: Title.parse( | |||
| findElementOrNull(element, 'media:title'), | |||
| findFirstElement(element, 'media:title'), | |||
| ), | |||
| description: Description.parse( | |||
| findElementOrNull(element, 'media:description'), | |||
| findFirstElement(element, 'media:description'), | |||
| ), | |||
| keywords: findElementOrNull(element, 'media:keywords')?.text, | |||
| keywords: findFirstElement(element, 'media:keywords')?.text, | |||
| thumbnails: element.findElements('media:thumbnail').map((e) { | |||
| return Thumbnail.parse(e); | |||
| }).toList(), | |||
| hash: Hash.parse( | |||
| findElementOrNull(element, 'media:hash'), | |||
| findFirstElement(element, 'media:hash'), | |||
| ), | |||
| player: Player.parse( | |||
| findElementOrNull(element, 'media:player'), | |||
| findFirstElement(element, 'media:player'), | |||
| ), | |||
| copyright: Copyright.parse( | |||
| findElementOrNull(element, 'media:copyright'), | |||
| findFirstElement(element, 'media:copyright'), | |||
| ), | |||
| text: Text.parse( | |||
| findElementOrNull(element, 'media:text'), | |||
| findFirstElement(element, 'media:text'), | |||
| ), | |||
| restriction: Restriction.parse( | |||
| findElementOrNull(element, 'media:restriction'), | |||
| findFirstElement(element, 'media:restriction'), | |||
| ), | |||
| community: Community.parse( | |||
| findElementOrNull(element, 'media:community'), | |||
| findFirstElement(element, 'media:community'), | |||
| ), | |||
| comments: findElementOrNull(element, 'media:comments') | |||
| comments: findFirstElement(element, 'media:comments') | |||
| ?.findElements('media:comment') | |||
| ?.map((e) { | |||
| return e.text; | |||
| })?.toList() ?? | |||
| [], | |||
| embed: Embed.parse( | |||
| findElementOrNull(element, 'media:embed'), | |||
| findFirstElement(element, 'media:embed'), | |||
| ), | |||
| responses: findElementOrNull(element, 'media:responses') | |||
| responses: findFirstElement(element, 'media:responses') | |||
| ?.findElements('media:response') | |||
| ?.map((e) { | |||
| return e.text; | |||
| })?.toList() ?? | |||
| [], | |||
| backLinks: findElementOrNull(element, 'media:backLinks') | |||
| backLinks: findFirstElement(element, 'media:backLinks') | |||
| ?.findElements('media:backLink') | |||
| ?.map((e) { | |||
| return e.text; | |||
| })?.toList() ?? | |||
| [], | |||
| status: Status.parse( | |||
| findElementOrNull(element, 'media:status'), | |||
| findFirstElement(element, 'media:status'), | |||
| ), | |||
| prices: element.findElements('media:price').map((e) { | |||
| return Price.parse(e); | |||
| }).toList(), | |||
| license: License.parse( | |||
| findElementOrNull(element, 'media:license'), | |||
| findFirstElement(element, 'media:license'), | |||
| ), | |||
| peerLink: PeerLink.parse( | |||
| findElementOrNull(element, 'media:peerLink'), | |||
| findFirstElement(element, 'media:peerLink'), | |||
| ), | |||
| rights: Rights.parse( | |||
| findElementOrNull(element, 'media:rights'), | |||
| findFirstElement(element, 'media:rights'), | |||
| ), | |||
| scenes: findElementOrNull(element, 'media:scenes') | |||
| scenes: findFirstElement(element, 'media:scenes') | |||
| ?.findElements('media:scene') | |||
| ?.map((e) { | |||
| return Scene.parse(e); | |||
| @@ -19,10 +19,10 @@ class Scene { | |||
| return null; | |||
| } | |||
| return Scene( | |||
| title: findElementOrNull(element, 'sceneTitle')?.text, | |||
| description: findElementOrNull(element, 'sceneDescription')?.text, | |||
| startTime: findElementOrNull(element, 'sceneStartTime')?.text, | |||
| endTime: findElementOrNull(element, 'sceneEndTime')?.text, | |||
| title: findFirstElement(element, 'sceneTitle')?.text, | |||
| description: findFirstElement(element, 'sceneDescription')?.text, | |||
| startTime: findFirstElement(element, 'sceneStartTime')?.text, | |||
| endTime: findFirstElement(element, 'sceneEndTime')?.text, | |||
| ); | |||
| } | |||
| } | |||
| @@ -59,47 +59,44 @@ class RssFeed { | |||
| factory RssFeed.parse(String xmlString) { | |||
| var document = XmlDocument.parse(xmlString); | |||
| XmlElement channelElement; | |||
| try { | |||
| channelElement = document.findAllElements('channel').first; | |||
| } on StateError { | |||
| var channelElement = findFirstElement(document, 'channel', recursive: true); | |||
| if (channelElement == null) { | |||
| throw ArgumentError('channel not found'); | |||
| } | |||
| return RssFeed( | |||
| title: findElementOrNull(channelElement, 'title')?.text, | |||
| author: findElementOrNull(channelElement, 'author')?.text, | |||
| description: findElementOrNull(channelElement, 'description')?.text, | |||
| link: findElementOrNull(channelElement, 'link')?.text, | |||
| items: channelElement.findElements('item').map((element) { | |||
| return RssItem.parse(element); | |||
| }).toList(), | |||
| image: RssImage.parse(findElementOrNull(channelElement, 'image')), | |||
| cloud: RssCloud.parse(findElementOrNull(channelElement, 'cloud')), | |||
| categories: channelElement.findElements('category').map((element) { | |||
| return RssCategory.parse(element); | |||
| }).toList(), | |||
| skipDays: findElementOrNull(channelElement, 'skipDays') | |||
| title: findFirstElement(channelElement, 'title')?.text, | |||
| author: findFirstElement(channelElement, 'author')?.text, | |||
| description: findFirstElement(channelElement, 'description')?.text, | |||
| link: findFirstElement(channelElement, 'link')?.text, | |||
| items: channelElement | |||
| .findElements('item') | |||
| .map((e) => RssItem.parse(e)) | |||
| .toList(), | |||
| image: RssImage.parse(findFirstElement(channelElement, 'image')), | |||
| cloud: RssCloud.parse(findFirstElement(channelElement, 'cloud')), | |||
| categories: channelElement | |||
| .findElements('category') | |||
| .map((e) => RssCategory.parse(e)) | |||
| .toList(), | |||
| skipDays: findFirstElement(channelElement, 'skipDays') | |||
| ?.findAllElements('day') | |||
| ?.map((element) { | |||
| return element.text; | |||
| })?.toList() ?? | |||
| ?.map((e) => e.text) | |||
| ?.toList() ?? | |||
| [], | |||
| skipHours: findElementOrNull(channelElement, 'skipHours') | |||
| skipHours: findFirstElement(channelElement, 'skipHours') | |||
| ?.findAllElements('hour') | |||
| ?.map((element) { | |||
| return int.tryParse(element.text ?? '0'); | |||
| })?.toList() ?? | |||
| ?.map((e) => int.tryParse(e.text ?? '0')) | |||
| ?.toList() ?? | |||
| [], | |||
| lastBuildDate: findElementOrNull(channelElement, 'lastBuildDate')?.text, | |||
| language: findElementOrNull(channelElement, 'language')?.text, | |||
| generator: findElementOrNull(channelElement, 'generator')?.text, | |||
| copyright: findElementOrNull(channelElement, 'copyright')?.text, | |||
| docs: findElementOrNull(channelElement, 'docs')?.text, | |||
| managingEditor: findElementOrNull(channelElement, 'managingEditor')?.text, | |||
| rating: findElementOrNull(channelElement, 'rating')?.text, | |||
| webMaster: findElementOrNull(channelElement, 'webMaster')?.text, | |||
| ttl: int.tryParse(findElementOrNull(channelElement, 'ttl')?.text ?? '0'), | |||
| lastBuildDate: findFirstElement(channelElement, 'lastBuildDate')?.text, | |||
| language: findFirstElement(channelElement, 'language')?.text, | |||
| generator: findFirstElement(channelElement, 'generator')?.text, | |||
| copyright: findFirstElement(channelElement, 'copyright')?.text, | |||
| docs: findFirstElement(channelElement, 'docs')?.text, | |||
| managingEditor: findFirstElement(channelElement, 'managingEditor')?.text, | |||
| rating: findFirstElement(channelElement, 'rating')?.text, | |||
| webMaster: findFirstElement(channelElement, 'webMaster')?.text, | |||
| ttl: int.tryParse(findFirstElement(channelElement, 'ttl')?.text ?? '0'), | |||
| dc: DublinCore.parse(channelElement), | |||
| itunes: Itunes.parse(channelElement), | |||
| ); | |||
| @@ -6,16 +6,16 @@ class RssImage { | |||
| final String url; | |||
| final String link; | |||
| RssImage(this.title, this.url, this.link); | |||
| RssImage({this.title, this.url, this.link}); | |||
| factory RssImage.parse(XmlElement element) { | |||
| if (element == null) { | |||
| return null; | |||
| } | |||
| var title = findElementOrNull(element, 'title')?.text; | |||
| var url = findElementOrNull(element, 'url')?.text; | |||
| var link = findElementOrNull(element, 'link')?.text; | |||
| return RssImage(title, url, link); | |||
| return RssImage( | |||
| title: findFirstElement(element, 'title')?.text, | |||
| url: findFirstElement(element, 'url')?.text, | |||
| link: findFirstElement(element, 'link')?.text, | |||
| ); | |||
| } | |||
| } | |||
| @@ -45,20 +45,21 @@ class RssItem { | |||
| factory RssItem.parse(XmlElement element) { | |||
| return RssItem( | |||
| title: findElementOrNull(element, 'title')?.text, | |||
| description: findElementOrNull(element, 'description')?.text, | |||
| link: findElementOrNull(element, 'link')?.text, | |||
| categories: element.findElements('category').map((element) { | |||
| return RssCategory.parse(element); | |||
| }).toList(), | |||
| guid: findElementOrNull(element, 'guid')?.text, | |||
| pubDate: parseDateTime(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')), | |||
| title: findFirstElement(element, 'title')?.text, | |||
| description: findFirstElement(element, 'description')?.text, | |||
| link: findFirstElement(element, 'link')?.text, | |||
| categories: element | |||
| .findElements('category') | |||
| .map((e) => RssCategory.parse(e)) | |||
| .toList(), | |||
| guid: findFirstElement(element, 'guid')?.text, | |||
| pubDate: parseDateTime(findFirstElement(element, 'pubDate')?.text), | |||
| author: findFirstElement(element, 'author')?.text, | |||
| comments: findFirstElement(element, 'comments')?.text, | |||
| source: RssSource.parse(findFirstElement(element, 'source')), | |||
| content: RssContent.parse(findFirstElement(element, 'content:encoded')), | |||
| media: Media.parse(element), | |||
| enclosure: RssEnclosure.parse(findElementOrNull(element, 'enclosure')), | |||
| enclosure: RssEnclosure.parse(findFirstElement(element, 'enclosure')), | |||
| dc: DublinCore.parse(element), | |||
| itunes: Itunes.parse(element), | |||
| ); | |||
| @@ -2,26 +2,39 @@ import 'dart:core'; | |||
| import 'package:xml/xml.dart'; | |||
| XmlElement findElementOrNull(XmlElement element, String name, | |||
| {String namespace}) { | |||
| XmlElement findFirstElement( | |||
| XmlNode node, | |||
| String name, { | |||
| bool recursive = false, | |||
| String namespace, | |||
| }) { | |||
| try { | |||
| return element.findAllElements(name, namespace: namespace).first; | |||
| return findElements(node, name, recursive: recursive, namespace: namespace) | |||
| ?.first; | |||
| } on StateError { | |||
| return null; | |||
| } | |||
| } | |||
| List<XmlElement> findAllDirectElementsOrNull(XmlElement element, String name, | |||
| {String namespace}) { | |||
| Iterable<XmlElement> findElements( | |||
| XmlNode node, | |||
| String name, { | |||
| bool recursive = false, | |||
| String namespace, | |||
| }) { | |||
| try { | |||
| return element.findElements(name, namespace: namespace).toList(); | |||
| if (recursive) { | |||
| return node.findAllElements(name, namespace: namespace); | |||
| } else { | |||
| return node.findElements(name, namespace: namespace); | |||
| } | |||
| } on StateError { | |||
| return null; | |||
| } | |||
| } | |||
| bool parseBoolLiteral(XmlElement element, String tagName) { | |||
| var v = findElementOrNull(element, tagName)?.text?.toLowerCase()?.trim(); | |||
| var v = findFirstElement(element, tagName)?.text?.toLowerCase()?.trim(); | |||
| if (v == null) return false; | |||
| return ['yes', 'true'].contains(v); | |||
| } | |||
| @@ -258,7 +258,9 @@ void main() { | |||
| expect(feed.items.first.dc.description, 'description'); | |||
| expect(feed.items.first.dc.publisher, 'publisher'); | |||
| expect(feed.items.first.dc.contributor, 'contributor'); | |||
| expect(feed.items.first.dc.date, DateTime.utc(2000, 1, 1, 12)); | |||
| expect(feed.items.first.dc.date, DateTime.utc(2000, 1, 2, 12)); | |||
| expect(feed.items.first.dc.created, DateTime.utc(2000, 1, 2, 13)); | |||
| expect(feed.items.first.dc.modified, DateTime.utc(2000, 1, 2, 14)); | |||
| expect(feed.items.first.dc.type, 'type'); | |||
| expect(feed.items.first.dc.format, 'format'); | |||
| expect(feed.items.first.dc.identifier, 'identifier'); | |||
| @@ -9,6 +9,8 @@ | |||
| <dc:publisher>publisher</dc:publisher> | |||
| <dc:contributor>contributor</dc:contributor> | |||
| <dc:date>2000-01-01T12:00+00:00</dc:date> | |||
| <dc:created>2000-01-01T13:00+00:00</dc:created> | |||
| <dc:modified>2000-01-01T14:00+00:00</dc:modified> | |||
| <dc:type>type</dc:type> | |||
| <dc:format>format</dc:format> | |||
| <dc:identifier>identifier</dc:identifier> | |||
| @@ -24,9 +26,9 @@ | |||
| <dc:description>description</dc:description> | |||
| <dc:publisher>publisher</dc:publisher> | |||
| <dc:contributor>contributor</dc:contributor> | |||
| <dc:date>2000-01-01T12:00+00:00</dc:date> | |||
| <dc:created>2000-01-01T13:00+00:00</dc:created> | |||
| <dc:modified>2000-01-01T14:00+00:00</dc:modified> | |||
| <dc:date>2000-01-02T12:00+00:00</dc:date> | |||
| <dc:created>2000-01-02T13:00+00:00</dc:created> | |||
| <dc:modified>2000-01-02T14:00+00:00</dc:modified> | |||
| <dc:type>type</dc:type> | |||
| <dc:format>format</dc:format> | |||
| <dc:identifier>identifier</dc:identifier> | |||
| @@ -45,12 +45,9 @@ | |||
| <itunes:keywords>go, golang, open source, software, development</itunes:keywords> | |||
| <itunes:subtitle>with Erik, Carlisia, and Brian</itunes:subtitle> | |||
| <itunes:summary>Foo</itunes:summary> | |||
| <dc:creator> | |||
| Erik St. Martin, Carlisia Pinto, and Brian Ketelsen | |||
| <dc:creator>Erik St. Martin, Carlisia Pinto, and Brian Ketelsen | |||
| </dc:creator> | |||
| <itunes:author> | |||
| Erik St. Martin, Carlisia Pinto, and Brian Ketelsen | |||
| </itunes:author> | |||
| <itunes:author>Erik St. Martin, Carlisia Pinto, and Brian Ketelsen</itunes:author> | |||
| </item> | |||
| </channel> | |||
| </rss> | |||