Merge branch 'ae/support_img_title_and_desc_in_replace_pic' of https://github.com/alanoe/python-docx-template into alanoe-ae/support_img_title_and_desc_in_replace_pic
This commit is contained in:
commit
af2b027c9f
@ -39,7 +39,7 @@ class DocxTemplate(object):
|
|||||||
self.crc_to_new_media = {}
|
self.crc_to_new_media = {}
|
||||||
self.crc_to_new_embedded = {}
|
self.crc_to_new_embedded = {}
|
||||||
self.zipname_to_replace = {}
|
self.zipname_to_replace = {}
|
||||||
self.pic_to_replace = {}
|
self.pics_to_replace = {}
|
||||||
self.pic_map = {}
|
self.pic_map = {}
|
||||||
self.current_rendering_part = None
|
self.current_rendering_part = None
|
||||||
|
|
||||||
@ -477,10 +477,10 @@ class DocxTemplate(object):
|
|||||||
|
|
||||||
if hasattr(dst_file, 'read'):
|
if hasattr(dst_file, 'read'):
|
||||||
# NOTE: file extension not checked
|
# NOTE: file extension not checked
|
||||||
self.pic_to_replace[embedded_file] = dst_file.read()
|
self.pics_to_replace[embedded_file] = dst_file.read()
|
||||||
else:
|
else:
|
||||||
with open(dst_file, 'rb') as fh:
|
with open(dst_file, 'rb') as fh:
|
||||||
self.pic_to_replace[embedded_file] = fh.read()
|
self.pics_to_replace[embedded_file] = fh.read()
|
||||||
|
|
||||||
def replace_embedded(self, src_file, dst_file):
|
def replace_embedded(self, src_file, dst_file):
|
||||||
"""Replace one embedded object by another one into a docx
|
"""Replace one embedded object by another one into a docx
|
||||||
@ -568,33 +568,34 @@ class DocxTemplate(object):
|
|||||||
|
|
||||||
def pre_processing(self):
|
def pre_processing(self):
|
||||||
|
|
||||||
if self.pic_to_replace:
|
if self.pics_to_replace:
|
||||||
self.build_pic_map()
|
self._replace_pics()
|
||||||
|
|
||||||
# Do the actual replacement
|
def _replace_pics(self):
|
||||||
for embedded_file, stream in six.iteritems(self.pic_to_replace):
|
"""Replaces pictures xml tags in the docx template with pictures provided by the user"""
|
||||||
if embedded_file not in self.pic_map:
|
|
||||||
raise ValueError('Picture "%s" not found in the docx template'
|
|
||||||
% embedded_file)
|
|
||||||
self.pic_map[embedded_file][1]._blob = stream
|
|
||||||
|
|
||||||
def build_pic_map(self):
|
replaced_pics = {key: False for key in self.pics_to_replace}
|
||||||
"""Searches in docx template all the xml pictures tag and store them
|
|
||||||
in pic_map dict"""
|
|
||||||
if self.pic_to_replace:
|
|
||||||
# Main document
|
|
||||||
part = self.docx.part
|
|
||||||
self.pic_map.update(self._img_filename_to_part(part))
|
|
||||||
|
|
||||||
# Header/Footer
|
# Main document
|
||||||
for relid, rel in six.iteritems(self.docx.part.rels):
|
part = self.docx.part
|
||||||
if rel.reltype in (REL_TYPE.HEADER, REL_TYPE.FOOTER):
|
self._replace_docx_part_pics(part, replaced_pics)
|
||||||
self.pic_map.update(self._img_filename_to_part(rel.target_part))
|
|
||||||
|
# Header/Footer
|
||||||
|
for relid, rel in six.iteritems(part.rels):
|
||||||
|
if rel.reltype in (REL_TYPE.HEADER, REL_TYPE.FOOTER):
|
||||||
|
self._replace_docx_part_pics(rel.target_part, replaced_pics)
|
||||||
|
|
||||||
|
# make sure all template images defined by user were replaced
|
||||||
|
for img_id, replaced in replaced_pics.items():
|
||||||
|
if not replaced:
|
||||||
|
raise ValueError(
|
||||||
|
"Picture %s not found in the docx template" % img_id
|
||||||
|
)
|
||||||
|
|
||||||
def get_pic_map(self):
|
def get_pic_map(self):
|
||||||
return self.pic_map
|
return self.pic_map
|
||||||
|
|
||||||
def _img_filename_to_part(self, doc_part):
|
def _replace_docx_part_pics(self, doc_part, replaced_pics):
|
||||||
|
|
||||||
et = etree.fromstring(doc_part.blob)
|
et = etree.fromstring(doc_part.blob)
|
||||||
|
|
||||||
@ -617,17 +618,37 @@ class DocxTemplate(object):
|
|||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# title=inl.xpath('wp:docPr/@title',namespaces=docx.oxml.ns.nsmap)[0]
|
non_visual_properties = 'pic:pic/pic:nvPicPr/pic:cNvPr/'
|
||||||
name = gd.xpath('pic:pic/pic:nvPicPr/pic:cNvPr/@name',
|
filename = gd.xpath('%s@name' % non_visual_properties,
|
||||||
namespaces=docx.oxml.ns.nsmap)[0]
|
namespaces=docx.oxml.ns.nsmap)[0]
|
||||||
|
titles = gd.xpath('%s@title' % non_visual_properties,
|
||||||
|
namespaces=docx.oxml.ns.nsmap)
|
||||||
|
if titles:
|
||||||
|
title = titles[0]
|
||||||
|
else:
|
||||||
|
title = ""
|
||||||
|
descriptions = gd.xpath('%s@descr' % non_visual_properties,
|
||||||
|
namespaces=docx.oxml.ns.nsmap)
|
||||||
|
if descriptions:
|
||||||
|
description = descriptions[0]
|
||||||
|
else:
|
||||||
|
description = ""
|
||||||
|
|
||||||
|
part_map[filename] = (doc_part.rels[rel].target_ref,
|
||||||
|
doc_part.rels[rel].target_part)
|
||||||
|
|
||||||
|
# replace data
|
||||||
|
for img_id, img_data in six.iteritems(self.pics_to_replace):
|
||||||
|
if img_id == filename or img_id == title or img_id == description:
|
||||||
|
part_map[filename][1]._blob = img_data
|
||||||
|
replaced_pics[img_id] = True
|
||||||
|
break
|
||||||
|
|
||||||
part_map[name] = (doc_part.rels[rel].target_ref,
|
|
||||||
doc_part.rels[rel].target_part)
|
|
||||||
# FIXME: figure out what exceptions are thrown here and catch more specific exceptions
|
# FIXME: figure out what exceptions are thrown here and catch more specific exceptions
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return part_map
|
self.pic_map.update(part_map)
|
||||||
|
|
||||||
def build_url_id(self, url):
|
def build_url_id(self, url):
|
||||||
return self.docx._part.relate_to(url, REL_TYPE.HYPERLINK,
|
return self.docx._part.relate_to(url, REL_TYPE.HYPERLINK,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user