I try to create an open div
tag condition and close a div
tag in another condition with TAL in a Zope Page Template but I'm not allowed to overlap tags.
Here is my code :
<div id="notaccordion">
<tal:x repeat="item python:range(26)">
<tal:x define="global block_name python:current.values()[0]['block_name']">
<tal:x condition="python:isDone">
</div>
</tal:x>
<tal:x condition="python:not isDone">
<tal:x replace="python:block_name">
</tal:x>
<div>
</tal:x>
</tal:x>
</tal:x>
</div>
The important part is:
<tal:x condition="python:isDone">
</div>
</tal:x>
And here is the error.
Compilation failed
zope.tal.taldefs.TALError: TAL attributes on <tal:x> require explicit </tal:x>
I tried with a Python script but it didn't work either.
<div id="notaccordion">
<tal:x repeat="item python:range(26)">
<tal:x define="global block_name python:current.values()[0]['block_name']">
<tal:x condition="python:isDone">
<tal:x content="python:context[close_div]()">
</tal:x>
</tal:x>
<tal:x condition="python:not isDone">
<tal:x replace="python:block_name">
</tal:x>
<tal:x content="python:context[open_div]()">
</tal:x>
</tal:x>
</tal:x>
</tal:x>
</div>
With close_div
script:
print '</div>'
return printed
It returns </div>
instead of </div>
If you wonder why I'm doing it. I have a tree structure that I need to display. Since I (think I) can't do it recursively, I try to emulate it using a LIFO list. And current
is my current node.
I try to achieve this (node is dict of dict... used as a tree) :
lifo = list()
lifo.append([node, False])
while lifo:
current, isDone = lifo[-1]
block = current.keys()[0]
if isDone:
print '</div>'
lifo.pop()
else:
lifo[-1][1] = True
print '<div>'
print block
children = current[block].get('children', {})
if children:
for childBlock, childValue in children.items():
lifo.append([{childBlock:childValue}, False])
Any help or suggestion is appreciated
Page templates have to be valid XML, so you cannot just arbitrarily include tags willy nilly. Tree structures are best handled recursively (perhaps with macro snippets):
<metal:recurse define-macro="list">
<ul>
<li tal:repeat="el elements">
<span tal:content="el/id">element id</span>
<metal:block tal:condition="el/children"
tal:define="elements el/children">
<div metal:use-macro="template/macros/list" />
</metal:recurse>
</li>
</ul>
</metal:recurse>
The Plone navigation portlet, for example, also uses a separate macro template for each level, calling into itself to render children (recurse
is the same template).
For your specific method using a open_div
or close_div
script, you need to mark the content value as structure
to prevent the automatic HTML escaping from taking place:
<tal:x content="structure python:context[open_div]()">