Feed Creation: Add a separate extension call for namespace stuff. Change extensions accordingly.

Entry creation: Entries create their own XML Element, which is put into the feed by the caller
This commit is contained in:
wltb 2014-05-01 01:18:30 +02:00
parent 1e9cf23f65
commit bf6b8af249
5 changed files with 78 additions and 79 deletions

View file

@ -57,13 +57,9 @@ class FeedEntry(object):
self.__extensions = {} self.__extensions = {}
def atom_entry(self, feed, extensions=True): def atom_entry(self, extensions=True):
'''Insert an ATOM entry into a existing XML structure. Normally you '''Create an ATOM entry and return it.'''
would pass the feed node of an ATOM feed XML to this function. entry = etree.Element('entry')
:param feed: The XML element to use as parent node for the element.
'''
entry = etree.SubElement(feed, 'entry')
if not ( self.__atom_id and self.__atom_title and self.__atom_updated ): if not ( self.__atom_id and self.__atom_title and self.__atom_updated ):
raise ValueError('Required fields not set') raise ValueError('Required fields not set')
id = etree.SubElement(entry, 'id') id = etree.SubElement(entry, 'id')
@ -175,13 +171,9 @@ class FeedEntry(object):
return entry return entry
def rss_entry(self, feed, extensions=True): def rss_entry(self, extensions=True):
'''Insert an RSS item into a existing XML structure. Normally you '''Create a RSS item and return it.'''
would pass the channel node of an RSS feed XML to this function. entry = etree.Element('item')
:param feed: The XML element to use as parent node for the item.
'''
entry = etree.SubElement(feed, 'item')
if not ( self.__rss_title or self.__rss_description or self.__rss_content): if not ( self.__rss_title or self.__rss_description or self.__rss_content):
raise ValueError('Required fields not set') raise ValueError('Required fields not set')
if self.__rss_title: if self.__rss_title:

View file

@ -15,9 +15,12 @@
class BaseExtension(object): class BaseExtension(object):
'''Basic FeedGenerator extension. '''Basic FeedGenerator extension.
''' '''
def extend_ns(self):
'''Returns a dict that will be used in the namespace map for the feed.'''
return dict()
def extend_rss(self, feed): def extend_rss(self, feed):
'''Create an RSS feed xml structure containing all previously set fields. '''Extend a RSS feed xml structure containing all previously set fields.
:param feed: The feed xml root element. :param feed: The feed xml root element.
:returns: The feed root element. :returns: The feed root element.
@ -26,7 +29,7 @@ class BaseExtension(object):
def extend_atom(self, feed): def extend_atom(self, feed):
'''Create an ATOM feed xml structure containing all previously set '''Extend an ATOM feed xml structure containing all previously set
fields. fields.
:param feed: The feed xml root element. :param feed: The feed xml root element.

View file

