Search code examples
pythonhtmltemplatesgenshi

How do I use genshi.builder to programmatically build an HTML document?


I recently discovered the genshi.builder module. It reminds me of Divmod Nevow's Stan module. How would one use genshi.builder.tag to build an HTML document with a particular doctype? Or is this even a good thing to do? If not, what is the right way?


Solution

  • It's not possible to build an entire page using just genshi.builder.tag -- you would need to perform some surgery on the resulting stream to insert the doctype. Besides, the resulting code would look horrific. The recommended way to use Genshi is to use a separate template file, generate a stream from it, and then render that stream to the output type you want.

    genshi.builder.tag is mostly useful for when you need to generate simple markup from within Python, such as when you're building a form or doing some sort of logic-heavy modification of the output.

    See documentation for:

    If you really want to generate a full document using only builder.tag, this (completely untested) code could be a good starting point:

    from itertools import chain
    from genshi.core import DOCTYPE, Stream
    from genshi.output import DocType
    from genshi.builder import tag as t
    
    # Build the page using `genshi.builder.tag`
    page = t.html (t.head (t.title ("Hello world!")), t.body (t.div ("Body text")))
    
    # Convert the page element into a stream
    stream = page.generate ()
    
    # Chain the page stream with a stream containing only an HTML4 doctype declaration
    stream = Stream (chain ([(DOCTYPE, DocType.get ('html4'), None)], stream))
    
    # Convert the stream to text using the "html" renderer (could also be xml, xhtml, text, etc)
    text = stream.render ('html')
    

    The resulting page will have no whitespace in it -- it'll look normal, but you'll have a hard time reading the source code because it will be entirely on one line. Implementing appropriate filters to add whitespace is left as an exercise to the reader.