Added initial ATOM and RSS feed parser and generator.
(work in progress)
This commit is contained in:
105
library/text/parser/feed/src/support/feed_generator.e
Normal file
105
library/text/parser/feed/src/support/feed_generator.e
Normal file
@@ -0,0 +1,105 @@
|
||||
note
|
||||
description: "Summary description for {FEED_GENERATOR}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
FEED_GENERATOR
|
||||
|
||||
inherit
|
||||
XML_UTILITIES
|
||||
|
||||
feature {NONE} -- Helpers
|
||||
|
||||
initialize
|
||||
do
|
||||
create indentation.make_empty
|
||||
end
|
||||
|
||||
indent
|
||||
do
|
||||
indentation.append ("%T")
|
||||
end
|
||||
|
||||
exdent
|
||||
require
|
||||
has_indentation: indentation.count > 0
|
||||
do
|
||||
indentation.remove_tail (1)
|
||||
end
|
||||
|
||||
indentation: STRING
|
||||
|
||||
append_content_tag_to (a_tagname: READABLE_STRING_8; a_attr: detachable ITERABLE [TUPLE [name: READABLE_STRING_8; value: detachable READABLE_STRING_GENERAL]]; a_content: detachable READABLE_STRING_GENERAL; a_output: STRING)
|
||||
do
|
||||
if a_content /= Void or a_attr /= Void then
|
||||
a_output.append (indentation)
|
||||
a_output.append ("<")
|
||||
a_output.append (a_tagname)
|
||||
if a_attr /= Void then
|
||||
across
|
||||
a_attr as ic
|
||||
loop
|
||||
if attached ic.item.value as l_att_value then
|
||||
a_output.append_character (' ')
|
||||
a_output.append (ic.item.name)
|
||||
a_output.append_character ('=')
|
||||
a_output.append_character ('%"')
|
||||
a_output.append (escaped_unicode_xml (l_att_value.as_string_32))
|
||||
a_output.append_character ('%"')
|
||||
end
|
||||
end
|
||||
end
|
||||
if a_content = Void then
|
||||
a_output.append ("/>")
|
||||
else
|
||||
a_output.append (">")
|
||||
a_output.append (escaped_unicode_xml (a_content.as_string_32))
|
||||
a_output.append ("</" + a_tagname + ">%N")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
append_cdata_content_tag_to (a_tagname: READABLE_STRING_8; a_attr: detachable ITERABLE [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_32]]; a_content: detachable READABLE_STRING_32; a_output: STRING)
|
||||
do
|
||||
if a_content /= Void then
|
||||
a_output.append (indentation)
|
||||
a_output.append ("<")
|
||||
a_output.append (a_tagname)
|
||||
if a_attr /= Void then
|
||||
across
|
||||
a_attr as ic
|
||||
loop
|
||||
a_output.append_character (' ')
|
||||
a_output.append (ic.item.name)
|
||||
a_output.append_character ('=')
|
||||
a_output.append_character ('%"')
|
||||
a_output.append (escaped_unicode_xml (ic.item.value))
|
||||
a_output.append_character ('%"')
|
||||
end
|
||||
end
|
||||
a_output.append (">")
|
||||
a_output.append (to_cdata_element (a_content))
|
||||
a_output.append ("</" + a_tagname + ">%N")
|
||||
end
|
||||
end
|
||||
|
||||
to_cdata_element (a_value: READABLE_STRING_GENERAL): STRING
|
||||
local
|
||||
cdata: XML_CHARACTER_DATA
|
||||
xdoc: XML_DOCUMENT
|
||||
pprinter: XML_NODE_PRINTER
|
||||
l_output: XML_STRING_8_OUTPUT_STREAM
|
||||
do
|
||||
create xdoc.make
|
||||
create cdata.make (xdoc.root_element, a_value.as_string_32)
|
||||
create pprinter.make
|
||||
create Result.make (cdata.content_count)
|
||||
create l_output.make (Result)
|
||||
pprinter.set_output (l_output)
|
||||
pprinter.process_character_data (cdata)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
87
library/text/parser/feed/src/support/feed_helpers.e
Normal file
87
library/text/parser/feed/src/support/feed_helpers.e
Normal file
@@ -0,0 +1,87 @@
|
||||
note
|
||||
description: "Summary description for {FEED_HELPERS}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
FEED_HELPERS
|
||||
|
||||
feature -- Helpers
|
||||
|
||||
date_time (a_date_string: READABLE_STRING_32): DATE_TIME
|
||||
-- "2015-08-14T10:34:13.493740Z"
|
||||
-- "Sat, 07 Sep 2002 00:00:01 GMT"
|
||||
local
|
||||
i,j: INTEGER
|
||||
s: READABLE_STRING_GENERAL
|
||||
y,m,d,h,min: INTEGER
|
||||
sec: REAL_64
|
||||
htdate: HTTP_DATE
|
||||
str: STRING_32
|
||||
do
|
||||
if a_date_string.count > 0 and then a_date_string.item (1).is_digit then
|
||||
i := a_date_string.index_of ('-', 1)
|
||||
if i > 0 then
|
||||
s := a_date_string.substring (1, i - 1)
|
||||
y := s.to_integer_32 -- Year
|
||||
j := i + 1
|
||||
i := a_date_string.index_of ('-', j)
|
||||
if i > 0 then
|
||||
s := a_date_string.substring (j, i - 1)
|
||||
m := s.to_integer_32 -- Month
|
||||
j := i + 1
|
||||
i := a_date_string.index_of ('T', j)
|
||||
if i = 0 then
|
||||
i := a_date_string.index_of (' ', j)
|
||||
end
|
||||
if i = 0 then
|
||||
i := a_date_string.count + 1
|
||||
end
|
||||
if i > 0 then
|
||||
s := a_date_string.substring (j, i - 1)
|
||||
if s.is_integer then
|
||||
d := s.to_integer_32 -- Day
|
||||
j := i + 1
|
||||
i := a_date_string.index_of (':', j)
|
||||
if i > 0 then
|
||||
s := a_date_string.substring (j, i - 1)
|
||||
h := s.to_integer
|
||||
j := i + 1
|
||||
i := a_date_string.index_of (':', j)
|
||||
if i > 0 then
|
||||
s := a_date_string.substring (j, i - 1)
|
||||
min := s.to_integer
|
||||
j := i + 1
|
||||
i := a_date_string.index_of ('Z', j)
|
||||
if i = 0 then
|
||||
i := a_date_string.count + 1
|
||||
end
|
||||
s := a_date_string.substring (j, i - 1)
|
||||
sec := s.to_double
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
create Result.make (y,m,d,h,m,0)
|
||||
Result.fine_second_add (sec)
|
||||
else
|
||||
i := a_date_string.index_of ('+', 1)
|
||||
if i > 0 then
|
||||
str := a_date_string.substring (1, i - 1)
|
||||
str.append (" GMT")
|
||||
create htdate.make_from_string (str)
|
||||
Result := htdate.date_time
|
||||
if a_date_string.substring (i + 1, a_date_string.count).is_case_insensitive_equal ("0000") then
|
||||
|
||||
end
|
||||
else
|
||||
create htdate.make_from_string (a_date_string)
|
||||
Result := htdate.date_time
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
84
library/text/parser/feed/src/support/feed_parser_utilities.e
Normal file
84
library/text/parser/feed/src/support/feed_parser_utilities.e
Normal file
@@ -0,0 +1,84 @@
|
||||
note
|
||||
description: "Summary description for {FEED_PARSER_UTILITIES}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
FEED_PARSER_UTILITIES
|
||||
|
||||
feature -- Access
|
||||
|
||||
xml_element_text (a_parent: XML_ELEMENT; a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||
do
|
||||
if attached a_parent.element_by_name (a_name) as elt then
|
||||
if attached elt.text as t then
|
||||
t.left_adjust
|
||||
t.right_adjust
|
||||
Result := t
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
xml_attribute_text (a_elt: XML_ELEMENT; a_att_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||
do
|
||||
if attached a_elt.attribute_by_name (a_att_name) as att then
|
||||
Result := att.value
|
||||
end
|
||||
end
|
||||
|
||||
xml_element_code (elt: XML_ELEMENT): STRING_32
|
||||
local
|
||||
xprinter: XML_NODE_PRINTER
|
||||
do
|
||||
create xprinter.make
|
||||
create Result.make_empty
|
||||
xprinter.set_output (create {XML_STRING_32_OUTPUT_STREAM}.make (Result))
|
||||
xprinter.process_element (elt)
|
||||
end
|
||||
|
||||
links_from_xml (elt: XML_ELEMENT; a_link_elt_name: READABLE_STRING_GENERAL): detachable ARRAYED_LIST [FEED_LINK]
|
||||
local
|
||||
x_link: XML_ELEMENT
|
||||
lnk: FEED_LINK
|
||||
do
|
||||
if attached elt.elements_by_name (a_link_elt_name) as x_links then
|
||||
create Result.make (0)
|
||||
across
|
||||
x_links as ic
|
||||
loop
|
||||
x_link := ic.item
|
||||
if attached xml_attribute_text (x_link, "href") as l_href and then
|
||||
l_href.is_valid_as_string_8
|
||||
then
|
||||
create lnk.make (l_href.as_string_8)
|
||||
lnk.set_relation (xml_attribute_text (x_link, "rel"))
|
||||
lnk.set_type (xml_attribute_text (x_link, "type"))
|
||||
Result.force (lnk)
|
||||
elseif attached x_link.text as l_url and then not l_url.is_whitespace then
|
||||
create lnk.make (l_url)
|
||||
Result.force (lnk)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
element_by_prefixed_name (elt: XML_ELEMENT; a_ns_prefix: READABLE_STRING_GENERAL; a_name: READABLE_STRING_GENERAL): detachable XML_ELEMENT
|
||||
do
|
||||
across
|
||||
elt as ic
|
||||
until
|
||||
Result /= Void
|
||||
loop
|
||||
if attached {XML_ELEMENT} ic.item as x_item then
|
||||
if
|
||||
attached x_item.ns_prefix as l_ns_prefix and then a_ns_prefix.same_string (l_ns_prefix) and then
|
||||
a_name.same_string (x_item.name)
|
||||
then
|
||||
Result := x_item
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
197
library/text/parser/feed/src/support/feed_to_string_32_visitor.e
Normal file
197
library/text/parser/feed/src/support/feed_to_string_32_visitor.e
Normal file
@@ -0,0 +1,197 @@
|
||||
note
|
||||
description: "Convert a FEED to STRING_32 representation. Mostly for debug output."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
FEED_TO_STRING_32_VISITOR
|
||||
|
||||
inherit
|
||||
FEED_VISITOR
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_buffer: STRING_32)
|
||||
do
|
||||
buffer := a_buffer
|
||||
create indentation.make_empty
|
||||
end
|
||||
|
||||
buffer: STRING_32
|
||||
|
||||
feature -- Visitor
|
||||
|
||||
visit_feed (a_feed: FEED)
|
||||
do
|
||||
if attached a_feed.id as l_id then
|
||||
append_text ("#")
|
||||
append (l_id)
|
||||
append_new_line
|
||||
end
|
||||
if attached a_feed.date as dt then
|
||||
append_text ("date:")
|
||||
append (dt.out)
|
||||
append_new_line
|
||||
end
|
||||
|
||||
append_text (a_feed.title)
|
||||
append_new_line
|
||||
indent
|
||||
if attached a_feed.description as l_desc then
|
||||
append_text (l_desc)
|
||||
append_new_line
|
||||
end
|
||||
|
||||
across
|
||||
a_feed.links as ic
|
||||
loop
|
||||
ic.item.accept (Current)
|
||||
append_new_line
|
||||
end
|
||||
|
||||
append_new_line
|
||||
|
||||
across
|
||||
a_feed.entries as ic
|
||||
loop
|
||||
exdent
|
||||
append_text (create {STRING_32}.make_filled ('-', 40))
|
||||
append_new_line
|
||||
indent
|
||||
ic.item.accept (Current)
|
||||
append_new_line
|
||||
end
|
||||
end
|
||||
|
||||
visit_entry (a_entry: FEED_ENTRY)
|
||||
do
|
||||
if attached a_entry.id as l_id then
|
||||
append_text ("#")
|
||||
append (l_id)
|
||||
append_new_line
|
||||
end
|
||||
if attached a_entry.date as dt then
|
||||
append_text ("date:")
|
||||
append (dt.out)
|
||||
append_new_line
|
||||
end
|
||||
append_text (a_entry.title)
|
||||
append_new_line
|
||||
indent
|
||||
if attached a_entry.author as l_author then
|
||||
l_author.accept (Current)
|
||||
append_new_line
|
||||
end
|
||||
if attached a_entry.categories as cats then
|
||||
append_text ("Categories: ")
|
||||
from
|
||||
cats.start
|
||||
until
|
||||
cats.after
|
||||
loop
|
||||
if not cats.isfirst then
|
||||
append (", ")
|
||||
end
|
||||
append (cats.item)
|
||||
cats.forth
|
||||
end
|
||||
append_new_line
|
||||
end
|
||||
if attached a_entry.description as l_summary then
|
||||
append_text (l_summary)
|
||||
append_new_line
|
||||
end
|
||||
|
||||
across
|
||||
a_entry.links as ic
|
||||
loop
|
||||
ic.item.accept (Current)
|
||||
append_new_line
|
||||
end
|
||||
|
||||
if attached a_entry.content as l_content then
|
||||
append_text (l_content)
|
||||
append_new_line
|
||||
end
|
||||
exdent
|
||||
end
|
||||
|
||||
visit_link (a_link: FEED_LINK)
|
||||
local
|
||||
s: STRING_32
|
||||
do
|
||||
create s.make_empty
|
||||
s.append_string_general ("@")
|
||||
s.append_string (a_link.relation)
|
||||
s.append_string (" -> ")
|
||||
s.append_string (a_link.href)
|
||||
append_text (s)
|
||||
end
|
||||
|
||||
visit_author (a_author: FEED_AUTHOR)
|
||||
local
|
||||
s: STRING_32
|
||||
do
|
||||
create s.make_empty
|
||||
s.append_string_general ("by ")
|
||||
s.append_string (a_author.name)
|
||||
if attached a_author.email as l_email then
|
||||
s.append_character (' ')
|
||||
s.append_character ('(')
|
||||
s.append_string_general (l_email)
|
||||
s.append_character (')')
|
||||
end
|
||||
append_text (s)
|
||||
end
|
||||
|
||||
feature -- Helper
|
||||
|
||||
indentation: STRING_32
|
||||
|
||||
indent
|
||||
do
|
||||
indentation.append (" ")
|
||||
end
|
||||
|
||||
exdent
|
||||
do
|
||||
indentation.remove_tail (2)
|
||||
end
|
||||
|
||||
append_new_line
|
||||
do
|
||||
append ("%N")
|
||||
end
|
||||
|
||||
append_text (s: READABLE_STRING_GENERAL)
|
||||
local
|
||||
lst: LIST [READABLE_STRING_GENERAL]
|
||||
do
|
||||
if indentation.is_empty then
|
||||
append (s)
|
||||
else
|
||||
lst := s.split ('%N')
|
||||
from
|
||||
lst.start
|
||||
until
|
||||
lst.after
|
||||
loop
|
||||
append (indentation)
|
||||
append (lst.item)
|
||||
if not lst.islast then
|
||||
append ("%N")
|
||||
end
|
||||
lst.forth
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
append (s: READABLE_STRING_GENERAL)
|
||||
do
|
||||
buffer.append_string_general (s)
|
||||
end
|
||||
|
||||
end
|
||||
28
library/text/parser/feed/src/support/feed_visitor.e
Normal file
28
library/text/parser/feed/src/support/feed_visitor.e
Normal file
@@ -0,0 +1,28 @@
|
||||
note
|
||||
description: "Summary description for {FEED_VISITOR}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
FEED_VISITOR
|
||||
|
||||
feature -- Visit
|
||||
|
||||
visit_feed (a_feed: FEED)
|
||||
deferred
|
||||
end
|
||||
|
||||
visit_link (a_link: FEED_LINK)
|
||||
deferred
|
||||
end
|
||||
|
||||
visit_entry (a_entry: FEED_ENTRY)
|
||||
deferred
|
||||
end
|
||||
|
||||
visit_author (a_author: FEED_AUTHOR)
|
||||
deferred
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user