def extend_atom(self, entry): '''Add additional fields to an RSS item. :param feed: The RSS item XML element to use. ''' groups = {None: entry} for media_content in self.__media_content: # Define current media:group group = groups.get(media_content.get('group')) if group is None: group = xml_elem('{%s}group' % MEDIA_NS, entry) groups[media_content.get('group')] = group # Add content content = xml_elem('{%s}content' % MEDIA_NS, group) for attr in ('url', 'fileSize', 'type', 'medium', 'isDefault', 'expression', 'bitrate', 'framerate', 'samplingrate', 'channels', 'duration', 'height', 'width', 'lang'): if media_content.get(attr): content.set(attr, media_content[attr]) for media_thumbnail in self.__media_thumbnail: # Define current media:group group = groups.get(media_thumbnail.get('group')) if group is None: group = xml_elem('{%s}group' % MEDIA_NS, entry) groups[media_thumbnail.get('group')] = group # Add thumbnails thumbnail = xml_elem('{%s}thumbnail' % MEDIA_NS, group) for attr in ('url', 'height', 'width', 'time'): if media_thumbnail.get(attr): thumbnail.set(attr, media_thumbnail[attr]) return entry
def extend_file(self, entry): '''Add additional fields to an RSS item. :param feed: The RSS item XML element to use. ''' GEO_NS = 'http://www.georss.org/georss' if self.__point: point = xml_elem('{%s}point' % GEO_NS, entry) point.text = self.__point if self.__line: line = xml_elem('{%s}line' % GEO_NS, entry) line.text = self.__line if self.__polygon: polygon = xml_elem('{%s}polygon' % GEO_NS, entry) polygon.text = self.__polygon if self.__box: box = xml_elem('{%s}box' % GEO_NS, entry) box.text = self.__box if self.__featuretypetag: featuretypetag = xml_elem('{%s}featuretypetag' % GEO_NS, entry) featuretypetag.text = self.__featuretypetag if self.__relationshiptag: relationshiptag = xml_elem('{%s}relationshiptag' % GEO_NS, entry) relationshiptag.text = self.__relationshiptag if self.__featurename: featurename = xml_elem('{%s}featurename' % GEO_NS, entry) featurename.text = self.__featurename if self.__elev: elevation = xml_elem('{%s}elev' % GEO_NS, entry) elevation.text = str(self.__elev) if self.__floor: floor = xml_elem('{%s}floor' % GEO_NS, entry) floor.text = str(self.__floor) if self.__radius: radius = xml_elem('{%s}radius' % GEO_NS, entry) radius.text = str(self.__radius) return entry
def _add_text_elm(entry, data, name): """Add a text subelement to an entry""" if not data: return elm = xml_elem(name, entry) type_ = data.get('type') if data.get('src'): if name != 'content': raise ValueError("Only the 'content' element of an entry can " "contain a 'src' attribute") elm.attrib['src'] = data['src'] elif data.get(name): # Surround xhtml with a div tag, parse it and embed it if type_ == 'xhtml': xhtml = '<div xmlns="http://www.w3.org/1999/xhtml">' \ + data.get(name) + '</div>' elm.append(xml_fromstring(xhtml)) elif type_ == 'CDATA': elm.text = CDATA(data.get(name)) # Parse XML and embed it elif type_ and (type_.endswith('/xml') or type_.endswith('+xml')): elm.append(xml_fromstring(data[name])) # Embed the text in escaped form elif not type_ or type_.startswith('text') or type_ == 'html': elm.text = data.get(name) # Everything else should be included base64 encoded else: raise NotImplementedError( 'base64 encoded {} is not supported at the moment. ' 'Pull requests adding support are welcome.'.format(name) ) # Add type description of the content if type_: elm.attrib['type'] = type_
def extend_rss(self, entry): '''Add additional fields to an RSS item. :param feed: The RSS item XML element to use. ''' if self.__torrent_filename: filename = xml_elem('{%s}filename' % TORRENT_NS, entry) filename.text = self.__torrent_filename if self.__torrent_contentlength: contentlength = xml_elem('{%s}contentlength' % TORRENT_NS, entry) contentlength.text = self.__torrent_contentlength if self.__torrent_infohash: infohash = xml_elem('{%s}infohash' % TORRENT_NS, entry) infohash.text = self.__torrent_infohash magnet = xml_elem('{%s}magneturi' % TORRENT_NS, entry) magnet.text = 'magnet:?xt=urn:btih:' + self.__torrent_infohash if self.__torrent_seeds: seeds = xml_elem('{%s}seed' % TORRENT_NS, entry) seeds.text = self.__torrent_seeds if self.__torrent_peers: peers = xml_elem('{%s}peers' % TORRENT_NS, entry) peers.text = self.__torrent_peers if self.__torrent_verified: verified = xml_elem('{%s}verified' % TORRENT_NS, entry) verified.text = self.__torrent_verified
def extend_rss(self, entry): '''Add additional fields to an RSS item. :param feed: The RSS item XML element to use. ''' ITUNES_NS = 'http://www.itunes.com/dtds/podcast-1.0.dtd' if self.__itunes_author: author = xml_elem('{%s}author' % ITUNES_NS, entry) author.text = self.__itunes_author if self.__itunes_block is not None: block = xml_elem('{%s}block' % ITUNES_NS, entry) block.text = 'yes' if self.__itunes_block else 'no' if self.__itunes_image: image = xml_elem('{%s}image' % ITUNES_NS, entry) image.attrib['href'] = self.__itunes_image if self.__itunes_duration: duration = xml_elem('{%s}duration' % ITUNES_NS, entry) duration.text = self.__itunes_duration if self.__itunes_explicit in ('yes', 'no', 'clean'): explicit = xml_elem('{%s}explicit' % ITUNES_NS, entry) explicit.text = self.__itunes_explicit if self.__itunes_is_closed_captioned is not None: is_closed_captioned = xml_elem('{%s}isClosedCaptioned' % ITUNES_NS, entry) if self.__itunes_is_closed_captioned: is_closed_captioned.text = 'yes' else: is_closed_captioned.text = 'no' if self.__itunes_order is not None and self.__itunes_order >= 0: order = xml_elem('{%s}order' % ITUNES_NS, entry) order.text = str(self.__itunes_order) if self.__itunes_subtitle: subtitle = xml_elem('{%s}subtitle' % ITUNES_NS, entry) subtitle.text = self.__itunes_subtitle if self.__itunes_summary: summary = xml_elem('{%s}summary' % ITUNES_NS, entry) summary.text = self.__itunes_summary return entry
def _extend_xml(self, xml_element): '''Extend xml_element with set DC fields. :param xml_element: etree element ''' DCELEMENTS_NS = 'http://purl.org/dc/elements/1.1/' for elem in ['contributor', 'coverage', 'creator', 'date', 'description', 'language', 'publisher', 'relation', 'rights', 'source', 'subject', 'title', 'type', 'format', 'identifier']: if hasattr(self, '_dcelem_%s' % elem): for val in getattr(self, '_dcelem_%s' % elem) or []: node = xml_elem('{%s}%s' % (DCELEMENTS_NS, elem), xml_element) node.text = val
def _set_value(channel, name, value): if value: newelem = xml_elem('{%s}' % SYNDICATION_NS + name, channel) newelem.text = value
def _create_atom(self, extensions=True): '''Create a ATOM feed xml structure containing all previously set fields. :returns: Tuple containing the feed root element and the element tree. ''' nsmap = dict() if extensions: for ext in self.__extensions.values() or []: if ext.get('atom'): nsmap.update(ext['inst'].extend_ns()) feed = xml_elem('feed', xmlns='http://www.w3.org/2005/Atom', nsmap=nsmap) if self.__atom_feed_xml_lang: feed.attrib['{http://www.w3.org/XML/1998/namespace}lang'] = \ self.__atom_feed_xml_lang if not (self.__atom_id and self.__atom_title and self.__atom_updated): missing = ([] if self.__atom_title else ['title']) + \ ([] if self.__atom_id else ['id']) + \ ([] if self.__atom_updated else ['updated']) missing = ', '.join(missing) raise ValueError('Required fields not set (%s)' % missing) id = xml_elem('id', feed) id.text = self.__atom_id title = xml_elem('title', feed) title.text = self.__atom_title updated = xml_elem('updated', feed) updated.text = self.__atom_updated.isoformat() # Add author elements for a in self.__atom_author or []: # Atom requires a name. Skip elements without. if not a.get('name'): continue author = xml_elem('author', feed) name = xml_elem('name', author) name.text = a.get('name') if a.get('email'): email = xml_elem('email', author) email.text = a.get('email') if a.get('uri'): uri = xml_elem('uri', author) uri.text = a.get('uri') for l in self.__atom_link or []: link = xml_elem('link', feed, href=l['href']) if l.get('rel'): link.attrib['rel'] = l['rel'] if l.get('type'): link.attrib['type'] = l['type'] if l.get('hreflang'): link.attrib['hreflang'] = l['hreflang'] if l.get('title'): link.attrib['title'] = l['title'] if l.get('length'): link.attrib['length'] = l['length'] for c in self.__atom_category or []: cat = xml_elem('category', feed, term=c['term']) if c.get('scheme'): cat.attrib['scheme'] = c['scheme'] if c.get('label'): cat.attrib['label'] = c['label'] # Add author elements for c in self.__atom_contributor or []: # Atom requires a name. Skip elements without. if not c.get('name'): continue contrib = xml_elem('contributor', feed) name = xml_elem('name', contrib) name.text = c.get('name') if c.get('email'): email = xml_elem('email', contrib) email.text = c.get('email') if c.get('uri'): uri = xml_elem('uri', contrib) uri.text = c.get('uri') if self.__atom_generator and self.__atom_generator.get('value'): generator = xml_elem('generator', feed) generator.text = self.__atom_generator['value'] if self.__atom_generator.get('uri'): generator.attrib['uri'] = self.__atom_generator['uri'] if self.__atom_generator.get('version'): generator.attrib['version'] = self.__atom_generator['version'] if self.__atom_icon: icon = xml_elem('icon', feed) icon.text = self.__atom_icon if self.__atom_logo: logo = xml_elem('logo', feed) logo.text = self.__atom_logo if self.__atom_rights: rights = xml_elem('rights', feed) rights.text = self.__atom_rights if self.__atom_subtitle: subtitle = xml_elem('subtitle', feed) subtitle.text = self.__atom_subtitle if extensions: for ext in self.__extensions.values() or []: if ext.get('atom'): ext['inst'].extend_atom(feed) for entry in self.__feed_entries: entry = entry.atom_entry() feed.append(entry) doc = etree.ElementTree(feed) return feed, doc
def _create_rss(self, extensions=True): '''Create an RSS feed xml structure containing all previously set fields. :returns: Tuple containing the feed root element and the element tree. ''' nsmap = dict() if extensions: 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 = xml_elem('rss', version='2.0', nsmap=nsmap) channel = xml_elem('channel', feed) if not (self.__rss_title and self.__rss_link and self.__rss_description): missing = ([] if self.__rss_title else ['title']) + \ ([] if self.__rss_link else ['link']) + \ ([] if self.__rss_description else ['description']) missing = ', '.join(missing) raise ValueError('Required fields not set (%s)' % missing) title = xml_elem('title', channel) title.text = self.__rss_title link = xml_elem('link', channel) link.text = self.__rss_link desc = xml_elem('description', channel) desc.text = self.__rss_description for ln in self.__atom_link or []: # It is recommended to include a atom self link in rss documents… if ln.get('rel') == 'self': selflink = xml_elem('{http://www.w3.org/2005/Atom}link', channel, href=ln['href'], rel='self') if ln.get('type'): selflink.attrib['type'] = ln['type'] if ln.get('hreflang'): selflink.attrib['hreflang'] = ln['hreflang'] if ln.get('title'): selflink.attrib['title'] = ln['title'] if ln.get('length'): selflink.attrib['length'] = ln['length'] break if self.__rss_category: for cat in self.__rss_category: category = xml_elem('category', channel) category.text = cat['value'] if cat.get('domain'): category.attrib['domain'] = cat['domain'] if self.__rss_cloud: cloud = xml_elem('cloud', channel) cloud.attrib['domain'] = self.__rss_cloud.get('domain') cloud.attrib['port'] = self.__rss_cloud.get('port') cloud.attrib['path'] = self.__rss_cloud.get('path') cloud.attrib['registerProcedure'] = self.__rss_cloud.get( 'registerProcedure') cloud.attrib['protocol'] = self.__rss_cloud.get('protocol') if self.__rss_copyright: copyright = xml_elem('copyright', channel) copyright.text = self.__rss_copyright if self.__rss_docs: docs = xml_elem('docs', channel) docs.text = self.__rss_docs if self.__rss_generator: generator = xml_elem('generator', channel) generator.text = self.__rss_generator if self.__rss_image: image = xml_elem('image', channel) url = xml_elem('url', image) url.text = self.__rss_image.get('url') title = xml_elem('title', image) title.text = self.__rss_image.get('title', self.__rss_title) link = xml_elem('link', image) link.text = self.__rss_image.get('link', self.__rss_link) if self.__rss_image.get('width'): width = xml_elem('width', image) width.text = self.__rss_image.get('width') if self.__rss_image.get('height'): height = xml_elem('height', image) height.text = self.__rss_image.get('height') if self.__rss_image.get('description'): description = xml_elem('description', image) description.text = self.__rss_image.get('description') if self.__rss_language: language = xml_elem('language', channel) language.text = self.__rss_language if self.__rss_lastBuildDate: lastBuildDate = xml_elem('lastBuildDate', channel) lastBuildDate.text = formatRFC2822(self.__rss_lastBuildDate) if self.__rss_managingEditor: managingEditor = xml_elem('managingEditor', channel) managingEditor.text = self.__rss_managingEditor if self.__rss_pubDate: pubDate = xml_elem('pubDate', channel) pubDate.text = formatRFC2822(self.__rss_pubDate) if self.__rss_rating: rating = xml_elem('rating', channel) rating.text = self.__rss_rating if self.__rss_skipHours: skipHours = xml_elem('skipHours', channel) for h in self.__rss_skipHours: hour = xml_elem('hour', skipHours) hour.text = str(h) if self.__rss_skipDays: skipDays = xml_elem('skipDays', channel) for d in self.__rss_skipDays: day = xml_elem('day', skipDays) day.text = d if self.__rss_textInput: textInput = xml_elem('textInput', channel) textInput.attrib['title'] = self.__rss_textInput.get('title') textInput.attrib['description'] = \ self.__rss_textInput.get('description') textInput.attrib['name'] = self.__rss_textInput.get('name') textInput.attrib['link'] = self.__rss_textInput.get('link') if self.__rss_ttl: ttl = xml_elem('ttl', channel) ttl.text = str(self.__rss_ttl) if self.__rss_webMaster: webMaster = xml_elem('webMaster', channel) webMaster.text = self.__rss_webMaster if extensions: for ext in self.__extensions.values() or []: if ext.get('rss'): ext['inst'].extend_rss(feed) for entry in self.__feed_entries: item = entry.rss_entry() channel.append(item) doc = etree.ElementTree(feed) return feed, doc
def extend_rss(self, rss_feed): '''Extend an RSS feed root with set itunes fields. :returns: The feed root element. ''' ITUNES_NS = 'http://www.itunes.com/dtds/podcast-1.0.dtd' channel = rss_feed[0] if self.__itunes_author: author = xml_elem('{%s}author' % ITUNES_NS, channel) author.text = self.__itunes_author if self.__itunes_block is not None: block = xml_elem('{%s}block' % ITUNES_NS, channel) block.text = 'yes' if self.__itunes_block else 'no' for c in self.__itunes_category or []: if not c.get('cat'): continue category = channel.find( '{%s}category[@text="%s"]' % (ITUNES_NS, c.get('cat'))) if category is None: category = xml_elem('{%s}category' % ITUNES_NS, channel) category.attrib['text'] = c.get('cat') if c.get('sub'): subcategory = xml_elem('{%s}category' % ITUNES_NS, category) subcategory.attrib['text'] = c.get('sub') if self.__itunes_image: image = xml_elem('{%s}image' % ITUNES_NS, channel) image.attrib['href'] = self.__itunes_image if self.__itunes_explicit in ('yes', 'no', 'clean'): explicit = xml_elem('{%s}explicit' % ITUNES_NS, channel) explicit.text = self.__itunes_explicit if self.__itunes_complete in ('yes', 'no'): complete = xml_elem('{%s}complete' % ITUNES_NS, channel) complete.text = self.__itunes_complete if self.__itunes_new_feed_url: new_feed_url = xml_elem('{%s}new-feed-url' % ITUNES_NS, channel) new_feed_url.text = self.__itunes_new_feed_url if self.__itunes_owner: owner = xml_elem('{%s}owner' % ITUNES_NS, channel) owner_name = xml_elem('{%s}name' % ITUNES_NS, owner) owner_name.text = self.__itunes_owner.get('name') owner_email = xml_elem('{%s}email' % ITUNES_NS, owner) owner_email.text = self.__itunes_owner.get('email') if self.__itunes_subtitle: subtitle = xml_elem('{%s}subtitle' % ITUNES_NS, channel) subtitle.text = self.__itunes_subtitle if self.__itunes_summary: summary = xml_elem('{%s}summary' % ITUNES_NS, channel) summary.text = self.__itunes_summary if self.__itunes_type in ('episodic', 'serial'): type = xml_elem('{%s}type' % ITUNES_NS, channel) type.text = self.__itunes_type return rss_feed
def rss_entry(self, extensions=True): '''Create a RSS item and return it.''' entry = xml_elem('item') if not (self.__rss_title or self.__rss_description or self.__rss_content): raise ValueError('Required fields not set') if self.__rss_title: title = xml_elem('title', entry) title.text = self.__rss_title if self.__rss_link: link = xml_elem('link', entry) link.text = self.__rss_link if self.__rss_description and self.__rss_content: description = xml_elem('description', entry) description.text = self.__rss_description XMLNS_CONTENT = 'http://purl.org/rss/1.0/modules/content/' content = xml_elem('{%s}encoded' % XMLNS_CONTENT, entry) content.text = CDATA(self.__rss_content['content']) \ if self.__rss_content.get('type', '') == 'CDATA' \ else self.__rss_content['content'] elif self.__rss_description: description = xml_elem('description', entry) description.text = self.__rss_description elif self.__rss_content: description = xml_elem('description', entry) description.text = CDATA(self.__rss_content['content']) \ if self.__rss_content.get('type', '') == 'CDATA' \ else self.__rss_content['content'] for a in self.__rss_author or []: author = xml_elem('author', entry) author.text = a if self.__rss_guid.get('guid'): guid = xml_elem('guid', entry) guid.text = self.__rss_guid['guid'] permaLink = str(self.__rss_guid.get('permalink', False)).lower() guid.attrib['isPermaLink'] = permaLink for cat in self.__rss_category or []: category = xml_elem('category', entry) category.text = cat['value'] if cat.get('domain'): category.attrib['domain'] = cat['domain'] if self.__rss_comments: comments = xml_elem('comments', entry) comments.text = self.__rss_comments if self.__rss_enclosure: enclosure = xml_elem('enclosure', entry) enclosure.attrib['url'] = self.__rss_enclosure['url'] enclosure.attrib['length'] = self.__rss_enclosure['length'] enclosure.attrib['type'] = self.__rss_enclosure['type'] if self.__rss_pubDate: pubDate = xml_elem('pubDate', entry) pubDate.text = formatRFC2822(self.__rss_pubDate) if self.__rss_source: source = xml_elem('source', entry, url=self.__rss_source['url']) source.text = self.__rss_source['title'] if extensions: for ext in self.__extensions.values() or []: if ext.get('rss'): ext['inst'].extend_rss(entry) return entry
def atom_entry(self, extensions=True): '''Create an ATOM entry and return it.''' entry = xml_elem('entry') if not (self.__atom_id and self.__atom_title and self.__atom_updated): raise ValueError('Required fields not set') id = xml_elem('id', entry) id.text = self.__atom_id title = xml_elem('title', entry) title.text = self.__atom_title updated = xml_elem('updated', entry) updated.text = self.__atom_updated.isoformat() # An entry must contain an alternate link if there is no content # element. if not self.__atom_content: links = self.__atom_link or [] if not [l for l in links if l.get('rel') == 'alternate']: raise ValueError('Entry must contain an alternate link or ' + 'a content element.') # Add author elements for a in self.__atom_author or []: # Atom requires a name. Skip elements without. if not a.get('name'): continue author = xml_elem('author', entry) name = xml_elem('name', author) name.text = a.get('name') if a.get('email'): email = xml_elem('email', author) email.text = a.get('email') if a.get('uri'): uri = xml_elem('uri', author) uri.text = a.get('uri') _add_text_elm(entry, self.__atom_content, 'content') for l in self.__atom_link or []: link = xml_elem('link', entry, href=l['href']) if l.get('rel'): link.attrib['rel'] = l['rel'] if l.get('type'): link.attrib['type'] = l['type'] if l.get('hreflang'): link.attrib['hreflang'] = l['hreflang'] if l.get('title'): link.attrib['title'] = l['title'] if l.get('length'): link.attrib['length'] = l['length'] _add_text_elm(entry, self.__atom_summary, 'summary') for c in self.__atom_category or []: cat = xml_elem('category', entry, term=c['term']) if c.get('scheme'): cat.attrib['scheme'] = c['scheme'] if c.get('label'): cat.attrib['label'] = c['label'] # Add author elements for c in self.__atom_contributor or []: # Atom requires a name. Skip elements without. if not c.get('name'): continue contrib = xml_elem('contributor', entry) name = xml_elem('name', contrib) name.text = c.get('name') if c.get('email'): email = xml_elem('email', contrib) email.text = c.get('email') if c.get('uri'): uri = xml_elem('uri', contrib) uri.text = c.get('uri') if self.__atom_published: published = xml_elem('published', entry) published.text = self.__atom_published.isoformat() if self.__atom_rights: rights = xml_elem('rights', entry) rights.text = self.__atom_rights if self.__atom_source: source = xml_elem('source', entry) if self.__atom_source.get('title'): source_title = xml_elem('title', source) source_title.text = self.__atom_source['title'] if self.__atom_source.get('link'): xml_elem('link', source, href=self.__atom_source['link']) if extensions: for ext in self.__extensions.values() or []: if ext.get('atom'): ext['inst'].extend_atom(entry) return entry