Skip to content

Commit

Permalink
Refactoring for processing feeds with data.zip
Browse files Browse the repository at this point in the history
  • Loading branch information
eprunier committed Jul 24, 2013
1 parent aa076ed commit 9a89739
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 50 deletions.
3 changes: 2 additions & 1 deletion project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
:url "http://github.com/eprunier/ariane"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.5.1"]])
:dependencies [[org.clojure/clojure "1.5.1"]
[org.clojure/data.zip "0.1.1"]])
62 changes: 50 additions & 12 deletions src/ariane/atom.clj
Original file line number Diff line number Diff line change
@@ -1,16 +1,54 @@
(ns ariane.atom
"Namespace for parsing Atom feeds.")
"Namespace for parsing Atom feeds."
(:require [clojure.zip :as zip]
[clojure.data.zip.xml :as zip-xml]))

(defn- add-map-entry
"Add key/value entry to map only if value is not nil."
[to [key value]]
(if value
(assoc to key value)
to))

(defn- links
[links]
(vec (for [link links]
(let [link-spec {:href
(first (zip-xml/xml-> link (zip-xml/attr :href)))}]
(if-let [rel (first (zip-xml/xml-> link (zip-xml/attr :rel)))]
(assoc link-spec :rel rel)
link-spec)))))

(defn- infos
[root]
(-> {}
(add-map-entry [:title (first (zip-xml/xml-> root :title zip-xml/text))])
(add-map-entry [:description (first (zip-xml/xml-> root :summary zip-xml/text))])
(add-map-entry [:updated (first (zip-xml/xml-> root :updated zip-xml/text))])
(add-map-entry [:links (links (zip-xml/xml-> root :link))])))

(defn- authors
[authors]
(vec (for [author authors]
{:name (first (zip-xml/xml-> author :name zip-xml/text))
:uri (first (zip-xml/xml-> author :uri zip-xml/text))})))

(defn- entries
[root]
(for [entry (zip-xml/xml-> root :entry)]
(-> {}
(add-map-entry [:id (first (zip-xml/xml-> entry :id zip-xml/text))])
(add-map-entry [:title (first (zip-xml/xml-> entry :title zip-xml/text))])
(add-map-entry [:links (links (zip-xml/xml-> entry :link))])
(add-map-entry [:updated (first (zip-xml/xml-> entry :updated zip-xml/text))])
(add-map-entry [:authors (authors (zip-xml/xml-> entry :author))])
(add-map-entry [:description
{:type (first (zip-xml/xml-> entry :content (zip-xml/attr :type)))
:content (first (zip-xml/xml-> entry :content zip-xml/text))}]))))

(defn parse-atom
"Parse Atom feed generated by ariane.core/parse"
"Parse Atom feed generated by ariane.core/parse. "
[feed]
(for [tag feed]
(let [tag-name (:tag tag)
tag-content (:content tag)]
(cond
(= tag-name :subtitle) [:description (first tag-content)]
(= tag-name :summary) [:description (first tag-content)]
(= tag-name :link) [:link (get-in tag [:attrs :href])]
(= tag-name :author) [:author (parse-atom (:content tag))]
(= tag-name :entry) [:item (parse-atom (:content tag))]
:else [tag-name (first tag-content)]))))
(let [root (zip/xml-zip feed)]
{:infos (infos root)
:entries (entries root)}))
20 changes: 3 additions & 17 deletions src/ariane/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,6 @@
[source]
(let [feed (xml/parse source)]
(cond
(rss-feed? feed) (rss/parse-rss (:content feed))
(atom-feed? feed) (atom/parse-atom (:content feed))
:else (println "Unkown format"))))

(defn infos
"Returns feed informations."
[data]
(filter (fn [[name _]]
(not= :item name))
data))

(defn items
"Returns feed items."
[data]
(filter (fn [[name _]]
(= :item name))
data))
(rss-feed? feed) (rss/parse-rss feed)
(atom-feed? feed) (atom/parse-atom feed)
:else (println "Unsupported format"))))
69 changes: 49 additions & 20 deletions src/ariane/rss.clj
Original file line number Diff line number Diff line change
@@ -1,26 +1,55 @@
(ns ariane.rss
"Namespace for parsing RSS feeds.")
"Namespace for parsing RSS feeds."
(:require [clojure.zip :as zip]
[clojure.data.zip.xml :as zip-xml]))

(defn- channel
[feed]
(:content (first feed)))
(defn- add-map-entry
"Add key/value entry to map only if value is not nil."
[to [key value]]
(if (and value
(not-empty value))
(assoc to key value)
to))

(defn- parse-feed
[feed]
(for [tag feed]
(let [tag-name (:tag tag)
tag-content (:content tag)]
(cond
(= tag-name :guid) [:id (first tag-content)]
(= tag-name :lastBuildDate) [:updated (first tag-content)]
(= tag-name :pubDate) [:published (first tag-content)]
(= tag-name :author) [:author (parse-feed (:content tag))]
(= tag-name :item) [:item (parse-feed (:content tag))]
:else [tag-name (first tag-content)]))))
(defn- links
[links]
(vec (for [link links]
(let [link-spec {:href
(first (zip-xml/xml-> link zip-xml/text))}]
(if-let [rel (first (zip-xml/xml-> link (zip-xml/attr :rel)))]
(assoc link-spec :rel rel)
link-spec)))))

(defn- infos
[root]
(-> {}
(add-map-entry [:title (first (zip-xml/xml-> root :title zip-xml/text))])
(add-map-entry [:description (first (zip-xml/xml-> root :description zip-xml/text))])
(add-map-entry [:updated (first (zip-xml/xml-> root :lastBuildDate zip-xml/text))])
(add-map-entry [:links (links (zip-xml/xml-> root :link))])))

(defn- authors
[authors]
(vec (for [author authors]
{:name (first (zip-xml/xml-> author :name zip-xml/text))
:uri (first (zip-xml/xml-> author :uri zip-xml/text))})))

(defn- entries
[root]
(for [entry (zip-xml/xml-> root :item)]
(-> {}
(add-map-entry [:id (first (zip-xml/xml-> entry :guid zip-xml/text))])
(add-map-entry [:title (first (zip-xml/xml-> entry :title zip-xml/text))])
(add-map-entry [:links (links (zip-xml/xml-> entry :link))])
(add-map-entry [:updated (first (zip-xml/xml-> entry :pubDate zip-xml/text))])
(add-map-entry [:authors (authors (zip-xml/xml-> entry :author))])
(add-map-entry [:description
{:content (first (zip-xml/xml-> entry :description zip-xml/text))}]))))

(defn parse-rss
"Parse RSS feed generated by ariane.core/parse"
"Parse Atom feed generated by ariane.core/parse. "
[feed]
(-> feed
channel
parse-feed))
(let [root (zip/xml-zip feed)
channel (first (zip-xml/xml-> root :channel))]
{:infos (infos channel)
:entries (entries channel)}))

0 comments on commit 9a89739

Please sign in to comment.