views:

557

answers:

2

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?

+2  A: 

Genshi.builder is for "programmatically generating markup streams"[1]. I believe the purpose of it is as a backend for the templating language. You're probably looking for the templating language for generating a whole page.

You can, however do the following:

>>> import genshi.output
>>> genshi.output.DocType('html')
('html', '-//W3C//DTD HTML 4.01//EN', 'http://www.w3.org/TR/html4/strict.dtd')

See other Doctypes here: http://genshi.edgewall.org/wiki/ApiDocs/genshi.output#genshi.output:DocType

[1] genshi.builder.__doc__
alif
is there a way to build an html document using genshi, though? i'm looking for something similar to stan. if this isn't an appropriate use of genshi, that's fine, but i would like to know if this is the case.
Jeremy Cantrell
+2  A: 

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.

John Millikin
this makes sense. sounds like something you might use to build an html fragment to load into a page using ajax or something?
Jeremy Cantrell
Even for small AJAX pages I prefer templates, because they tend to just be simple "if logged in, show name" logic and parameter substitution. builder.tag is for when there's something really complex that I can't figure out how to write nicely with a template.
John Millikin