views:

171

answers:

2
class tree:
    def __init__(self, name='a', childs=[]):
        self.name = name
        self.childs = childs

output:

<ul>
    <li>
    Introduction
    <ul>
        <li>Sub Intro</li>
    </ul>
    </li>

    <li>Module 1</li>
</ul>

Sorry, my English is poor.

A: 

Maybe something like this:

NEW=object()
END=object()

class tree:
    def __init__(self, name='a', childs=[]):
        self.name = name
        self.childs = childs

    def __str__(self):
        indent=0
        result=[]
        for i in self.childs:
            if i is NEW:
                result.append('%s<ul>\n'%('    '*indent))
                indent+=1
            elif i is END:                
                indent-=1
                result.append('%s</ul>\n'%('    '*indent))
            else:
                result.append('%s<li>%s</li>\n'%('    '*indent, i))
        return ''.join(result)



print tree('test', [NEW, 'Introduction', NEW, 'Sub Intro', END, 'Module 1', END])
Florian Diesch
+1  A: 

To generate nested lists without recursion you'd simply keep track of your nesting level, incrementing it as you traverse into deeper levels of nesting and decrementing it as you traverse back upwards.

The natural approach, for handling things like closing tags, would be to maintain a simple stack (Python list) and push the closing tags onto it as you insert their corresponding opening tags into the output stream. You'd then pop these off as you traverse out of any level of nesting.

You don't say anything about your input format ... so let's pretend that it looks something like:

= Introduction
== Sub Intro
= Module 1

Then something like:

 def pref_txt_to_ul(txt):
    nesting = 0
    closing_tags = list()
    for x in txt:
        if len(x.split()) < 2:
            continue
        prefix, content = x.split(None,1)
        nd = len(prefix)           ## new depth
        assert prefix == "=" * nd  ## First "word" is all = characters

        if nd > nesting:
            print "\n", " " * nesting * 4, "<ul>" * (nd - nesting), ## Push new opening tags into output
            closing_tags.append('</ul>' * (nd - nesting))  ## push closing tags for later
        elif nd < nesting:
            for x in range(nesting - nd):
                if closing_tags:
                    print " " * nesting * 4, closing_tags.pop(),  ## Pop closing tags
        nesting = nd
        print "\n", " " * nesting * 4, "<li>%s</li>" % content,  # push out this item (at new depth)
    ## After all text is done:
    while closing_tags:
        print closing_tags.pop(),   # Pop off remaining cloing tags

... should do the trick (albeit, rather crudely).

Note that I'm not actually enforcing a rule that one should only increase the nesting level in increments of one. Degenerate input that go from = to ====== in one step would generate extraneous tags and push extraneous tags into the closing stack.

Note: I'm only answering the explicit question about how to handle nesting without recursion. One might infer from your example (using HTML unordered list tags) that your real goal is to generate valid HTML. In that case there are a wealth of Python tools that are far better suited to that task then any crude text munging I'm doing in this example. A Yahoo or Google search on: Python "generate HTML" will return many thousands of pages about ways to do this and the many available tools for this.

(I remember that I used HTMLgen years ago, and I see that it's still available as a Debian package, but it seems to have fallen off of PyPI ... the Python Package Index. There are undoubtedly much more recently updated packages out there. Most people seem to use templating engines such as Genshi or Mako, for example).

Jim Dennis
god job thank very much
But this presumes his input is sequential, and not a tree. If he really has a tree data structure as input, this isn't helpful. The hard part about doing trees without recursing is walking the tree - something you don't have to do here.
Nick Bastin