Created
May 5, 2023 08:23
-
-
Save louwersj/74a8c059a391689dee0954dcbd9cdfbd to your computer and use it in GitHub Desktop.
Example code to show how XML data can be infused into a docx template based upon Jinja2.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Example code to show how XML data can be infused into a docx template based upon Jinja2. | |
import sys | |
import uuid | |
import xml.etree.cElementTree as ET | |
from docxtpl import DocxTemplate | |
xmlStructure = ("input_data.xml") | |
def getTemplate (name): | |
''' | |
Function is used to retrieve the word .docx template. the template will be retrieved based upon the variable name | |
provided to the function. In this example we will retrieve the template from local disk. In a more production like | |
environment the template will have to be retrieved (most likely) from an external location...possibly via https | |
:param name: | |
:return: | |
''' | |
try: | |
templatePath = "./templates/{}".format(name) | |
retreivedTemplate = DocxTemplate(templatePath) | |
except IOError as e: | |
# handle the exception | |
print(f"Error opening template file: {e}") | |
return retreivedTemplate | |
def getXmlRoot (name): | |
''' | |
Used to retrieve the XML file and get the root element. In this example we load the .xml structure from a local | |
file. In other situations you might need to get this via a https call or it is send to the code as part of the | |
invocation call. the xml root should be retruned as xml.etree.ElementTree.Element variable to the calling logic | |
:param name: | |
:return: xml.etree.ElementTree.Element | |
''' | |
try: | |
xmlTree = ET.parse(name) | |
xmlRoot = xmlTree.getroot() | |
except FileNotFoundError as e: | |
print(f"Error: {e}. The XML file does not exist.") | |
sys.exit(1) | |
except ET.ParseError as e: | |
print(f"Error: {e}. Failed to parse the XML file.") | |
sys.exit(1) | |
except Exception as e: | |
print(f"Error: {e}.") | |
sys.exit(1) | |
return xmlRoot | |
def createContextStruct(xmlInput): | |
''' | |
Used to build a context structure based upon the XML input file. The context structure needs to be a simple K/V like | |
structure where K equals the Jinja variable names in the word template. In this example we extract the K/V values | |
from everything within <variables> in the main XML input file. In a specific situation you might want/need to change | |
this. | |
:param xmlInput: | |
:return: | |
''' | |
context = {} | |
for var in xmlInput.iter(): | |
if var.tag != "output_data" and var.tag != "variables": | |
context[var.tag] = var.text | |
return context | |
if __name__ == '__main__': | |
# get the XML data using the getXmlRoot function | |
try: | |
xmlContent = getXmlRoot(xmlStructure) | |
except AttributeError as e: | |
# handle the exception | |
print(f"Error reading the the XML data when calling the getXmlRoot function : {e}") | |
sys.exit(1) | |
# get the word template name form the XML file. | |
try: | |
templateName = (xmlContent.find("template")).text | |
except Exception as e: | |
# handle the exception | |
print(f"Error reading the template name from the XML file: {e}") | |
sys.exit(1) | |
# get the word template name form the XML file. | |
try: | |
docTemplate = getTemplate(templateName) | |
except Exception as e: | |
# handle the exception | |
print(f"Error unable to get the document template using the getTemplate function: {e}") | |
sys.exit(1) | |
# create a context structure which will hold a K/V list in a dict for all variables in the word template. | |
try: | |
context = createContextStruct(xmlContent) | |
except Exception as e: | |
# handle the excpetion | |
print(f"Error, unable to create context by using createContextStruct {e}") | |
sys.exit(1) | |
docTemplate.render(context) | |
outputName = ("./{}.docx").format(str(uuid.uuid4())) | |
docTemplate.save(outputName) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment