Added method escape_values. Exclusively for Python3.
This commit is contained in:
parent
5ee43cf3e1
commit
40bf39cde7
@ -19,13 +19,12 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
# cgi.escape is deprecated in python 3.7
|
# cgi.escape is deprecated in python 3.7
|
||||||
from cgi import escape
|
from cgi import escape
|
||||||
import HTMLParser
|
|
||||||
unescape = HTMLParser.HTMLParser().unescape
|
|
||||||
import re
|
import re
|
||||||
import six
|
import six
|
||||||
import binascii
|
import binascii
|
||||||
import os
|
import os
|
||||||
import zipfile
|
import zipfile
|
||||||
|
import sys
|
||||||
|
|
||||||
NEWLINE_XML = '</w:t><w:br/><w:t xml:space="preserve">'
|
NEWLINE_XML = '</w:t><w:br/><w:t xml:space="preserve">'
|
||||||
NEWPARAGRAPH_XML = '</w:t></w:r></w:p><w:p><w:r><w:t xml:space="preserve">'
|
NEWPARAGRAPH_XML = '</w:t></w:r></w:p><w:p><w:r><w:t xml:space="preserve">'
|
||||||
@ -171,7 +170,43 @@ class DocxTemplate(object):
|
|||||||
def map_headers_footers_xml(self, relKey, xml):
|
def map_headers_footers_xml(self, relKey, xml):
|
||||||
self.docx._part._rels[relKey]._target._blob = xml
|
self.docx._part._rels[relKey]._target._blob = xml
|
||||||
|
|
||||||
def render(self,context,jinja_env=None):
|
@staticmethod
|
||||||
|
def escape_values(context):
|
||||||
|
"""Escape strings for an XML Word document
|
||||||
|
which may contain <, >, &, ', and ".
|
||||||
|
"""
|
||||||
|
def escape_recursively(d):
|
||||||
|
"""Escape string values of the passed :dict: `d` in-place
|
||||||
|
including nested dictionaries.
|
||||||
|
"""
|
||||||
|
nonlocal hash_values
|
||||||
|
|
||||||
|
for k, v in d.items():
|
||||||
|
if isinstance(v, dict):
|
||||||
|
hash_value = id(v)
|
||||||
|
if hash_value not in hash_values:
|
||||||
|
hash_values.add(hash_value)
|
||||||
|
escape_recursively(v)
|
||||||
|
else:
|
||||||
|
# Avoid dict, Listing, InlineImage, RichText, etc. classes
|
||||||
|
# by comparing v to str. Do not use try-except.
|
||||||
|
if isinstance(v, str):
|
||||||
|
# Unescape at first to avoid secondary escaping
|
||||||
|
d[k] = escape(unescape(v))
|
||||||
|
|
||||||
|
# Avoid RecursionError (if back edges, i.e. cycles, exist)
|
||||||
|
# by using a set of hash values of iterated dictionaries.
|
||||||
|
hash_values = {id(context), }
|
||||||
|
|
||||||
|
escape_recursively(context)
|
||||||
|
|
||||||
|
def render(self, context, jinja_env=None):
|
||||||
|
if sys.version_info >= (3, 0):
|
||||||
|
self.escape_values(context)
|
||||||
|
else:
|
||||||
|
# Sorry folk, use awesome Python3 such as 3.6
|
||||||
|
pass
|
||||||
|
|
||||||
# Body
|
# Body
|
||||||
xml_src = self.build_xml(context,jinja_env)
|
xml_src = self.build_xml(context,jinja_env)
|
||||||
|
|
||||||
|
|||||||
12
tests/escape_auto.py
Normal file
12
tests/escape_auto.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from docxtpl import *
|
||||||
|
|
||||||
|
tpl = DocxTemplate("test_files/escape_tpl.docx")
|
||||||
|
|
||||||
|
context = {'myvar': R('"less than" must be escaped : <, this can be done with RichText() or R()'),
|
||||||
|
'myescvar':'It can be escaped with a "|e" jinja filter in the template too : < ',
|
||||||
|
'nlnp' : R('Here is a multiple\nlines\nstring\aand some\aother\aparagraphs\aNOTE: the current character styling is removed'),
|
||||||
|
'mylisting': Listing('the listing\nwith\nsome\nlines\nand special chars : <>&'),
|
||||||
|
}
|
||||||
|
|
||||||
|
tpl.render(context)
|
||||||
|
tpl.save("test_files/escape.docx")
|
||||||
Loading…
x
Reference in New Issue
Block a user