Tags - Using and Creating
  1. What is a Tag?
  2. Creating a New Tag Manually
  3. Creating New Tags the Right Way
  4. Tagsets included with Brevé
  5. Tag.walk

Back to Main Documentation

What is a Tag?

The core concept behind Brevé tags is that they are instances of a quite simple Python class that overrides the __getitem__ and __str__ methods. Because of this, it's quite easy to modify them or define new tags.

Creating a New Tag Manually

The method explained here is mostly for illustration. It's not the suggested way of creating Brevé tags.

Let's say you wanted to create a tag called "foo". To do so, you must derive from breve.tags.Proto. Proto requires only one argument: the name of the tag.

from breve.tags import Proto

foo = Proto ( 'foo' )

Now, you can use foo as any other tag:

print foo ( style='fancy' ) [ 'hello' ]

This would output:

<foo style="fancy">hello</foo>

To make your foo tag available in a Brevé template requires a bit more work. This topic is covered below.

Creating New Tags the Right Way

You can create tag description files (which are Python modules) by hand or use the xsd2breve script from the tools/ directory of the source distribution.

Here's a simple example showing how to describe the Google sitemap [1] schema:

# sitemap.py
from breve.tags import Proto

xmlns = "http://www.google.com/schemas/sitemap/0.84/sitemap.xsd"
doctype = "" # required, but not used here
tag_names = [ "changefreq", "lastmod", "loc", "priority", "url", "urlset" ]
tags = { }
for t in tag_names:
    tags [ t ] = Proto ( t )

You could have also generated this exact file with using the xsd2breve script:

xsd2breve http://www.google.com/schemas/sitemap/0.84/sitemap.xsd > sitemap.py

Assuming you have now have sitemap.py somewhere on your Python path, you would use:

from breve import Template
import sitemap

vars = dict ( loc = 'http://www.example.com/',
              lastmod = '2005-01-01',
              changefreq = 'monthly',
              priority = 0.8 )
t = Template ( tags = sitemap.tags, xmlns = sitemap.xmlns )
t.namespace = 'v'
t.render ( 'mytemplate', vars = vars )

Note that we set the template variable namespace to "v" in order to avoid clashing with our custom tag names.

Next, we create our template:

# mytemplate.b
urlset ( xmlns = xmlns ) [
    url [
        loc [ v.loc ],
        lastmod [ v.lastmod ],
        changefreq [ v.changefreq ],
        priority [ v.priority ]
    ]
]

which would render as:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">
    <url>
        <loc>http://www.example.com/</loc>
        <lastmod>2005-01-01</lastmod>
        <changefreq>monthly</changefreq>
        <priority>0.8</priority>
    </url>
</urlset>

Custom Tags and Buffet

The Buffet adapter also supports rendering custom tags. Simply pass the name of your tag definition module (which must be on the Python path) as the value of "format":

from breve.tags import Namespace

# turbogears example
@expose ( 'breve:sitemap', format = 'sitemap' )
def sitemap ( self ):
    return dict ( v = Namespace (
        loc = 'http://www.example.com/',
        lastmod = '2005-01-01',
        changefreq = 'monthly',
        priority = 0.8
    ) )

The Namespace is necessary as TurboGears provides no mechanism for passing extra arguments to template engines.

Tagsets Included with Brevé

Brevé ships with a few default tagsets. While all tagsets share a common set of features, some of them have utility and helper tags to assist with the particular XML dialect they represent.

XHTML Tags

XHTML tags are available in the breve.tags.html module. This is the default tagset for Brevé if not overridden.

This tagset has a few helper tags and functions:

  • inlineJS - Useful for embedding JavaScript within a page.
  • checkbox - Equivalent to input ( type='checkbox' ) except that it handles properly setting the checked attribute to "checked" if the attribute evaluates to True.
  • option - Similar to checkbox above, except that it handles properly setting the selected attribute to "selected" if the attribute selected attribute evaluates to True.
  • lorem_ipsum - Silly content filler. Renders as a bunch of "lorem ipsum" text.

Back to Main Documentation

Tag.walk

As of Brevé 1.2, Tags have a new method walk ( callback, tags_only = False ). This feature traverses the DOM starting with the tag instance the method is invoked upon.

For each child of that Tag, the callback function is called with two arguments: the current element and whether or not the element is a Tag instance . If the callback returns False, the traversal is discontinued. Any other value (including None) means the traversal is to continue.

from breve.flatten import flatten
from breve.tags.html import tags
globals( ).update ( tags )

logged_in = False
username = None

template = html [
    body [
       div ( id='login-form', style='display:none;' ),
       div ( id='content' )
    ]
]

def fill_login ( tag, is_tag ):
    if tag.attrs.get ( 'id', None ) == 'login-form':
        if not logged_in:
            tag.children.append (
                form ( action = '/login' ) [
                    'username: ', input ( type = 'text', name = 'username' ),
                    'password: ', input ( type = 'password', name = 'password' ),
                    input ( type = 'submit', value = 'submit' )
                ]
            )
        else:
            tag.children.append (
                span ( id = 'hello-user' ) [ 'Hello %s' % username ]
            )
        tag.attrs [ 'style' ] = "display: block;"
        return False

template.walk ( fill_login, tags_only = True )
print flatten ( template )

This would result in:

<html>
  <body>
    <div style="display: block;" id="login-form">
      <form action="/login">
        username: <input type="text" name="username"></input>
        password: <input type="password" name="password"></input>
        <input type="submit" value="submit"></input>
      </form>
    </div>
    <div id="content"></div>
  </body>
</html>

Back to Main Documentation

[1]https://www.google.com/webmasters/tools/docs/en/protocol.html
edit page
Back to top
Rendered using Brevé 1.2.6Copyright © 2007, Cliff Wells