@ -42,6 +42,8 @@ class DcBaseExtension(BaseExtension):
self._dcelem_title = None self._dcelem_title = None
self._dcelem_type = None self._dcelem_type = None
def extend_ns(self):
return {'dc' : 'http://purl.org/dc/elements/1.1/'}
def extend_atom(self, atom_feed): def extend_atom(self, atom_feed):
'''Create an Atom feed xml structure containing all previously set fields. '''Create an Atom feed xml structure containing all previously set fields.
@ -49,14 +51,8 @@ class DcBaseExtension(BaseExtension):
:returns: The feed root element :returns: The feed root element
''' '''
DCELEMENTS_NS = 'http://purl.org/dc/elements/1.1/' DCELEMENTS_NS = 'http://purl.org/dc/elements/1.1/'
# Replace the root element to add the new namespace
nsmap = atom_feed.nsmap feed = atom_feed
nsmap['dc'] = DCELEMENTS_NS
feed = etree.Element('feed', nsmap=nsmap)
if '{http://www.w3.org/XML/1998/namespace}lang' in atom_feed.attrib:
feed.attrib['{http://www.w3.org/XML/1998/namespace}lang'] = \
atom_feed.attrib['{http://www.w3.org/XML/1998/namespace}lang']
feed[:] = atom_feed[:]
for elem in ['contributor', 'coverage', 'creator', 'date', 'description', for elem in ['contributor', 'coverage', 'creator', 'date', 'description',
'language', 'publisher', 'relation', 'rights', 'source', 'subject', 'language', 'publisher', 'relation', 'rights', 'source', 'subject',
@ -83,12 +79,7 @@ class DcBaseExtension(BaseExtension):
:returns: Tuple containing the feed root element and the element tree. :returns: Tuple containing the feed root element and the element tree.
''' '''
DCELEMENTS_NS = 'http://purl.org/dc/elements/1.1/' DCELEMENTS_NS = 'http://purl.org/dc/elements/1.1/'
# Replace the root element to add the new namespace channel = rss_feed[0]
nsmap = rss_feed.nsmap
nsmap['dc'] = DCELEMENTS_NS
feed = etree.Element('rss', version='2.0', nsmap=nsmap )
feed[:] = rss_feed[:]
channel = feed[0]
for elem in ['contributor', 'coverage', 'creator', 'date', 'description', for elem in ['contributor', 'coverage', 'creator', 'date', 'description',
'language', 'publisher', 'relation', 'rights', 'source', 'subject', 'language', 'publisher', 'relation', 'rights', 'source', 'subject',
@ -106,7 +97,7 @@ class DcBaseExtension(BaseExtension):
node = etree.SubElement(channel, '{%s}identifier' % DCELEMENTS_NS) node = etree.SubElement(channel, '{%s}identifier' % DCELEMENTS_NS)
node.text = identifier node.text = identifier
return feed return rss_feed
def dc_contributor(self, contributor=None, replace=False): def dc_contributor(self, contributor=None, replace=False):

View file

@ -34,6 +34,8 @@ class PodcastExtension(BaseExtension):
self.__itunes_summary = None self.__itunes_summary = None
def extend_ns(self):
return {'itunes' : 'http://www.itunes.com/dtds/podcast-1.0.dtd'}
def extend_rss(self, rss_feed): def extend_rss(self, rss_feed):
@ -42,11 +44,7 @@ class PodcastExtension(BaseExtension):
:returns: Tuple containing the feed root element and the element tree. :returns: Tuple containing the feed root element and the element tree.
''' '''
ITUNES_NS = 'http://www.itunes.com/dtds/podcast-1.0.dtd' ITUNES_NS = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
# Replace the root element to add the itunes namespace feed = rss_feed
nsmap = rss_feed.nsmap
nsmap['itunes'] = ITUNES_NS
feed = etree.Element('rss', version='2.0', nsmap=nsmap )
feed[:] = rss_feed[:]
channel = feed[0] channel = feed[0]
if self.__itunes_author: if self.__itunes_author:

View file

@ -88,7 +88,13 @@ class FeedGenerator(object):
:returns: Tuple containing the feed root element and the element tree. :returns: Tuple containing the feed root element and the element tree.
''' '''
feed = etree.Element('feed', xmlns='http://www.w3.org/2005/Atom') nsmap = dict()
if extensions:
for ext in self.__extensions.values() or []:
if ext.get('atom'):
nsmap.update( ext['inst'].extend_ns() )
feed = etree.Element('feed', xmlns='http://www.w3.org/2005/Atom', nsmap=nsmap)
if self.__atom_feed_xml_lang: if self.__atom_feed_xml_lang:
feed.attrib['{http://www.w3.org/XML/1998/namespace}lang'] = \ feed.attrib['{http://www.w3.org/XML/1998/namespace}lang'] = \
self.__atom_feed_xml_lang self.__atom_feed_xml_lang
@ -182,10 +188,11 @@ class FeedGenerator(object):
if extensions: if extensions:
for ext in self.__extensions.values() or []: for ext in self.__extensions.values() or []:
if ext.get('atom'): if ext.get('atom'):
feed = ext['inst'].extend_atom(feed) ext['inst'].extend_atom(feed)
for entry in self.__feed_entries: for entry in self.__feed_entries:
entry.atom_entry(feed) entry = entry.atom_entry()
feed.append(entry)
doc = etree.ElementTree(feed) doc = etree.ElementTree(feed)
return feed, doc return feed, doc
@ -220,9 +227,16 @@ class FeedGenerator(object):
:returns: Tuple containing the feed root element and the element tree. :returns: Tuple containing the feed root element and the element tree.
''' '''
feed = etree.Element('rss', version='2.0', nsmap = dict()
nsmap={'atom': 'http://www.w3.org/2005/Atom', if extensions:
'content': 'http://purl.org/rss/1.0/modules/content/'} ) for ext in self.__extensions.values() or []:
if ext.get('rss'):
nsmap.update( ext['inst'].extend_ns() )
nsmap.update({'atom': 'http://www.w3.org/2005/Atom',
'content': 'http://purl.org/rss/1.0/modules/content/'})
feed = etree.Element('rss', version='2.0', nsmap=nsmap )
channel = etree.SubElement(feed, 'channel') channel = etree.SubElement(feed, 'channel')
if not ( self.__rss_title and self.__rss_link and self.__rss_description ): if not ( self.__rss_title and self.__rss_link and self.__rss_description ):
missing = ', '.join(([] if self.__rss_title else ['title']) + \ missing = ', '.join(([] if self.__rss_title else ['title']) + \
@ -335,10 +349,11 @@ class FeedGenerator(object):
if extensions: if extensions:
for ext in self.__extensions.values() or []: for ext in self.__extensions.values() or []:
if ext.get('rss'): if ext.get('rss'):
feed = ext['inst'].extend_rss(feed) ext['inst'].extend_rss(feed)
for entry in self.__feed_entries: for entry in self.__feed_entries:
entry.rss_entry(channel) item = entry.rss_entry()
channel.append(item)
doc = etree.ElementTree(feed) doc = etree.ElementTree(feed)
return feed, doc return feed, doc