Changeset 3348

Show
Ignore:
Timestamp:
03/12/08 09:30:10 (9 months ago)
Author:
coling
Message:

Convert the XML/XSLT processing to use python-lxml as it seems altogether more reliable with Unicode data.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • clientsplugin/0.11/cron/changes.xslt

    r2716 r3348  
    77  <xsl:output method="html" indent="yes" encoding="UTF-8" omit-xml-declaration="yes"/> 
    88  <xsl:decimal-format name="GBP" decimal-separator="." grouping-separator=","/> 
    9    
    10   <xsl:param name="view" /> 
    119   
    1210  <!-- Match the root of the XML render the three views --> 
  • clientsplugin/0.11/cron/send-client-email

    r2839 r3348  
    3434import locale 
    3535import time 
    36 import libxml2 
    37 import libxslt 
     36from lxml import etree 
     37import codecs 
    3838from datetime import datetime 
    3939from optparse import OptionParser 
     
    4646from trac.wiki import wiki_to_html 
    4747from genshi import escape 
     48 
    4849 
    4950parser = OptionParser() 
     
    7273    self.encoding = 'us-ascii' 
    7374   
    74   def Send(self, subject, addresses, info, formatter): 
     75  def Send(self, subject, addresses, xml, transform): 
    7576    if not self.config.getbool('notification', 'smtp_enabled'): 
    7677      return 
     
    112113     
    113114    view = 'plain' 
    114     result = formatter.applyStylesheet(info, {'view': '"%s"' % view }) 
    115     msg_text = MIMEText(formatter.saveResultToString(result), view, self.encoding) 
     115    arg = "'%s'" % view 
     116    result = transform(xml, view=arg) 
     117    msg_text = MIMEText(str(result), view, self.encoding) 
    116118    msg_root.attach(msg_text) 
    117     result.freeDoc() 
    118119     
    119120    msg_related = MIMEMultipart('related') 
     
    121122     
    122123    view = 'html' 
    123     result = formatter.applyStylesheet(info, {'view': '"%s"' % view }) 
    124     msg_text = MIMEText(formatter.saveResultToString(result), view, self.encoding) 
     124    arg = "'%s'" % view 
     125    result = transform(xml, view=arg) 
     126    msg_text = MIMEText(str(result), view, self.encoding) 
    125127    msg_related.attach(msg_text) 
    126     result.freeDoc() 
    127128     
    128129    # Handle image embedding... 
    129130    view = 'images' 
    130     result = formatter.applyStylesheet(info, {'view': '"%s"' % view }) 
    131     if result and result.children and result.children.children: 
    132       for img in result.children.children: 
    133         if 'img' != img.name: 
     131    arg = "'%s'" % view 
     132    result = transform(xml, view=arg) 
     133    if result: 
     134      for img in result.getroot(): 
     135        if 'img' != img.tag: 
    134136          continue 
    135         if not img.hasProp('id') or not img.hasProp('src'): 
     137        if not img.get('id') or not img.get('src'): 
    136138          continue 
    137139         
    138         fp = open(img.prop('src'), 'rb') 
     140        fp = open(img.get('src'), 'rb') 
    139141        if not fp: 
    140142          continue 
    141143        msg_img = MIMEImage(fp.read()) 
    142144        fp.close() 
    143         msg_img.add_header('Content-ID', '<%s>' % img.prop('id')) 
     145        msg_img.add_header('Content-ID', '<%s>' % img.get('id')) 
    144146        msg_related.attach(msg_img) 
    145     result.freeDoc() 
    146147     
    147148    # Send the email 
     
    196197         
    197198        try: 
    198           styledoc = libxml2.parseFile(stylesheet
    199           style = libxslt.parseStylesheetDoc(styledoc
     199          ss = open(stylesheet, 'r'
     200          transform = etree.XSLT(etree.parse(ss)
    200201        except: 
    201202          print "Error: Cannot load/parse stylesheet '%s'" % stylesheet 
     
    242243            continue 
    243244           
    244           xml = StringIO() 
    245           xml.write('<clientsplugin>') 
     245          xml = etree.Element('clientsplugin') 
    246246           
    247247          # Place basic client info here 
    248           xml.write('<client>') 
    249           xml.write('<name>%s</name>' % name) 
    250           xml.write('<lastupdate>%s</lastupdate>' % myformat_date(lastupdate)) 
    251           xml.write('</client>') 
    252            
     248          client = etree.SubElement(xml, 'client') 
     249          etree.SubElement(client, 'name').text = name 
     250          etree.SubElement(client, 'lastupdate').text = myformat_date(lastupdate) 
     251 
    253252          have_data = False 
    254253          if 'summary' == field: 
     
    265264            cur2 = db.cursor() 
    266265            cur2.execute(sql, (name,)) 
    267             xml.write('<summary>') 
     266            xsummary = etree.SubElement(xml, 'summary') 
    268267            for tid, summary, description, status, milestone, due in cur2: 
    269268              have_data = True 
    270269              if options.debug: 
    271270                print "  Summarising ticket #%s" % tid 
    272               xml.write('<ticket>') 
    273               xml.write('<id>%s</id>' % tid) 
    274               xml.write('<summary>%s</summary>' % escape(summary)) 
    275               xml.write('<description>%s</description>' % wiki_to_html(extract_client_text(description), self.env, self.req)) 
    276               xml.write('<status>%s</status>' % status) 
    277               xml.write('<milestone>%s</milestone>' % milestone) 
    278               xml.write('<due>%s</due>' % myformat_date(due)) 
    279               xml.write('</ticket>') 
    280              
    281             xml.write('</summary>') 
    282            
     271              ticket = etree.SubElement(xsummary, 'ticket') 
     272              etree.SubElement(ticket, 'id').text = str(tid) 
     273              etree.SubElement(ticket, 'summary').text = summary 
     274              ticket.append(etree.XML('<description>%s</description>' % wiki_to_html(extract_client_text(description), self.env, self.req))) 
     275              etree.SubElement(ticket, 'status').text = status 
     276              etree.SubElement(ticket, 'milestone').text = milestone 
     277              etree.SubElement(ticket, 'due').text = myformat_date(due) 
     278 
    283279          elif 'changes' == field: 
    284280            # Load in any changes that have happend 
     
    298294            cur2 = db.cursor() 
    299295            cur2.execute(sql, (name, lastupdate, now)) 
    300             xml.write('<changes>') 
     296            changes = etree.SubElement(xml, 'changes') 
    301297            lasttid = 0 
    302298            for tid, summary, description, status, milestone, due, cgfield, oldvalue, newvalue in cur2: 
     
    320316                print "  Change notification (%s) for ticket #%s" % (cgfield, tid) 
    321317              have_data = True 
    322               if lasttid and lasttid != tid: 
    323                 xml.write('</changelog>') 
    324                 xml.write('</ticket>') 
    325                
    326318              if lasttid != tid: 
    327                 xml.write('<ticket>') 
    328                 xml.write('<id>%s</id>' % tid) 
    329                 xml.write('<summary>%s</summary>' % escape(summary)) 
    330                 xml.write('<description>%s</description>' % wiki_to_html(extract_client_text(description), self.env, self.req)) 
    331                 xml.write('<status>%s</status>' % status) 
    332                 xml.write('<milestone>%s</milestone>' % milestone) 
    333                 xml.write('<due>%s</due>' % myformat_date(due)
    334                 xml.write('<changelog>') 
    335                
    336               xml.write('<detail>%s</detail>' % wiki_to_html(text, self.env, self.req)) 
     319                ticket = etree.SubElement(changes, 'ticket') 
     320                etree.SubElement(ticket, 'id').text = str(tid) 
     321                etree.SubElement(ticket, 'summary').text = summary 
     322                ticket.append(etree.XML('<description>%s</description>' % wiki_to_html(extract_client_text(description), self.env, self.req))) 
     323                etree.SubElement(ticket, 'status').text = status 
     324                etree.SubElement(ticket, 'milestone').text = milestone 
     325                etree.SubElement(ticket, 'due').text = myformat_date(due
     326                changelog = etree.SubElement(ticket, 'changelog') 
     327 
     328              changelog.append(etree.XML('<detail>%s</detail>' % wiki_to_html(text, self.env, self.req))) 
    337329              lasttid = tid 
    338330             
    339             if lasttid: 
    340               xml.write('</changelog>') 
    341               xml.write('</ticket>') 
    342             xml.write('</changes>') 
    343            
    344           xml.write('</clientsplugin>') 
    345  
    346           #if options.debug: 
    347           #  print xml.getvalue() 
     331          if options.debug: 
     332            file = open('/tmp/send-client-email.xml', 'w') 
     333            file.write(etree.tostring(xml, pretty_print=True)) 
     334            file.close() 
     335            print " Wrote XML to /tmp/send-client-email.xml" 
    348336 
    349337          if not have_data: 
    350338            continue 
    351            
    352           doc = libxml2.parseDoc(xml.getvalue()) 
     339 
    353340          subject = 'Ticket Summary for %s' % name 
    354341          if 'changes' == field: 
     
    356343          if options.debug: 
    357344            print "  Sending email '%s'" % subject 
    358           mailer.Send(subject, emails, doc, style) 
    359           doc.freeDoc() 
     345          mailer.Send(subject, emails, xml, transform) 
    360346 
    361347          if not options.debug: 
     
    366352            cursor2.execute(sql, (now, name)) 
    367353           
    368         style.freeStylesheet() 
    369354        db.commit() 
    370355        db.close() 
  • clientsplugin/0.11/cron/summary.xslt

    r2716 r3348  
    77  <xsl:output method="html" indent="yes" encoding="UTF-8" omit-xml-declaration="yes"/> 
    88  <xsl:decimal-format name="GBP" decimal-separator="." grouping-separator=","/> 
    9    
    10   <xsl:param name="view" /> 
    119   
    1210  <!-- Match the root of the XML render the three views -->