#!/usr/bin/python
import time
class FeedError(Exception): pass
def escape_xml(s):
"""Escape special characters in XML."""
chars = { "<" : "lt",
">" : "gt",
"&" : "amp",
'"' : "quot",
"'" : "apos" }
cs = []
for c in s:
if chars.has_key(c):
cs.append("&" + chars[c] + ";")
else:
cs.append(c)
return "".join(cs)
def wrap(name, value):
if value is None:
return ""
else:
return "<" + name + ">" + escape_xml(value).encode("UTF-8") + "" + name + ">\n"
class Channel:
"""A summary of a syndicated site."""
def __init__(self, title, link, description):
self.title = title
self.link = link
self.description = description
self.items = []
def add_item(self, *args, **keywords):
"""Add an item to the feed. The arguments to this method
are the same as for the Item constructor."""
self.items.append(Item(*args, **keywords))
def rss2(self):
"""Return the RSS 2.0 representation of this feed."""
bits = []
bits.append('\n')
bits.append('\n')
bits.append('\n')
bits.append(wrap("title", self.title))
bits.append(wrap("link", self.link))
bits.append(wrap("description", self.description))
for item in self.items:
bits.append('- \n')
bits.append(wrap("title", item.title))
bits.append(wrap("link", item.link))
bits.append(wrap("description", item.description))
if item.pubDate is not None:
d = item.pubDate
if type(d) is not tuple and type(d) is not time.struct_time:
d = time.gmtime(d)
s = time.strftime("%a, %d %b %Y %H:%M:%S +0000",
d)
bits.append(wrap("pubDate", s))
bits.append('
\n')
bits.append('\n\n')
return "".join(bits)
class Item:
"""An item in a syndication feed."""
def __init__(self, title = None, link = None, description = None, pubDate = None):
if title is None and description is None:
raise FeedError("Item must have either title or description")
self.title = title
self.link = link
self.description = description
self.pubDate = pubDate
if __name__ == "__main__":
c = Channel(title = "Test Stuff", link = "http://teststuff.example.com/", description = "Some test items for feedwriter")
c.add_item(title = "Title only")
try:
c.add_item(link = "http://example.com/")
except FeedError:
pass
else:
raise "Expected exception here"
c.add_item(title = "All of them", link = "http://example.com/", description = "Here's some stuff complete with embedded HTML.", pubDate = time.time())
print c.rss2()