Added initial ATOM and RSS feed parser and generator.

(work in progress)
This commit is contained in:
2015-09-07 19:22:50 +02:00
parent 1f1e2abbda
commit 39887c8bdb
22 changed files with 1820 additions and 0 deletions

View File

@@ -0,0 +1,125 @@
note
description: "[
RSS 2.0 Parser.
Warning: the implementation may not support the full RSS 2.0 specification.
]"
date: "$Date$"
revision: "$Revision$"
EIS: "name=RSS at wikipedia", "protocol=URI", "src=https://en.wikipedia.org/wiki/RSS"
EIS: "name=RDF Site Summary (RSS) 1.0", "protocol=URI", "src=http://purl.org/rss/1.0/spec"
class
RSS_2_FEED_PARSER
inherit
FEED_PARSER
feature -- Access
name: STRING = "rss2"
-- Associated name.
is_detected (xdoc: XML_DOCUMENT): BOOLEAN
-- Is `xdoc' an ATOM feed representation?
do
if attached {XML_ELEMENT} xdoc.element_by_name ("rss") as x_rss then
if attached xml_attribute_text (x_rss, "version") as l_version and then
l_version.starts_with ("2.")
then
Result := True
else
-- Let's default to RSS 2.0 for now.
Result := True
end
end
end
feed (xdoc: XML_DOCUMENT): detachable FEED
-- Feed from `xdoc' XML RSS 2.0 document.
local
lnk: FEED_LINK
x_item, x_content, x_author: detachable XML_ELEMENT
e: FEED_ENTRY
l_author: FEED_AUTHOR
do
if attached xdoc.element_by_name ("rss") as x_rss then
if
attached xml_attribute_text (x_rss, "version") as l_version and then
l_version.starts_with ("2.")
then
if attached x_rss.element_by_name ("channel") as x_channel then
if attached xml_element_text (x_channel, "title") as x_title then
create Result.make (x_title)
Result.set_description (xml_element_text (x_channel, "description"))
Result.set_updated_date_with_text (xml_element_text (x_channel, "lastBuildDate"))
if attached links_from_xml (x_channel, "link") as l_links then
across
l_links as link_ic
loop
lnk := link_ic.item
Result.links.force (lnk, lnk.relation)
end
end
if attached x_channel.elements_by_name ("item") as x_items then
across
x_items as ic
loop
x_item := ic.item
if attached xml_element_text (x_item, "title") as e_title then
create e.make (e_title)
e.set_description (xml_element_text (x_item, "description"))
e.set_updated_date_with_text (xml_element_text (x_item, "pubDate"))
e.set_id (xml_element_text (x_item, "guid"))
x_author := x_item.element_by_name ("creator")
if x_author = Void then
x_author := element_by_prefixed_name (x_item, "dc" , "creator")
end
if
x_author /= Void and then
attached x_author.text as l_author_name
then
create l_author.make (l_author_name)
e.set_author (l_author)
end
if attached links_from_xml (x_item, "link") as l_links then
across
l_links as link_ic
loop
lnk := link_ic.item
e.links.force (lnk, lnk.relation)
end
end
if attached x_item.elements_by_name ("category") as x_categories then
across
x_categories as cats
loop
if attached cats.item.text as cat then
e.set_category (cat)
end
end
end
x_content := x_item.element_by_name ("content")
if x_content = Void then
x_content := element_by_prefixed_name (x_item, "content" , "encoded")
if x_content /= Void then
e.set_content (x_content.text, Void)
end
else
e.set_content (xml_element_code (x_content), Void)
end
Result.add_entry (e)
end
end
end
end
end
end
end
end
end

View File

@@ -0,0 +1,133 @@
note
description: "Convert a FEED into an RSS 2.0 content."
date: "$Date$"
revision: "$Revision$"
class
RSS_2_GENERATOR
inherit
FEED_VISITOR
FEED_GENERATOR
create
make
feature {NONE} -- Initialization
make (a_buffer: STRING_8)
do
buffer := a_buffer
initialize
end
buffer: STRING_8
feature -- Visitor
visit_feed (a_feed: FEED)
do
buffer.append ("[
<?xml version="1.0" encoding="UTF-8"?>
<rss
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
version="2.0">
<channel>
]")
buffer.append_character ('%N')
indent
indent
append_content_tag_to ("title", Void, a_feed.title, buffer)
append_content_tag_to ("description", Void, a_feed.description, buffer)
across
a_feed.links as tb
loop
tb.item.accept (Current)
end
if attached a_feed.date as dt then
append_content_tag_to ("lastBuildDate", Void, date_to_string (dt), buffer)
end
across
a_feed.entries as ic
loop
ic.item.accept (Current)
end
exdent
exdent
buffer.append ("[
</channel>
</rss>
]")
end
visit_entry (a_entry: FEED_ENTRY)
do
buffer.append (indentation)
buffer.append ("<item>%N")
indent
append_content_tag_to ("title", Void, a_entry.title, buffer)
if attached a_entry.date as dt then
append_content_tag_to ("pubDate", Void, date_to_string (dt), buffer)
end
across
a_entry.links as tb
loop
tb.item.accept (Current)
end
if attached a_entry.author as u then
u.accept (Current)
end
if attached a_entry.categories as cats then
across
cats as ic
loop
append_content_tag_to ("category", Void, ic.item, buffer)
end
end
append_content_tag_to ("guid", Void, a_entry.id, buffer)
append_content_tag_to ("description", Void, a_entry.description, buffer)
append_cdata_content_tag_to ("content:encoded", Void, a_entry.content, buffer)
exdent
buffer.append (indentation)
buffer.append ("</item>%N")
end
visit_link (a_link: FEED_LINK)
local
attr: detachable ARRAYED_LIST [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_32]]
tu: TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_32]
do
create attr.make (2)
if attached a_link.relation as rel and then not rel.is_whitespace then
tu := ["rel", rel]
attr.force (tu)
end
if attached a_link.type as t and then not t.is_whitespace then
tu := ["type", t.as_string_32]
attr.force (tu)
end
if attr.is_empty then
attr := Void
end
append_content_tag_to ("link", attr, a_link.href, buffer)
end
visit_author (a_author: FEED_AUTHOR)
do
append_content_tag_to ("dc:creator", Void, a_author.name, buffer)
end
feature {NONE} -- Helpers
date_to_string (dt: DATE_TIME): STRING
local
htdate: HTTP_DATE
do
create htdate.make_from_date_time (dt)
Result := htdate.rfc850_string
end
end