Next / Previous / Contents / TCC Help System / NM Tech homepage

13. etbuilder.py: A simplified XML builder module

If you are building a lot of XML, it can be somewhat cumbersome to take several lines of code to build a single element. For elements with text content, you'll write a lot of two-line sequences like this:

    mainTitle  =  et.Element('h1')
    mainTitle.text  =  "Welcome to Your Title Here!"

The brilliant and productive Fredrik Lundh has written a very nice module called builder.py that makes building XML a lot easier.

13.1. Using the etbuilder module

Instead of importing the ElementTree package as et, use this importation:

from etbuilder import et, E

The name E is a factory object that creates et.Element instances.

Here is the calling sequence for E:

E(tag, *p, **kw)

The first argument, tag, is the element's name as a string. The return value is a new et.Element instance.

You can supply any number of positional arguments p, followed by any number of keyword arguments. The interpretation of each argument depends on its type. The displays with “>>>” prompts are interactive examples.

  • Any keyword argument of the form “name=value” becomes an XML attribute “name='value'” of the new element.

    >>> colElt=E('col', valign='top', align='left')
    >>> et.tostring(colElt)
    '<col align="left" valign="top" />'
    
  • String arguments are added to the content of the tag.

    >>> p14 = E("p", "Welcome to ", "Your Paragraph Here.")
    >>> et.tostring(p14)
    '<p>Welcome to Your Paragraph Here.</p>'
    
  • An argument of type int is converted to a string and added to the tag's content.

  • If you pass a dictionary to the factory, its members also become XML attributes. For instance, you might create an XHTML table cell element like this:

    >>> cell = E('td', {'valign': 'top', 'align': 'right'}, 14)
    >>> et.tostring(cell)
    '<td align="right" valign="top">14</td>'
    

  • You can pass in an et.Element instance, and it becomes a child element of the element being built. This allows you to nest calls within calls, like this:

    >>> head = E('head',
    ...    E('title', 'Your Page Title Here'),
    ...    E('link', rel='stylesheet', href='/tcc/style.css'))
    >>> print et.tostring(head, pretty_print=True)
    <head>
      <title>Your Page Title Here</title>
      <link href="/tcc/style.css" rel="stylesheet" />
    </head>
    

This module has one more nice wrinkle. If the name of the tag you are creating is also a valid Python name, you can use that name as the name of a method call on the E instance. That is,

E.name(...)

is functionally equivalent to

E("name", ...)

Here is an example:

>>> head = E.head(
...    E.title('Your title'),
...    E.link(rel='stylesheet', href='/tcc/style.css'))
>>> print et.tostring(head, pretty_print=True)
<head>
  <title>Your title</title>
  <link href="/tcc/style.css" rel="stylesheet" />
</head>