Question

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 &lt;/div&gt; 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

Was it helpful?

Solution

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]()">
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top