xiº
xiº

Reputation: 4687

Python: convert arbitrarily structured nested list to html

Say I have an arbitrary list:

qw = ['a', [['tag', '1'], ['tag', '2']]]

I need to build html with <blockquote> (just a python string; each element of list should be wrapped in blockquote tag accordingly to hierarchy):

<blockquote> a
    <blockquote> tag
        <blockquote> 1 </blockquote>
    </blockquote>
    <blockquote> tag
        <blockquote> 2 </blockquote>
    </blockquote>
</blockquote>

The result:

render

For example I have a string test='str1str2str34' and some rules to split it into list:

['str1str2str34', [
    ['str1', ['str', '1']], 
    ['str2', ['str', '2']], 
    ['str34', ['str', '3', '4']]
    ]
]

The rendered result based blockquote tags:

render3

So, I trying to change the recursive generator (for flattening a list):

def flatten(l):
    for el in l:
        if isinstance(el, collections.Iterable) and not isinstance(el, basestring):
            for sub in flatten(el):
                yield sub
        else:
            yield el

But really nothing comes of it.

Upvotes: 1

Views: 250

Answers (1)

xi&#186;
xi&#186;

Reputation: 4687

Over time I've come to the solution.

Firstly in my opinion dictionary is more suitable for this case.

To save the order we can use OrderedDict:

j = OrderedDict([
    ('str1str2str34', OrderedDict([
        ('str1', ['str', '1']),
        ('str2', ['str', '2']),
        ('str34', ['str', '3', '4'])
    ]))
])

We use the recursive generator to solve this task:

tag = 'blockquote'

def recurse(d, tag):
    if isinstance(d, (dict, OrderedDict)):
        for k in d:
            yield '<' + tag + '>' + k
            for sub in recurse(d[k], tag):
                yield sub
            yield '</' + tag + '>'
    elif isinstance(d, (list, tuple)):
        d = ['<{1}>{0}</{1}>'.format(el, tag) for el in d]
        yield '<' + tag + '>' + ' '.join(d) + '</' + tag + '>'

print '\n'.join(list(recurse(j, tag)))

Below is prettified html.

<blockquote>str1str2str34
    <blockquote>str1
        <blockquote>
            <blockquote>str</blockquote>
            <blockquote>1</blockquote>
        </blockquote>
    </blockquote>
    <blockquote>str2
        <blockquote>
            <blockquote>str</blockquote>
            <blockquote>2</blockquote>
        </blockquote>
    </blockquote>
    <blockquote>str34
        <blockquote>
            <blockquote>str</blockquote>
            <blockquote>3</blockquote>
            <blockquote>4</blockquote>
        </blockquote>
    </blockquote>
</blockquote>

Upvotes: 1

Related Questions