obj.render()
return obj.get()
- def create_txt(self, xml, logo=None, title=None):
- obj = render.rml2txt(xml, self.bin_datas)
+ def create_txt(self, rml,localcontext, logo=None, title=None):
+ obj = render.rml2txt(rml, localcontext, self.bin_datas)
obj.render()
return obj.get().encode('utf-8')
sxw_parents = ['{http://openoffice.org/2000/table}table-row','{http://openoffice.org/2000/office}body','{http://openoffice.org/2000/text}section']
class report(object):
- def preprocess_rml(self, root_node,type='pdf'):
+ def preprocess_rml(self, root_node,ntype='pdf'):
_regex1 = re.compile("\[\[(.*?)(repeatIn\(.*?\s*,\s*[\'\"].*?[\'\"]\s*(?:,\s*(.*?)\s*)?\s*\))(.*?)\]\]")
_regex11= re.compile("\[\[(.*?)(repeatIn\(.*?\s*\(.*?\s*[\'\"].*?[\'\"]\s*\),[\'\"].*?[\'\"](?:,\s*(.*?)\s*)?\s*\))(.*?)\]\]")
_regex2 = re.compile("\[\[(.*?)(removeParentNode\(\s*(?:['\"](.*?)['\"])\s*\))(.*?)\]\]")
if len(txt.group(4)) > 1:
return " "
match = rml_parents
- if type in ['odt','sxw']:
+ if ntype in ['odt','sxw']:
match = sxw_parents
- if type =='html2html':
+ if ntype =='html2html':
match = html_parents
if txt.group(3):
match = [txt.group(3)]
t = _regex11.sub(_sub1, node.text)
t = _regex3.sub(_sub3, t)
node.text = _regex2.sub(_sub2, t)
- self.preprocess_rml(node,type)
+ self.preprocess_rml(node,ntype)
return root_node
if __name__=='__main__':
return htmlizer.parseString(self.rml,self.localcontext)
class rml2txt(render.render):
- def __init__(self, xml, datas={}):
+ def __init__(self, rml, localcontext= None, datas={}):
super(rml2txt, self).__init__(datas)
- self.xml = xml
+ self.rml = rml
+ self.localcontext = localcontext
self.output_type = 'txt'
def _render(self):
- return txtizer.parseString(self.xml)
+ return txtizer.parseString(self.rml, self.localcontext)
class odt2odt(render.render):
def __init__(self, rml, localcontext = None, datas = {}):
rml2html_help()
print parseString(file(sys.argv[1], 'r').read()),
else:
- print 'Usage: trml2pdf input.rml >output.pdf'
- print 'Try \'trml2pdf --help\' for more information.'
+ print 'Usage: rml2html input.rml >output.html'
+ print 'Try \'rml2html --help\' for more information.'
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
#
##############################################################################
-from rml2txt import parseString
+from rml2txt import parseString, parseNode
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
import sys
import StringIO
-import xml.dom.minidom
import copy
+from lxml import etree
+import base64
import utils
"""Append some text to the current line.
Mimic the HTML behaviour, where all whitespace evaluates to
a single space """
+ if not txt:
+ return
bs = es = False
if txt[0].isspace():
bs = True
class _flowable(object):
- def __init__(self, template, doc):
+ def __init__(self, template, doc,localcontext):
self._tags = {
'1title': self._tag_title,
'1spacer': self._tag_spacer,
}
self.template = template
self.doc = doc
+ self.localcontext = localcontext
self.nitags = []
self.tbox = None
return node.toxml()
def _tag_spacer(self, node):
- length = 1+int(utils.unit_get(node.getAttribute('length')))/35
+ length = 1+int(utils.unit_get(node.get('length')))/35
return "\n"*length
def _tag_table(self, node):
saved_tb = self.tb
self.tb = None
sizes = None
- if node.hasAttribute('colWidths'):
- sizes = map(lambda x: utils.unit_get(x), node.getAttribute('colWidths').split(','))
+ if node.get('colWidths'):
+ sizes = map(lambda x: utils.unit_get(x), node.get('colWidths').split(','))
trs = []
- for n in node.childNodes:
- if n.nodeType == node.ELEMENT_NODE and n.localName == 'tr':
+ for n in utils._child_get(node,self):
+ if n.tag == 'tr':
tds = []
- for m in n.childNodes:
- if m.nodeType == node.ELEMENT_NODE and m.localName == 'td':
+ for m in utils._child_get(n,self):
+ if m.tag == 'td':
self.tb = textbox()
self.rec_render_cnodes(m)
tds.append(self.tb)
self.rec_render_cnodes(node)
def rec_render_cnodes(self,node):
- for n in node.childNodes:
- self.rec_render(n)
+ self.tb.appendtxt(utils._process_text(self, node.text or ''))
+ for n in utils._child_get(node,self):
+ self.rec_render(n)
+ self.tb.appendtxt(utils._process_text(self, node.tail or ''))
def rec_render(self,node):
""" Recursive render: fill outarr with text of current node
"""
- if node.nodeType == node.TEXT_NODE:
- self.tb.appendtxt(node.data)
- elif node.nodeType==node.ELEMENT_NODE:
- if node.localName in self._tags:
- self._tags[node.localName](node)
+ if node.tag != None:
+ if node.tag in self._tags:
+ self._tags[node.tag](node)
else:
- self.warn_nitag(node.localName)
- else:
- verbose("Unknown nodeType: %d" % node.nodeType)
+ self.warn_nitag(node.tag)
def render(self, node):
self.tb= textbox()
class _rml_tmpl_draw_string(_rml_tmpl_tag):
def __init__(self, node, style):
- self.posx = utils.unit_get(node.getAttribute('x'))
- self.posy = utils.unit_get(node.getAttribute('y'))
+ self.posx = utils.unit_get(node.get('x'))
+ self.posy = utils.unit_get(node.get('y'))
aligns = {
'drawString': 'left',
'drawRightString': 'right',
'alignment': lambda x: ('text-align',str(x))
}
result = ''
- for ps in stylesheet.getElementsByTagName('paraStyle'):
+ for ps in stylesheet.findall('paraStyle'):
attr = {}
attrs = ps.attributes
for i in range(attrs.length):
name = attrs.item(i).localName
- attr[name] = ps.getAttribute(name)
+ attr[name] = ps.get(name)
attrs = []
for a in attr:
if a in self._tags:
def __init__(self):
self.style = {}
self._styles = {
- 'fill': lambda x: {'td': {'color':x.getAttribute('color')}},
- 'setFont': lambda x: {'td': {'font-size':x.getAttribute('size')+'px'}},
- 'stroke': lambda x: {'hr': {'color':x.getAttribute('color')}},
+ 'fill': lambda x: {'td': {'color':x.get('color')}},
+ 'setFont': lambda x: {'td': {'font-size':x.get('size')+'px'}},
+ 'stroke': lambda x: {'hr': {'color':x.get('color')}},
}
def update(self, node):
if node.localName in self._styles:
return ';'.join(['%s:%s' % (x[0],x[1]) for x in self.style[tag].items()])
class _rml_template(object):
- def __init__(self, template):
+ def __init__(self, localcontext, out, node, doc, images={}, path='.', title=None):
+ self.localcontext = localcontext
self.frame_pos = -1
self.frames = []
self.template_order = []
'lines': _rml_tmpl_draw_lines
}
self.style = _rml_draw_style()
- for pt in template.getElementsByTagName('pageTemplate'):
+ for pt in node.findall('pageTemplate'):
frames = {}
- id = pt.getAttribute('id')
+ id = pt.get('id')
self.template_order.append(id)
- for tmpl in pt.getElementsByTagName('frame'):
- posy = int(utils.unit_get(tmpl.getAttribute('y1'))) #+utils.unit_get(tmpl.getAttribute('height')))
- posx = int(utils.unit_get(tmpl.getAttribute('x1')))
- frames[(posy,posx,tmpl.getAttribute('id'))] = _rml_tmpl_frame(posx, utils.unit_get(tmpl.getAttribute('width')))
- for tmpl in template.getElementsByTagName('pageGraphics'):
- for n in tmpl.childNodes:
+ for tmpl in pt.findall('frame'):
+ posy = int(utils.unit_get(tmpl.get('y1'))) #+utils.unit_get(tmpl.get('height')))
+ posx = int(utils.unit_get(tmpl.get('x1')))
+ frames[(posy,posx,tmpl.get('id'))] = _rml_tmpl_frame(posx, utils.unit_get(tmpl.get('width')))
+ for tmpl in node.findall('pageGraphics'):
+ for n in tmpl.getchildren():
if n.nodeType==n.ELEMENT_NODE:
if n.localName in self._tags:
t = self._tags[n.localName](n, self.style)
return result
class _rml_doc(object):
- def __init__(self, data):
- self.dom = xml.dom.minidom.parseString(data)
- self.filename = self.dom.documentElement.getAttribute('filename')
+ def __init__(self, node, localcontext, images={}, path='.', title=None):
+ self.localcontext = localcontext
+ self.etree = node
+ self.filename = self.etree.get('filename')
self.result = ''
def render(self, out):
- template = _rml_template(self.dom.documentElement.getElementsByTagName('template')[0])
- f = _flowable(template, self.dom)
- self.result += f.render(self.dom.documentElement.getElementsByTagName('story')[0])
- del f
+ #el = self.etree.findall('docinit')
+ #if el:
+ #self.docinit(el)
+
+ #el = self.etree.findall('stylesheet')
+ #self.styles = _rml_styles(el,self.localcontext)
+
+ el = self.etree.findall('template')
+ self.result =""
+ if len(el):
+ pt_obj = _rml_template(self.localcontext, out, el[0], self)
+ stories = utils._child_get(self.etree, self, 'story')
+ for story in stories:
+ if self.result:
+ self.result += '\f'
+ f = _flowable(pt_obj,story,self.localcontext)
+ self.result += f.render(story)
+ del f
+ else:
+ self.result = "<cannot render w/o template>"
self.result += '\n'
out.write( self.result)
-def parseString(data, fout=None):
- r = _rml_doc(data)
+def parseNode(rml, localcontext = {},fout=None, images={}, path='.',title=None):
+ node = etree.XML(rml)
+ r = _rml_doc(node, localcontext, images, path, title=title)
+ fp = StringIO.StringIO()
+ r.render(fp)
+ return fp.getvalue()
+
+def parseString(rml, localcontext = {},fout=None, images={}, path='.',title=None):
+ node = etree.XML(rml)
+ r = _rml_doc(node, localcontext, images, path, title=title)
if fout:
fp = file(fout,'wb')
r.render(fp)
# -*- encoding: utf-8 -*-
##############################################################################
#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
#
##############################################################################
+# trml2pdf - An RML to PDF converter
+# Copyright (C) 2003, Fabien Pinckaers, UCL, FSA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
import re
import reportlab
import reportlab.lib.units
+from lxml import etree
+
+_regex = re.compile('\[\[(.+?)\]\]')
+
+def _child_get(node, self=None, tagname=None):
+ for n in node:
+ if self and self.localcontext and n.get('rml_loop', False):
+ oldctx = self.localcontext
+ for ctx in eval(n.get('rml_loop'),{}, self.localcontext):
+ self.localcontext.update(ctx)
+ if (tagname is None) or (n.tag==tagname):
+ if n.get('rml_except', False):
+ try:
+ eval(n.get('rml_except'), {}, self.localcontext)
+ except:
+ continue
+ if n.get('rml_tag'):
+ try:
+ (tag,attr) = eval(n.get('rml_tag'),{}, self.localcontext)
+ n2 = copy.copy(n)
+ n2.tag = tag
+ n2.attrib.update(attr)
+ yield n2
+ except:
+ yield n
+ else:
+ yield n
+ self.localcontext = oldctx
+ continue
+ if self and self.localcontext and n.get('rml_except', False):
+ try:
+ eval(n.get('rml_except'), {}, self.localcontext)
+ except:
+ continue
+ if (tagname is None) or (n.tag==tagname):
+ yield n
+
+def _process_text(self, txt):
+ if not self.localcontext:
+ return txt
+ if not txt:
+ return ''
+ result = ''
+ sps = _regex.split(txt)
+ while sps:
+ # This is a simple text to translate
+ result += self.localcontext.get('translate', lambda x:x)(sps.pop(0))
+ if sps:
+ try:
+ txt2 = eval(sps.pop(0),self.localcontext)
+ except:
+ txt2 = ''
+ if type(txt2) == type(0) or type(txt2) == type(0.0):
+ txt2 = str(txt2)
+ if type(txt2)==type('') or type(txt2)==type(u''):
+ result += txt2
+ return result
def text_get(node):
rc = ''
- for node in node.childNodes:
- if node.nodeType == node.TEXT_NODE:
- rc = rc + node.data
+ for node in node.getchildren():
+ rc = rc + node.text
return rc
units = [
(re.compile('^(-?[0-9\.]+)\s*in$'), reportlab.lib.units.inch),
- (re.compile('^(-?[0-9\.]+)\s*cm$'), reportlab.lib.units.cm),
+ (re.compile('^(-?[0-9\.]+)\s*cm$'), reportlab.lib.units.cm),
(re.compile('^(-?[0-9\.]+)\s*mm$'), reportlab.lib.units.mm),
- (re.compile('^(-?[0-9\.]+)\s*px$'), 0.7),
(re.compile('^(-?[0-9\.]+)\s*$'), 1)
]
def unit_get(size):
global units
- for unit in units:
- res = unit[0].search(size, 0)
- if res:
- return int(unit[1]*float(res.group(1))*1.3)
+ if size:
+ for unit in units:
+ res = unit[0].search(size, 0)
+ if res:
+ return unit[1]*float(res.group(1))
return False
def tuple_int_get(node, attr_name, default=None):
- if not node.hasAttribute(attr_name):
+ if not node.get(attr_name):
return default
- res = [int(x) for x in node.getAttribute(attr_name).split(',')]
+ res = [int(x) for x in node.get(attr_name).split(',')]
return res
def bool_get(value):
def attr_get(node, attrs, dict={}):
res = {}
for name in attrs:
- if node.hasAttribute(name):
- res[name] = unit_get(node.getAttribute(name))
+ if node.get(name):
+ res[name] = unit_get(node.get(name))
for key in dict:
- if node.hasAttribute(key):
+ if node.get(key):
if dict[key]=='str':
- res[key] = str(node.getAttribute(key))
+ res[key] = str(node.get(key))
elif dict[key]=='bool':
- res[key] = bool_get(node.getAttribute(key))
+ res[key] = bool_get(node.get(key))
elif dict[key]=='int':
- res[key] = int(node.getAttribute(key))
+ res[key] = int(node.get(key))
+ elif dict[key]=='unit':
+ res[key] = unit_get(node.get(key))
return res
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
head_dom = etree.XML(rml_head)
for tag in head_dom.getchildren():
found = rml_dom.find('.//'+tag.tag)
- if found:
+ if found is not None:
if tag.get('position'):
found.append(tag)
else :
report_type = report_xml.report_type
if report_type in ['sxw','odt']:
fnct = self.create_source_odt
- elif report_type in ['pdf','raw','html']:
+ elif report_type in ['pdf','raw','txt','html']:
fnct = self.create_source_pdf
elif report_type=='html2html':
fnct = self.create_source_html2html
else:
- raise 'Unknown Report Type'
+ raise Exception('Unknown Report Type: '+report_type)
return fnct(cr, uid, ids, data, report_xml, context)
def create_source_odt(self, cr, uid, ids, data, report_xml, context=None):