Transformation Templates in Kid
This is the second post in response to cross-breading ZPT and XSLT. I’d like to dig into how I’d like templating to work in Kid and Leslie opens the door for me:
… maybe this is the sort of thing Ryan’s thinking about– I wonder how hard it would be to hack this into Kid? It would give only a subset of XSLT’s capabilities in trade for simplicity, and would only offer the
pullapproach, but it would give XML-pipelining to a ZPT-ish technology.
I’m not sure where to start so I’ll just dump out a little piece of a Kid template I’ve written as a unit test (i.e. there’s no code that processes this yet but it’s what I want to happen):
<p kid:match="test">
This is a test. This paragraph was inserted in place of a
<test> element found in the source document.
</p>
The XSLT equivalent would be:
<xsl:template match="test">
<p>This is a test. This paragraph was inserted in place of a
<test> element found in the source document.</p>
</xsl:template>
Both examples transform this document:
<testdoc>
<test>bla bla bla</test>
</testdoc>
… into this:
<testdoc>
<p>This is a test. This paragraph was inserted in place of a
<test> element found in the source document.</p>
</testdoc>
That’s a simple example but serves to illustrate the general concept
of specifying match criteria to trigger template
invocation. To me this is far superior to, let’s say, the ZPT/METAL
model where the source document must specify a macro
explicitly:
<testdoc>
<span metal:use-macro="test" tal:omit-tag=""/>
</testdoc>
Bringing XSLTish templates to Kid gets complex fast. In XSLT, the
match value is an XPath match expression and lets you get pretty
crazy with specifying when a template matches a node in the source
document:
<xsl:template match="pet[@kind = 'dog' and ../@name = 'Jack']">
...
That matches all <pet> elements with a kind attribute of
dog
and whose parent has a name attribute of Jack
. I’m
not sure what the best way to do this in Kid would be. We could make
kid:match a Python expression but there’s a couple of issues with
that. First, the expression would be verbose:
<p kid:match="context.tag = 'pet' and context.items['kind'] == 'dog'
and context.parent.items['name'] = 'Jack'">
Too loud.
Second, there’s a performance penalty with using expressions. Each
element in the source document would have to be run through n
expressions to see if any templates match. If kid:match were just a
tag name, we could do a dictionary lookup, but we’d lose a valuable
piece of what makes XSLT templates so powerful.
The other option would be to try to use XPath match expressions in Kid exactly like they’re used in XSLT. I’m not completely opposed to this idea but ElementTree, which I’m pretty committed to at this point, supports only light XPath functionality.
But yeah, I plan to steal as much from XSLT’s template approach as
possible while keeping things somewhat sane and simple. If there’s
any ideas or opinions out there, please let me know.
I’ve got one more post in me on this topic that I hope to get out either tonight or tomorrow. It will be on the ElementTree based pullparser I’ve been working on and how it plays into Kid’s templating system.