Add subdoc support

This commit is contained in:
elapouya 2015-03-13 17:05:26 +01:00
parent 80a10956ed
commit 028820f3dd
13 changed files with 111 additions and 17 deletions

View File

@ -1,2 +1,5 @@
eclipse.preferences.version=1
encoding//docxtpl/__init__.py=utf-8
encoding//tests/cellbg.py=utf-8
encoding//tests/order.py=utf-8
encoding//tests/subdoc.py=utf-8

View File

@ -1,3 +1,8 @@
0.1.2 (2015-03-13)
0.1.3 (2015-03-13)
------------------
- add subdoc support
- add some exemples in tests/
0.1.2 (2015-03-12)
------------------
- First running version

View File

@ -21,9 +21,17 @@ class DocxTemplate(object):
def __getattr__(self, name):
return getattr(self.docx, name)
def build_xml(self,context):
src_xml = etree.tostring(self.docx._element.body, pretty_print=True)
def get_docx(self):
return self.docx
def get_xml(self):
return etree.tostring(self.docx._element.body, pretty_print=True)
def write_xml(self,filename):
with open(filename,'w') as fh:
fh.write(self.get_xml())
def patch_xml(self,src_xml):
# strip all xml tags inside {% %} and {{ }}
# that Microsoft word can insert into xml code for this part of the document
def striptags(m):
@ -34,22 +42,28 @@ class DocxTemplate(object):
def cellbg(m):
cell_xml = m.group(1) + m.group(3)
cell_xml = re.sub(r'<w:r[ >](?:(?!<w:r[ >]).)*<w:t></w:t>.*?</w:r>','',cell_xml,flags=re.DOTALL)
return re.sub(r'(<w:shd[^/]*w:fill=")[^"]*("[^/]*/>)',r'\1{{ %s}}\2' % m.group(2), cell_xml)
cell_xml = re.sub(r'<w:shd[^/]*/>','', cell_xml, count=1)
return re.sub(r'(<w:tcPr[^>]*>)',r'\1<w:shd w:val="clear" w:color="auto" w:fill="{{%s}}"/>' % m.group(2), cell_xml)
src_xml = re.sub(r'(<w:tc[ >](?:(?!<w:tc[ >]).)*){%\s*cellbg\s+([^%]*)\s*%}(.*?</w:tc>)',cellbg,src_xml,flags=re.DOTALL)
# replace xml code corresponding to the paragraph containing {{{ xxx }}} by {{ xxx }}
src_xml = re.sub(r'<w:p[ >](?:(?!<w:p[ >]).)*{{{([^}]*)}}}.*?</w:p>',r'{{\1}}',src_xml,flags=re.DOTALL)
# replace xml code corresponding to the row containing {% tr-xxx template tag by {% xxx template tag itself
src_xml = re.sub(r'<w:tr[ >](?:(?!<w:tr[ >]).)*{%\s*tr-([^%]*%}).*?</w:tr>',r'{% \1',src_xml,flags=re.DOTALL)
# replace xml code corresponding to the paragraph containing {% p-xxx template tag by {% xxx template tag itself
src_xml = re.sub(r'<w:p[ >](?:(?!<w:p[ >]).)*{%\s*p-([^%]*%}).*?</w:p>',r'{% \1',src_xml,flags=re.DOTALL)
for y in ['tr', 'p', 'r']:
# replace into xml code the row containing {%y xxx %} or {{y xxx}} template tag
# by {% xxx %} or {{ xx }} without any surronding xml tags.
pat = r'<w:%(y)s[ >](?:(?!<w:%(y)s[ >]).)*({%%|{{)%(y)s ([^}%%]*(?:%%}|}})).*?</w:%(y)s>' % {'y':y}
src_xml = re.sub(pat, r'\1 \2',src_xml,flags=re.DOTALL)
return src_xml
def render_xml(self,src_xml,context):
template = Template(src_xml)
dst_xml = template.render(context)
dst_xml = template.render(context)
return dst_xml
def build_xml(self,context):
xml = self.get_xml()
xml = self.patch_xml(xml)
xml = self.render_xml(xml, context)
return xml
def map_xml(self,xml):
root = self.docx._element
@ -59,10 +73,28 @@ class DocxTemplate(object):
def render(self,context):
xml = self.build_xml(context)
self.map_xml(xml)
def new_subdoc(self):
return Subdoc(self)
class Subdoc(object):
""" Class for subdocumentation insertion into master document """
pass
def __init__(self, tpl):
self.tpl = tpl
self.docx = tpl.get_docx()
self.subdocx = Document()
self.subdocx._part = self.docx._part
def __getattr__(self, name):
return getattr(self.subdocx, name)
def __unicode__(self):
xml = ''
for p in self.paragraphs:
xml += '<w:p>\n' + re.sub(r'^.*\n', '', etree.tostring(p._element,pretty_print=True))
return xml
class Tpldoc(object):
""" class to build documenation to be passed into template variables """

View File

@ -24,7 +24,7 @@ News
""" % read('README', 'CHANGES')
setup(name='docxtpl',
version='0.1.2',
version='0.1.3',
description='Python docx template engine',
long_description=long_description,
classifiers=[

22
tests/cellbg.py Normal file
View File

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
'''
Created : 2015-03-12
@author: Eric Lapouyade
'''
from docxtpl import DocxTemplate
tpl=DocxTemplate('test_files/cellbg_tpl.docx')
context = {
'alerts' : [
{'date' : '2015-03-10', 'desc' : 'Very critical alert', 'type' : 'CRITICAL', 'bg': 'FF0000' },
{'date' : '2015-03-11', 'desc' : 'Just a warning', 'type' : 'WARNING', 'bg': 'FFDD00' },
{'date' : '2015-03-12', 'desc' : 'Information', 'type' : 'INFO', 'bg': '8888FF' },
{'date' : '2015-03-13', 'desc' : 'Debug trace', 'type' : 'DEBUG', 'bg': 'FF00FF' },
],
}
tpl.render(context)
tpl.save('test_files/cellbg.docx')

View File

@ -1,3 +1,10 @@
# -*- coding: utf-8 -*-
'''
Created : 2015-03-12
@author: Eric Lapouyade
'''
from docxtpl import DocxTemplate
tpl=DocxTemplate('test_files/order_tpl.docx')

25
tests/subdoc.py Normal file
View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
'''
Created : 2015-03-12
@author: Eric Lapouyade
'''
from docxtpl import DocxTemplate
tpl=DocxTemplate('test_files/subdoc_tpl.docx')
sd = tpl.new_subdoc()
p = sd.add_paragraph('This is a sub-document inserted into a bigger one')
p = sd.add_paragraph('It has been ')
p.add_run('dynamically').style = 'dynamic'
p.add_run(' generated with python by using ')
p.add_run('python-docx').italic = True
p.add_run(' library')
context = {
'mysubdoc' : sd,
}
tpl.render(context)
tpl.save('test_files/subdoc.docx')

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.