1

I've been experimenting with Cheetah3 as a templating engine to transform XML into something else. I have this working, using the below example XML input

<?xml version="1.0" encoding="UTF-8"?>
<example code="HI">
    <codes>
        <code>1</code>
        <code>2</code>
    </codes>
</example>

and the following code

#!/usr/bin/env python

import xmltodict
from Cheetah.Template import Template


with open('example.xml', 'r') as f:
    example_xml = f.read()
example_dict = xmltodict.parse(example_xml)

templateDefinition = "This is a template.\n" \
                     "Example: $example\n" \
                     "Example: $example.codes\n" \
                     "Example: $example.codes.code[0]"
template = Template(templateDefinition, searchList=[example_dict])
print(str(template))

Now if I change the input XML to be contained with a <request> root element (instead of <example>), and the template code from $example to $request it breaks. It would appear that $request is a reserved word in Cheetah3. Is there anyway around that, short of changing the root XML element before using Cheetah3?

Vy Do
  • 46,709
  • 59
  • 215
  • 313
Cynan
  • 160
  • 1
  • 5
  • Can you describe "it breaks" in a little more detail? For example, do you get an error message and if so, what is it? – JonSG May 11 '23 at 13:29
  • (Cheetah maintainer is here.) `$request` returns `None`. Strange. I'm investigating… – phd May 11 '23 at 13:45

2 Answers2

1

request is a special variable in Cheetah3, lets just try to rename the variable.

#!/usr/bin/env python

import xmltodict
from Cheetah.Template import Template


with open('example.xml', 'r') as f:
    example_xml = f.read()
example_dict = xmltodict.parse(example_xml)

# Rename 'request' to '_request' or any other name that is not reserved
if 'request' in example_dict:
    example_dict['_request'] = example_dict.pop('request')

templateDefinition = "This is a template.\n" \
                     "Example: $_request\n" \
                     "Example: $_request.codes\n" \
                     "Example: $_request.codes.code[0]"
template = Template(templateDefinition, searchList=[example_dict])
print(str(template))
Saxtheowl
  • 4,136
  • 5
  • 23
  • 32
1

(Cheetah maintainer is here.)

Class Template has a base class Servlet that declares a few class-level names that become reserved attributes.

For your current code the solution is to remove the offending attribute:

from Cheetah.Servlet import Servlet
del Servlet.request

The real solution would be to allow searchList to override class attributes or to divorce Servlet and Template (or to remove Servlet completely — it was created for Webware which was abandoned long ago). Both would be breaking changes and require a new major release.

phd
  • 82,685
  • 13
  • 120
  • 165
  • Thank you. I'm going to do for this as I don't need this module, however I've marked the other as the official answer as this solution may not work for everyone. I appreciate your answer though. – Cynan May 11 '23 at 16:57