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,104 @@
note
description: "[
ATOM Parser.
Warning: the implementation may not support the full ATOM specification.
]"
date: "$Date$"
revision: "$Revision$"
EIS: "name=ATOM at wikipedia", "protocol=URI", "src=https://en.wikipedia.org/wiki/Atom_(standard)"
EIS: "name=RSS at wikipedia", "protocol=URI", "src=https://en.wikipedia.org/wiki/RSS"
EIS: "name=ATOM 1.0 RFC4287", "protocol=URI", "src=https://tools.ietf.org/html/rfc4287"
class
ATOM_FEED_PARSER
inherit
FEED_PARSER
feature -- Access
name: STRING = "atom1"
-- Associated name.
is_detected (xdoc: XML_DOCUMENT): BOOLEAN
-- Is `xdoc' an ATOM feed representation?
do
Result := attached {XML_ELEMENT} xdoc.element_by_name ("feed") as x_feed and then
(
not attached xml_attribute_text (x_feed, "xmlns") as l_xmlns
or else l_xmlns.same_string ("http://www.w3.org/2005/Atom")
)
end
feed (xdoc: XML_DOCUMENT): detachable FEED
-- Feed from `xdoc' XML document.
local
l_title: READABLE_STRING_32
x_entry, x_link: detachable XML_ELEMENT
e: FEED_ENTRY
l_author: FEED_AUTHOR
lnk: FEED_LINK
s: STRING_32
do
if
attached xdoc.element_by_name ("feed") as x_feed and then
-- (not attached xml_attribute_text (x_feed, "xmlns") as l_xmlns or else l_xmlns.same_string ("http://www.w3.org/2005/Atom"))
attached xml_element_text (x_feed, "title") as t
then
l_title := t
create Result.make (l_title)
Result.set_description (xml_element_text (x_feed, "subtitle"))
Result.set_id (xml_element_text (x_feed, "id"))
Result.set_updated_date_with_text (xml_element_text (x_feed, "updated"))
if attached links_from_xml (x_feed, "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_feed.elements_by_name ("entry") as x_entries then
across
x_entries as ic
loop
x_entry := ic.item
if attached xml_element_text (x_entry, "title") as e_title then
create e.make (e_title)
e.set_description (xml_element_text (x_entry, "summary"))
e.set_id (xml_element_text (x_entry, "id"))
e.set_updated_date_with_text (xml_element_text (x_entry, "updated"))
if attached links_from_xml (x_entry, "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_entry.element_by_name ("content") as x_content then
e.set_content (xml_element_code (x_content), xml_attribute_text (x_content, "type"))
end
if attached x_entry.element_by_name ("author") as x_author then
if attached x_author.element_by_name ("name") as x_name and then
attached x_name.text as l_author_name
then
create l_author.make (l_author_name)
if attached x_author.element_by_name ("email") as x_email then
l_author.set_email (x_email.text)
end
e.set_author (l_author)
end
end
Result.add_entry (e)
end
end
end
end
end
end

View File

@@ -0,0 +1,193 @@
note
description: "Convert a FEED into an ATOM content."
date: "$Date$"
revision: "$Revision$"
class
ATOM_GENERATOR
inherit
FEED_VISITOR
FEED_GENERATOR
create
make
feature {NONE} -- Initialization
make (a_buffer: STRING_8)
do
buffer := a_buffer
create indentation.make_empty
end
buffer: STRING_8
feature -- Visitor
visit_feed (a_feed: FEED)
do
buffer.append ("[
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
]")
buffer.append_character ('%N')
indent
append_content_tag_to ("title", Void, a_feed.title, buffer)
append_content_tag_to ("subtitle", Void, a_feed.description, buffer)
if attached a_feed.id as l_id then
append_content_tag_to ("id", Void, l_id, buffer)
else
append_content_tag_to ("id", Void, "urn:uuid:" + new_uuid, buffer)
end
across
a_feed.links as tb
loop
tb.item.accept (Current)
end
if attached a_feed.date as dt then
append_content_tag_to ("updated", Void, date_to_string (dt), buffer)
end
across
a_feed.entries as ic
loop
ic.item.accept (Current)
end
exdent
buffer.append ("</feed>")
end
visit_entry (a_entry: FEED_ENTRY)
do
buffer.append (indentation)
buffer.append ("<entry>%N")
indent
append_content_tag_to ("title", Void, a_entry.title, buffer)
across
a_entry.links as tb
loop
tb.item.accept (Current)
end
if attached a_entry.id as l_id then
append_content_tag_to ("id", Void, l_id, buffer)
else
append_content_tag_to ("id", Void, "urn:uuid:" + new_uuid, buffer)
end
if attached a_entry.date as dt then
append_content_tag_to ("updated", Void, date_to_string (dt), buffer)
end
append_content_tag_to ("summary", Void, a_entry.description, buffer)
if attached a_entry.content as l_content then
if attached a_entry.content_type_or_default ("xhtml").is_case_insensitive_equal_general ("xhtml") then
-- if l_content.has_substring ("<div xmlns=%"http://www.w3.org/1999/xhtml%">") then
append_content_tag_to ("content", <<["type", "xhtml"]>>, l_content, buffer)
-- else
-- append_content_tag_to ("content", <<["type", "xhtml"]>>, {STRING_32} "<div xmlns=%"http://www.w3.org/1999/xhtml%">" + l_content + {STRING_32} "</div>", buffer)
-- end
else
append_content_tag_to ("content", <<["type", a_entry.content_type]>>, a_entry.content, buffer)
end
end
if attached a_entry.author as u then
u.accept (Current)
end
exdent
buffer.append (indentation)
buffer.append ("</entry>%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
tu := ["href", a_link.href.as_string_32]
attr.force (tu)
if attr.is_empty then
attr := Void
end
append_content_tag_to ("link", attr, Void, buffer)
end
visit_author (a_author: FEED_AUTHOR)
do
buffer.append (indentation)
buffer.append ("<author>%N")
indent
append_content_tag_to ("name", Void, a_author.name, buffer)
append_content_tag_to ("email", Void, a_author.email, buffer)
exdent
buffer.append (indentation)
buffer.append ("</author>%N")
end
feature {NONE} -- Helpers
new_uuid: STRING
local
gen: UUID_GENERATOR
do
create gen
Result := gen.generate_uuid.out.as_lower
end
date_to_string (dt: DATE_TIME): STRING
do
Result := date_to_rfc3339_string (dt)
end
date_to_rfc3339_string (d: DATE_TIME): STRING
-- 2003-12-13T18:30:02Z
local
i: INTEGER
do
create Result.make_empty
Result.append_integer (d.year)
Result.append_character ('-')
i := d.month
if i < 10 then
Result.append_integer (0)
end
Result.append_integer (i)
Result.append_character ('-')
i := d.day
if i < 10 then
Result.append_integer (0)
end
Result.append_integer (i)
Result.append_character ('T')
i := d.hour
if i < 10 then
Result.append_integer (0)
end
Result.append_integer (i)
Result.append_character (':')
i := d.minute
if i < 10 then
Result.append_integer (0)
end
Result.append_integer (i)
Result.append_character (':')
i := d.second
if i < 10 then
Result.append_integer (0)
end
Result.append_integer (i)
Result.append_character ('Z')
end
end