175 lines
5.6 KiB
Python
175 lines
5.6 KiB
Python
#!/usr/bin/python
|
|
# -*- encoding: utf-8 -*-
|
|
|
|
# * Copyright (c) 2012 Christopher Ramírez blindedbythedark [at} gmail (dot] com.
|
|
# * All rights reserved.
|
|
# *
|
|
# * Permission is hereby granted, free of charge, to any person obtaining a
|
|
# * copy of this software and associated documentation files (the "Software"),
|
|
# * to deal in the Software without restriction, including without limitation
|
|
# * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
# * and/or sell copies of the Software, and to permit persons to whom the
|
|
# * Software is furnished to do so, subject to the following conditions:
|
|
# *
|
|
# * The above copyright notice and this permission notice shall be included in
|
|
# * all copies or substantial portions of the Software.
|
|
# *
|
|
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
# * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
# * DEALINGS IN THE SOFTWARE.
|
|
|
|
"""
|
|
Secretary
|
|
Take the power of Django or Jinja2 templates to OpenOffice and LibreOffice.
|
|
|
|
This file implements BaseRender. BaseRender prepares a XML which describes
|
|
ODT document content to be processed by jinja2 or Django template system.
|
|
"""
|
|
|
|
import re
|
|
import os
|
|
import zipfile
|
|
import xml.dom.minidom
|
|
|
|
|
|
try:
|
|
from jinja2 import Template as TemplateEngine
|
|
except ImportError:
|
|
from django.template import Template as TemplateEngine
|
|
|
|
|
|
PARAGRAPH_TAG = '{% paragraph_tag %}'
|
|
|
|
class BaseRender():
|
|
"""
|
|
Prapares a XML string or file to be processed by a templating system.
|
|
|
|
Use example:
|
|
render = BaseRender('content/xml', var1, var2.. varN)
|
|
render.render
|
|
"""
|
|
|
|
def __init__(self, xml_doc, **template_args):
|
|
self.template_vars = template_args
|
|
self.xml_document = xml.dom.minidom.parse(xml_doc)
|
|
body = self.xml_document.getElementsByTagName('office:body')
|
|
self.content_body = body and body[0]
|
|
|
|
# ------------------------------------------------------------------------@
|
|
|
|
|
|
def get_paragraph_parent(self, node):
|
|
"""
|
|
Returns the first node's parent with name "text:p"
|
|
If parent "text:p" is not found, returns None.
|
|
"""
|
|
|
|
if hasattr(node, 'parentNode'):
|
|
if node.parentNode.nodeName.lower() == 'text:p':
|
|
return node.parentNode
|
|
else:
|
|
return get_paragraph_parent(node.parentNode)
|
|
else:
|
|
return None
|
|
|
|
# ------------------------------------------------------------------------@
|
|
|
|
|
|
def render_with_engine(self):
|
|
"""
|
|
Once the XML have been prepared, this routine is called
|
|
to do the actual rendering.
|
|
"""
|
|
template = TemplateEngine(self.xml_document.toxml())
|
|
return template.render(**self.template_vars)
|
|
|
|
# -----------------------------------------------------------------------
|
|
|
|
|
|
def scan_child_nodes(self, nodes):
|
|
"""
|
|
|
|
"""
|
|
if nodes.hasChildNodes():
|
|
child_nodes = nodes.childNodes
|
|
|
|
for node in child_nodes:
|
|
if node.nodeType == node.TEXT_NODE:
|
|
node_text = node.data.lower()
|
|
|
|
# replace a paragraph node with contained tags
|
|
# if tag PARAGRAPH_TAG is in paragraph content.
|
|
|
|
if node_text.find(PARAGRAPH_TAG) > -1:
|
|
# Get this node text:p parent
|
|
paragraph_node = self.get_paragraph_parent(node)
|
|
paragraph_parent = paragraph_node.parentNode
|
|
|
|
|
|
# Discar PARAGRAPH_TAG
|
|
pgraph_node_text = \
|
|
paragraph_node.toxml().replace(PARAGRAPH_TAG, '')
|
|
|
|
# replace text:p node's XML with its contained templates tags.
|
|
new_node_text = \
|
|
' '.join(re.findall('(\{.*?\})', pgraph_node_text))
|
|
|
|
new_node = xml_document.createTextNode(new_node_text)
|
|
paragraph_parent.replaceChild(new_node, paragraph_node)
|
|
|
|
else:
|
|
if node.hasChildNodes():
|
|
scan_child_nodes(node)
|
|
|
|
# -----------------------------------------------------------------------
|
|
|
|
|
|
def handle_special_tags(self):
|
|
"""
|
|
|
|
"""
|
|
paragraphs = self.content_body.getElementsByTagName('text:p')
|
|
for paragraph in paragraphs:
|
|
self.scan_child_nodes(paragraph)
|
|
|
|
# -----------------------------------------------------------------------
|
|
|
|
|
|
def render(self):
|
|
"""
|
|
render prepares the XML and the call render_with_engine
|
|
to parse template engine tags
|
|
"""
|
|
|
|
self.handle_special_tags()
|
|
|
|
return self.render_with_engine()
|
|
|
|
# -----------------------------------------------------------------------
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
data = {
|
|
'name': u'Christopher Ramirez',
|
|
'country': 'Nicaragua'
|
|
}
|
|
|
|
render = BaseRender('content.xml', record=data)
|
|
print render.render()
|
|
|
|
# xml_document = xml.dom.minidom.parse('content.xml')
|
|
# doc_body = xml_document.getElementsByTagName('office:body')
|
|
# doc_body = doc_body and doc_body[0]
|
|
|
|
# template = Template(doc_body.toprettyxml())
|
|
|
|
# print template.render( name='Christopher :)' )
|
|
|
|
|
|
|
|
|