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