Posts
Search
Contact
Cookies
About
RSS

WSGI and simple xhtml DOM creation

Added 17 Nov 2022, 9:56 p.m. edited 18 Jun 2023, 1:12 a.m.

I've found creating web content using a DOM (Document Object Model) very convenient (in more than one language). It allows valid document creation to happen naturally - it's actually quite difficult for example to miss match end tags and have one tag beginning inside a tag and ending outside it, something that is all too easy to do, when "manually" creating web content.

Investigating Python as web creation language lead unsurprisingly to WSGI, but before diving into some over complex framework (don't get me started on flasks ORM !!!) I decided to begin experimenting with just Python and WSGI at the lowest possible level. You might think this masochistic and you could be correct but a thorough understanding of the foundations you're later relying on can often provide unexpected dividends.

Configuring Apache was trivial a simple 2 liner!

LoadModule wsgi_module /usr/libexec/httpd/mod_wsgi.so
WSGIScriptAlias /wsgi /srv/www/apache/wsgi/test.py

I found the first XML module I came across just to get something working xml.dom.minidom, and found that creating a valid XHTML document was quite easy, leaving aside just for now the boiler plate of document specifications, lets look at adding a simple tag and content to a DOM.

def simple_app(environ, start_response):
    
    dom, body = getBody("WSGI example.");
    
    p = dom.createElement("p")
    p.appendChild(dom.createTextNode('Hello World !'))
    body.appendChild(p)
    
    output = dom.toprettyxml(encoding='utf-8')
    
    status = '200 OK'
    headers = [('Content-type', 'text/html'),
               ('Content-Length', str(len(output)))]
    start_response(status, headers)
        
    yield output

# mod_wsgi need the *application* variable to serve our small app
application = simple_app

I dare say with a little effort I can streamline adding a tag and even content into a more convenient one liner returning a reference to the tag (you might want to attach further structure to it - for example a table tag needs a hierarchy of tags attached to it)

But in essence the basics are rather simple, the only thing missing is the dom and body creation, which you can see in the complete source below.

Being rather encouraged with the simplicity of this quick hack, I rather think I'll be taking it further.

Enjoy!

# /srv/www/apache/wsgi/test.py

from xml.dom.minidom import getDOMImplementation, Document

def getBody(title):
    impl = getDOMImplementation()
    dt = impl.createDocumentType(
        "html",
        "-//W3C//DTD XHTML 1.0 Strict//EN",
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd",
    )
    dom = impl.createDocument("http://www.w3.org/1999/xhtml", "html", dt)
    html = dom.documentElement
    html.setAttribute("xmlns","http://www.w3.org/1999/xhtml")
    
    head = dom.createElement("head")
    html.appendChild(head)
    
    t = dom.createElement('title')
    t.appendChild(dom.createTextNode(title))
    head.appendChild(t)
    
    body = dom.createElement("body")
    html.appendChild(body)
    return (dom, body)

def simple_app(environ, start_response):
    
    dom, body = getBody("WSGI example.");
    
    p = dom.createElement("p")
    p.appendChild(dom.createTextNode('Hello World !'))
    body.appendChild(p)
    
    output = dom.toprettyxml(encoding='utf-8')
    
    status = '200 OK'
    headers = [('Content-type', 'text/html'),
               ('Content-Length', str(len(output)))]
    start_response(status, headers)
        
    yield output

# mod_wsgi uses the application variable, the simple_app function is the entry point
application = simple_app