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:
Eric Lapouyade 2021-05-09 10:26:08 +02:00
commit af2b027c9f

View File

@ -39,7 +39,7 @@ class DocxTemplate(object):
self.crc_to_new_media = {}
self.crc_to_new_embedded = {}
self.zipname_to_replace = {}
self.pic_to_replace = {}
self.pics_to_replace = {}
self.pic_map = {}
self.current_rendering_part = None
@ -477,10 +477,10 @@ class DocxTemplate(object):
if hasattr(dst_file, 'read'):
# NOTE: file extension not checked
self.pic_to_replace[embedded_file] = dst_file.read()
self.pics_to_replace[embedded_file] = dst_file.read()
else:
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):
"""Replace one embedded object by another one into a docx
@ -568,33 +568,34 @@ class DocxTemplate(object):
def pre_processing(self):
if self.pic_to_replace:
self.build_pic_map()
if self.pics_to_replace:
self._replace_pics()
# Do the actual replacement
for embedded_file, stream in six.iteritems(self.pic_to_replace):
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 _replace_pics(self):
"""Replaces pictures xml tags in the docx template with pictures provided by the user"""
def build_pic_map(self):
"""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))
replaced_pics = {key: False for key in self.pics_to_replace}
# Header/Footer
for relid, rel in six.iteritems(self.docx.part.rels):
if rel.reltype in (REL_TYPE.HEADER, REL_TYPE.FOOTER):
self.pic_map.update(self._img_filename_to_part(rel.target_part))
# Main document
part = self.docx.part
self._replace_docx_part_pics(part, replaced_pics)
# 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):
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)
@ -617,17 +618,37 @@ class DocxTemplate(object):
else:
continue
# title=inl.xpath('wp:docPr/@title',namespaces=docx.oxml.ns.nsmap)[0]
name = gd.xpath('pic:pic/pic:nvPicPr/pic:cNvPr/@name',
namespaces=docx.oxml.ns.nsmap)[0]
non_visual_properties = 'pic:pic/pic:nvPicPr/pic:cNvPr/'
filename = gd.xpath('%s@name' % non_visual_properties,
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
except Exception:
continue
return part_map
self.pic_map.update(part_map)
def build_url_id(self, url):
return self.docx._part.relate_to(url, REL_TYPE.HYPERLINK,