Showing posts with label markup. Show all posts
Showing posts with label markup. Show all posts

Wednesday, October 14, 2009

Working With Elements

There is virtually no escaping XML markup in one form or another when building modern applications. Whether HTML, SOAP, or some other dialect, XML has become an important standard to support in applications. Even if the application isn't a web application.

Thankfully, most programming languages have built-in library support for reading and manipulating XML. Some are better than others. For instance, the ElementTree Python package is probably the easiest library for developers to work with. It doesn't add unnecessary complexity on top of a simplistic standard.

The ElementTree package is now part of the growing set of standard Python modules included in the distribution. Since the module can be used to both read and write XML data, it cuts down on dependencies. Most XML libraries support both reading and writing of XML data, but like any other library type, it may do one well but not the other.

The following is an example of how easy it is to not only use the ElementTree package to build an XML document, but also to add abstractions around the elements that are created.
#Example; Abstracting elements.

#Do element tree imports.
from xml.etree.ElementTree import Element, tostring

#The base DOM element.
class Dom(object):
def __init__(self, name, **kw):

#Create the element and set the attributes.
self._element=Element(name)
for i in kw.keys():
self._element.attrib[i]=kw[i]

#Set an element attribute.
def __setitem__(self, name, value):
self._element.attrib[name]=value

#Get an attribute.
def __getitem__(self, name):
return self._element.attrib(name)

#Append a sub-element.
def append(self, value):
self._element.append(value._element)

#A specialized Dom class for accepting raw text content.
class DomContent(Dom):

#Constructor.
def __init__(self, name, content=None, **kw):
Dom.__init__(self, name, **kw)
self._element.text=content

#Common HTML elements.
class Head(Dom):
def __init__(self):
Dom.__init__(self, "head")

class Title(DomContent):
def __init__(self, content, **kw):
DomContent.__init__(self, "title", content, **kw)

class Body(Dom):
def __init__(self):
Dom.__init__(self, "body")

class Div(DomContent):
def __init__(self, content, **kw):
DomContent.__init__(self, "div", content, **kw)

#The root document.
class Document(Dom):
def __init__(self, title):
Dom.__init__(self, "html")

#Initialize the head, title, and body elements.
self.head=Head()
self.title=Title(title)
self.body=Body()

#Add the title element to the head element.
self.head.append(self.title)

#Add the head and body elements to the document.
self.append(self.head)
self.append(self.body)

#Actual output.
def __str__(self):
return tostring(self._element)

#Main.
if __name__=="__main__":

#Initialize the document with a title.
my_doc=Document("My Document")

#Create a div with content and an attribute.
my_div=Div("My Div", style="float: left;")

#Add the div to the body.
my_doc.body.append(my_div)

#Display.
print my_doc
In this example, we construct a simple HTML page. The Dom class is the topmost level abstraction that we create around ElementTree. The Dom class is meant to represent any HTML tags that are placed in the HTML page. The Dom._element attribute represents the actual ElementTree element. The Dom constructor will give the element attribute values based on what keyword parameters were passed to the constructor. The Dom.__getitem__() and Dom.__setitem__() methods allow element attributes to be get and set respectively. The Dom.append() method allows other Dom instances to be attached to the current instance as a sub-element.

The DomContent class is a simple specialization of the Dom class. The DomContent class accepts an additional content parameter, otherwise, the class isn't really any different than its' base class.

The Head, Title, Body, and Div classes are all standard HTML specializations of the Dom class. The main difference being that Title and Div inherit from DomContent instead of Dom because they support raw text content.

The Document class is a helper type of abstraction. It assembles Dom elements common in all HTML pages we might want to build. It is the Document class that makes the main program trivial to read and understand.

Wednesday, September 30, 2009

Python Cheetah Benchmark

With any web application, no matter what language it may be written in, templates need to be rendered. These are often HTML templates. If there were no templates, just static HTML files, what we would have is a static site as opposed to a web application. The dynamic aspects of the page are filled in by rendering a template. This is the most common approach for several reasons. Chiefly, the user interface is nicely separated from application logic. This, in turn, makes it easier for the user interfaces developers and designers to work without disrupting the logic they aren't concerned with. This also works vice-versa.

The Cheetah template rendering system, written for Python web applications, is a mature one. Cheetah provides a clean, elegant template syntax when compared to other Python template rendering systems. For instance, the syntax constructs are not represented as tags. This provides both flexibility and separation of concerns. Since tags aren't required, Cheetah can be used for templates other than HTML. Also, it is more obvious with Cheetah what is HTML markup and what is template markup.

Below is a very incomplete, sample of how to use Cheetah pragmatically. That is, it is very easy to plug into any potential Python system.
#Example; Timing Cheetah rendering.

#Do imports.
import timeit
from Cheetah.Template import Template

#Rendering test.
def render_cheetah():

#Cheetah template string.
template_str="""<html>
<head>
<title>$title</title>
</head>
<body>$body</body>
</html>"""

#The context supplied to the template; variable substitution.
context={"title":"Cheetah Test", "body":"Cheetah Test"}

#Initialize the Cheetah template object.
template_obj=Template(template_str, searchList=[context])

#Render the template.
str(template_obj)

#Main.
if __name__=="__main__":

#Run the test an print the results.
cheetah_timer=timeit.Timer("render_cheetah()",\
"from __main__ import render_cheetah")
print "Cheetah:",cheetah_timer.timeit(number=1000)

Tuesday, September 22, 2009

Simply HTML

Generating HTML markup in Python applications does not always mean resorting to rendering templates. Using templates to implement the views of an application on the web is a standard practice because it helps to remove the presentation layer. That being said, there is nothing to stop a standard Python module from generating markup while only being concerned with the presentation, not the application logic.

The html Python package provides a very simplistic method in which to generate HTML pragmatically. There is nothing wrong with using this approach as long as the separation of concerns principal is obeyed. This Python package allows developers to generate markup with a single HTML class. This class isn't meant to act as a singleton, but, rather, as a logically-separated string. There is nothing preventing developers from combining HTML instances to provide the final rendering.

The two main features of these HTML instances are that they use simple element methods to construct elements. This adds a nice self-containment to the document while it is under construction. The HTML instances also support the with statement. This provides a context for building child elements as is illustrated below.
#Example; Using the html package.

#Get the HTML class.
from html import HTML

#Main.
if __name__=="__main__":
#Instantiate an HTML document.
html_obj=HTML()

#Construct a HTML element and provide a context.
with html_obj.html():

#Construct a body element with a class,
#and provide a context.
with html_obj.body(klass="my-body"):

#Construct some body elements.
html_obj.h1("Testing 123", klass="my-header")
html_obj.p("Hello World!", klass="my-text")

#Display the markup.
print html_obj