A few months ago in "Sane template-like output for Amara" I discussed ideas for making the Amara output API a little bit more competitive with full-blown templating systems such as XSLT, without adopting all the madness of template frameworks.
I just checked in the simplest patch that does the trick. Here is an example from the previous article:
Amara 1.0 code:
person_elem = newdoc.xml_element( u'person', attributes={u'name': unicode(person.name)} ) newdoc.xml_append(person_elem)
Proposed Amara 1.2 code:
newdoc.xml_append_template("<person name='{person.name}'/>")
What I actually checked into CVS today for Amara 1.2:
newdoc.xml_append_fragment("<person name='%s'/>"%person.name)
That has the advantage of leaning as much as possible on an existing Python concept (formatted strings). As the method name indicates, this is conceptually no longer a template, but rather a fragment of XML in text form. The magic for Amara is in allowing one to dynamically create XML objects from such fragments. I think this is a unique capability (shared with 4Suite's MarkupWriter) for Python XML output APIs (I have no doubt you'll let me know if I'm wrong).
Also, I think the approach I settled on is best in light of the three "things to ponder" from the older article.
- Security. Again I'm leaning on a well-known facility of Python, and not introducing any new holes. The original proposal would have opened up possible issues with tainted strings in the template expressions.
- String or Unicode? I went with strings for the fragments. It's up to the developer to make sure that however he constructs the XML fragment, the result is a plain string and not a Unicode object.
-
separation of model and presentation. There is a very clear
separation between Python operations to build a string XML fragment
(these are usually the data model objects), and any transforms applied
to the resulting XML binding objects (this is usually the separate
presentation side). Sure a determined developer can write spaghetti,
but I think that with
xml_append_fragment
it's possible and natural to have a clean separation. With most template systems, this is very hard to achieve.
One other thing to mention is that the dynamic incorporation of the new fragment into the XML binding makes this a potential building block for pipelined processing architecture.
def process_link(body, href, content): body.xml_append_fragment('%s'%(href, content)) #Send the "a" element object that was just appended to #the next pipeline stage check_unique(body.a[-1]) return def check_unique(a_node): if not a_node.href in g_link_dict: #index the href to the link text (a element text content) g_link_dict[a_node.href] = unicode(a_node) return