Added initial ATOM and RSS feed parser and generator.
(work in progress)
This commit is contained in:
125
library/text/parser/feed/src/rss/rss_2_feed_parser.e
Normal file
125
library/text/parser/feed/src/rss/rss_2_feed_parser.e
Normal 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
|
||||
133
library/text/parser/feed/src/rss/rss_2_generator.e
Normal file
133
library/text/parser/feed/src/rss/rss_2_generator.e
Normal 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
|
||||
Reference in New Issue
Block a user