web/views/xmlrss.py
branchtls-sprint
changeset 824 a5e6acffde30
child 1091 b5e253c0dd13
equal deleted inserted replaced
823:cb8ccbef8fa5 824:a5e6acffde30
       
     1 """base xml and rss views
       
     2 
       
     3 
       
     4 :organization: Logilab
       
     5 :copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
       
     6 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
       
     7 """
       
     8 __docformat__ = "restructuredtext en"
       
     9 
       
    10 from time import timezone
       
    11 
       
    12 from logilab.mtconverter import xml_escape
       
    13 
       
    14 from cubicweb.view import EntityView, AnyRsetView
       
    15 from cubicweb.web.httpcache import MaxAgeHTTPCacheManager
       
    16 from cubicweb.common.uilib import simple_sgml_tag
       
    17 
       
    18 
       
    19 class XmlView(EntityView):
       
    20     """xml view for entities"""
       
    21     id = 'xml'
       
    22     title = _('xml')
       
    23     templatable = False
       
    24     content_type = 'text/xml'
       
    25     xml_root = 'rset'
       
    26     item_vid = 'xmlitem'
       
    27     
       
    28     def cell_call(self, row, col):
       
    29         self.wview(self.item_vid, self.rset, row=row, col=col)
       
    30         
       
    31     def call(self):
       
    32         """display a list of entities by calling their <item_vid> view"""
       
    33         self.w(u'<?xml version="1.0" encoding="%s"?>\n' % self.req.encoding)
       
    34         self.w(u'<%s size="%s">\n' % (self.xml_root, len(self.rset)))
       
    35         for i in xrange(self.rset.rowcount):
       
    36             self.cell_call(i, 0)
       
    37         self.w(u'</%s>\n' % self.xml_root)
       
    38 
       
    39 
       
    40 class XmlItemView(EntityView):
       
    41     id = 'xmlitem'
       
    42 
       
    43     def cell_call(self, row, col):
       
    44         """ element as an item for an xml feed """
       
    45         entity = self.complete_entity(row, col)
       
    46         self.w(u'<%s>\n' % (entity.e_schema))
       
    47         for rschema, attrschema in entity.e_schema.attribute_definitions():
       
    48             attr = rschema.type
       
    49             try:
       
    50                 value = entity[attr]
       
    51             except KeyError:
       
    52                 # Bytes
       
    53                 continue
       
    54             if value is not None:
       
    55                 if attrschema == 'Bytes':
       
    56                     from base64 import b64encode
       
    57                     value = '<![CDATA[%s]]>' % b64encode(value.getvalue())
       
    58                 elif isinstance(value, basestring):
       
    59                     value = xml_escape(value)
       
    60                 self.w(u'  <%s>%s</%s>\n' % (attr, value, attr))
       
    61         self.w(u'</%s>\n' % (entity.e_schema))
       
    62 
       
    63 
       
    64     
       
    65 class XmlRsetView(AnyRsetView):
       
    66     """dumps raw rset as xml"""
       
    67     id = 'rsetxml'
       
    68     title = _('xml export')
       
    69     templatable = False
       
    70     content_type = 'text/xml'
       
    71     xml_root = 'rset'
       
    72         
       
    73     def call(self):
       
    74         w = self.w
       
    75         rset, descr = self.rset, self.rset.description
       
    76         eschema = self.schema.eschema
       
    77         labels = self.columns_labels(False)
       
    78         w(u'<?xml version="1.0" encoding="%s"?>\n' % self.req.encoding)
       
    79         w(u'<%s query="%s">\n' % (self.xml_root, xml_escape(rset.printable_rql())))
       
    80         for rowindex, row in enumerate(self.rset):
       
    81             w(u' <row>\n')
       
    82             for colindex, val in enumerate(row):
       
    83                 etype = descr[rowindex][colindex]
       
    84                 tag = labels[colindex]
       
    85                 attrs = {}
       
    86                 if '(' in tag:
       
    87                     attrs['expr'] = tag
       
    88                     tag = 'funccall'
       
    89                 if val is not None and not eschema(etype).is_final():
       
    90                     attrs['eid'] = val
       
    91                     # csvrow.append(val) # val is eid in that case
       
    92                     val = self.view('textincontext', rset,
       
    93                                     row=rowindex, col=colindex)
       
    94                 else:
       
    95                     val = self.view('final', rset, displaytime=True,
       
    96                                     row=rowindex, col=colindex, format='text/plain')
       
    97                 w(simple_sgml_tag(tag, val, **attrs))
       
    98             w(u' </row>\n')
       
    99         w(u'</%s>\n' % self.xml_root)
       
   100     
       
   101 
       
   102 class RssView(XmlView):
       
   103     id = 'rss'
       
   104     title = _('rss')
       
   105     templatable = False
       
   106     content_type = 'text/xml'
       
   107     http_cache_manager = MaxAgeHTTPCacheManager
       
   108     cache_max_age = 60*60*2 # stay in http cache for 2 hours by default 
       
   109     
       
   110     def cell_call(self, row, col):
       
   111         self.wview('rssitem', self.rset, row=row, col=col)
       
   112         
       
   113     def call(self):
       
   114         """display a list of entities by calling their <item_vid> view"""
       
   115         req = self.req
       
   116         self.w(u'<?xml version="1.0" encoding="%s"?>\n' % req.encoding)
       
   117         self.w(u'''<rdf:RDF
       
   118  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
       
   119  xmlns:dc="http://purl.org/dc/elements/1.1/"
       
   120  xmlns="http://purl.org/rss/1.0/"
       
   121 >''')
       
   122         self.w(u'  <channel rdf:about="%s">\n' % xml_escape(req.url()))
       
   123         self.w(u'    <title>%s RSS Feed</title>\n' % xml_escape(self.page_title()))
       
   124         self.w(u'    <description>%s</description>\n' % xml_escape(req.form.get('vtitle', '')))
       
   125         params = req.form.copy()
       
   126         params.pop('vid', None)
       
   127         self.w(u'    <link>%s</link>\n' % xml_escape(self.build_url(**params)))
       
   128         self.w(u'    <items>\n')
       
   129         self.w(u'      <rdf:Seq>\n')
       
   130         for entity in self.rset.entities():
       
   131             self.w(u'      <rdf:li resource="%s" />\n' % xml_escape(entity.absolute_url()))
       
   132         self.w(u'      </rdf:Seq>\n')
       
   133         self.w(u'    </items>\n')
       
   134         self.w(u'  </channel>\n')
       
   135         for i in xrange(self.rset.rowcount):
       
   136             self.cell_call(i, 0)
       
   137         self.w(u'</rdf:RDF>')
       
   138 
       
   139 
       
   140 class RssItemView(EntityView):
       
   141     id = 'rssitem'
       
   142     date_format = '%%Y-%%m-%%dT%%H:%%M%+03i:00' % (timezone / 3600)
       
   143 
       
   144     def cell_call(self, row, col):
       
   145         entity = self.complete_entity(row, col)
       
   146         self.w(u'<item rdf:about="%s">\n' % xml_escape(entity.absolute_url()))
       
   147         self._marker('title', entity.dc_long_title())
       
   148         self._marker('link', entity.absolute_url())
       
   149         self._marker('description', entity.dc_description())
       
   150         self._marker('dc:date', entity.dc_date(self.date_format))
       
   151         if entity.creator:
       
   152             self.w(u'<author>')
       
   153             self._marker('name', entity.creator.name())
       
   154             email = entity.creator.get_email()
       
   155             if email:
       
   156                 self._marker('email', email)
       
   157             self.w(u'</author>')
       
   158         self.w(u'</item>\n')
       
   159         
       
   160     def _marker(self, marker, value):
       
   161         if value:
       
   162             self.w(u'  <%s>%s</%s>\n' % (marker, xml_escape(value), marker))