Port txt report to new report engine.
bzr revid: p_christ@hol.gr-20090507171706-ozmwxiuwv5jf1q4p
This commit is contained in:
parent
2ccc626184
commit
eac36b4a19
|
@ -205,8 +205,8 @@ class report_rml(report_int):
|
|||
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')
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ html_parents = ['tr','body','div']
|
|||
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*\))(.*?)\]\]")
|
||||
|
@ -35,9 +35,9 @@ class report(object):
|
|||
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)]
|
||||
|
@ -51,7 +51,7 @@ class report(object):
|
|||
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__':
|
||||
|
|
|
@ -52,13 +52,14 @@ class rml2html(render.render):
|
|||
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 = {}):
|
||||
|
|
|
@ -455,7 +455,7 @@ if __name__=="__main__":
|
|||
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:
|
|
@ -20,7 +20,7 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from rml2txt import parseString
|
||||
from rml2txt import parseString, parseNode
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -40,8 +40,9 @@
|
|||
|
||||
import sys
|
||||
import StringIO
|
||||
import xml.dom.minidom
|
||||
import copy
|
||||
from lxml import etree
|
||||
import base64
|
||||
|
||||
import utils
|
||||
|
||||
|
@ -80,6 +81,8 @@ class textbox():
|
|||
"""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
|
||||
|
@ -135,7 +138,7 @@ class textbox():
|
|||
|
||||
|
||||
class _flowable(object):
|
||||
def __init__(self, template, doc):
|
||||
def __init__(self, template, doc,localcontext):
|
||||
self._tags = {
|
||||
'1title': self._tag_title,
|
||||
'1spacer': self._tag_spacer,
|
||||
|
@ -149,6 +152,7 @@ class _flowable(object):
|
|||
}
|
||||
self.template = template
|
||||
self.doc = doc
|
||||
self.localcontext = localcontext
|
||||
self.nitags = []
|
||||
self.tbox = None
|
||||
|
||||
|
@ -174,7 +178,7 @@ class _flowable(object):
|
|||
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):
|
||||
|
@ -182,14 +186,14 @@ class _flowable(object):
|
|||
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)
|
||||
|
@ -228,21 +232,19 @@ class _flowable(object):
|
|||
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()
|
||||
|
@ -288,8 +290,8 @@ class _rml_tmpl_frame(_rml_tmpl_tag):
|
|||
|
||||
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',
|
||||
|
@ -348,12 +350,12 @@ class _rml_stylesheet(object):
|
|||
'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:
|
||||
|
@ -369,9 +371,9 @@ class _rml_draw_style(object):
|
|||
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:
|
||||
|
@ -391,7 +393,8 @@ class _rml_draw_style(object):
|
|||
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 = []
|
||||
|
@ -404,16 +407,16 @@ class _rml_template(object):
|
|||
'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)
|
||||
|
@ -480,21 +483,46 @@ class _rml_template(object):
|
|||
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)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# -*- 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
|
||||
|
@ -20,37 +20,110 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
# 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):
|
||||
|
@ -59,17 +132,18 @@ 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:
|
|
@ -309,7 +309,7 @@ class rml_parse(object):
|
|||
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 :
|
||||
|
@ -359,12 +359,12 @@ class report_sxw(report_rml, preprocess.report):
|
|||
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):
|
||||
|
|
Loading…
Reference in New Issue