What is it?
License
Download
Installation
Requirements
Classes
Initialization
Objects
Access
Substitution
Attributes
Batch Substitution
State
Concatenation
Repetition
Appending
Iteration
Output
Development
webstring
A Python Template Engine
WHAT IS IT?
webstring is a template engine for programmers whose favorite template language is Python. webstring can be used to generate any text output from a template with the additional advantages of advanced XML and HTML templating using the lxml and cElementTree libraries.

webstring
was designed to meet the following general goals:
  1. To separate model and view logic from controller logic. The advantages of using an MVC architecture are:
    • Clarity: it is easy to tell which parts of an application do what. Code is clearer, more compact, and readable, which can make errors easier to spot, a particularly important feature when more than one developer maintains the code.
    • Modularity: model, view, or controller logic can be upgraded, reused, or replaced with little or no disruption to other parts of an application if they are not mixed together.
    • Division of Labor: designers should design the view, programmers should program the controller, and data architects should design the model.

    webstring enforces MVC by following a pipeline or push template style: Python controller code has to explicitly push data into the template because a webstring template contains no callback logic and therefore cannot itself request data from the controller.
  2. To separate template logic from template data. Template data is text in the template that does not originate from an external source. Template logic controls a template's output when when template data and external data are mixed. Template data tells what a template is and template logic tells how it works. The advantages of keeping template data distinct from template logic are similar to the advantages of using an MVC architecture:
    • Clarity: mental clarity is easily achieved when template data and template logic are encapsulated in separate, clearly distinct packages. webstring allows template data to be kept in one file and Python code, its template logic, in another. Text data and logic are fundamentally different beasts: Text data is generally a declarative data format that defines what should be computed. Python is an imperative format that defines how computation should be performed. Separating them is the road to easier maintenance.
    • Modularity: modular template data and template logic can be upgraded, reused, or replaced with little or no disruption to each other. webstring's placeholders are non-invasive markers. Many template engines use some kind of explicit or implicit logic for placeholders. This is not a modular approach: it sharply intertwines not only template logic and data but model, view, and controller logic. webstring keeps template data and template logic separate. Template logic does not have to know anything about the text half of a webstring template except for the name of its placeholders. Template data can be written without any structural awareness that it will ever be template data, let alone by controlled by external template logic written in Python. All it needs are placeholders that identify where external data can be inserted.
    • Division of labor: separating template data from template logic allows for a clean separation of roles: Data architects can design text formats, designers can work on making text look good, and Python programmers can write controller code.
  3. To require only Python for templating. When templating with Python, the minimum requirement is, of course, Python. webstring goes further: its design is based on the proposition that the only tool you need to template text with Python is Python.

    Many template engines use a custom template language, usually with just enough logic to handle variable substitution, condition statements, and loops. Compared with the effort of templating with C or Java, using a custom template language can be a giant step forward in programmer productivity. Using a custom template language with Python, however, is a giant step backwards.

    By design, Python places programmer productivity ahead of computer productivity, an approach that Bruce Eckel nicely summarized as “Python fits your brain”. The average Python programmer can keep the core Python language in their head without constantly checking Python's documentation for information on basic language features. Layering another language on top of Python increases the mental overhead of programming with few compensating advantages. Why use a special purpose template language when the general purpose programming language you already know does the job?
  4. To use Python syntax, idiom, and patterns. The reason for this design goal is similar to the reason behind goal number three: if a programmer has already invested the time to learn Python, why devalue that investment by introducing syntax, idioms, or patterns that are not "Pythonic" into Python templating?

    webstring uses Python syntax, idiom, and patterns exclusively. Template placeholders are mapped to Python objects. These objects implement portions of Python's sequence API and support operations like access by position, concatenation, and repetition. They can also be manipulated like Python strings. If a webstring operation has an exact analog in existing Python usage, the Python analog was used. Where no exact one-to-one analog exists, names of methods and attributes from the Python standard library and third-party modules where the usage approaches webstring's were used.

    Making methods as Pythonic as possible was a major emphasis of webstring's development. Use webstring should be painless for a Python programmer; its usage should be a direct and natural outgrowth of their previous Python experience.
  5. To play well with other Python software. webstring is designed to be imported into another piece of Python software and used without much modification or complexity. Its API is Pythonic and many of its operations use standard Python syntax. All data inputs into webstring use standard Python data structures like strings, lists, and dictionaries.

    webstring provides classes that implement the Python Web Server Gateway Interface (WSGI) standard that provides a common way for Python web applications to run on different web servers. These classes, WSGITemplate, WSGIHTMLTemplate, and WSGITextTemplate, are WSGI middleware that allows WSGI-compliant Python web applications to dynamically output XML, HTML, and text.

    webstring also includes a class, TurboWebstring, that implements the TurboGears/Buffet template plugin API.
webstring's XML and HTML templating was designed to meet the following goals:
  1. To use XML as a data format, not a programming language. XML has several disadvantages as a programming language. First of all, it was never intended to be a programming language. Tim Berners-Lee, creator of HTML and a driving force behind the standardization of XML, commented on HTML and, by implication, on XML that, "I chose HTML not to be a programming language because I wanted different programs to do different things with it: present it differently, extract tables of contents, index it, and so on." It must also be structured in ways that, while useful for a data format, are unnecessarily verbose, restrictive, and repetitive for a programming language, especially if the programming language is Python.

    XML is also frequently worked on by non-programmers. Mixing logic and XML may force non-programmers to acquire a programming awareness that may be counterproductive to their jobs. They might also be forced to wait for a programmer to change the data format before they can work on it (and vice versa).

    XML is for data. Python is for logic.

  2. To use existing XML formats. Many template engines use custom XML syntax for placeholders, usually either custom comments, elements, or attributes. Existing XML formats must often include this template engine specific XML to work with these template engines. This can violate the MVC advantages of clarity, modularity, and division of labor. It can make using outside software that provides special processing for a specific XML format more difficult. It can lead to template engine lock-in since prohibitively extensive modifications may be required to move an XML template from one template engine to another.

    webstring is designed to work with existing XML formats as they are. The only modifications to an XML document that webstring requires is assigning a unique identifier to each element used as a placeholder. webstring can use any XML attribute as a placeholder but, by default, it uses the ID attribute. This closely follows the spirit of the W3C xml:id standard which makes the ID attribute the standard mechanism for uniquely identifying elements within an XML document.
  3. To hide the parts of an XML document that are not being used. webstring uses a component API style: it only exposes elements that are marked with a placeholder and usually only "the elements in the template that need to be manipulated are marked". Each element marked with a placeholder can be accessed, evaluated, and manipulated separately. Elements and attributes that do not have a placeholder remain hidden and do not exist from the programmer or application's perspective.
  4. To use the best Python XML libraries. cElementTree provides a high performance library with a highly Pythonic API for processing XML with Python. lxml implements the same API as cElementTree but adds additional features. While cElementTree supports most of the XML 1.1 standard, XML namespaces, and parts of the XPath 1.0 standard, lxml, since it's a binding for the libxml2 and libxslt libraries, supports those standards plus XSLT, XInclude, XML Schema, RelaxNG, Xpointer, and xml:id. Since libxml2 and libxslt are written in C, lxml's performance approaches that of cElementTree.

    webstring does not force its users to pick between best of breed Python XML processing libraries. They can use the library that best fits their needs while using the same simple yet powerful API.
  5. To bridge HTML and XML. XML purists would like to leave HTML behind. But they can't. To quote the Kid FAQ:

    Q: But isn't tag-soup like HTML 4 evil?

    A: No. HTML 4.01 isn't XML but it's the best option for serving pages at present because all browsers have relatively strong support for it. Serving XHTML as text/html has serious issues and not all browsers (IE <= 7.0) support XHTML as application/xhtml+xml.

    However, maintaining content in an XML based format is advantageous because you can perform validation, transformations, and other stuff using readily available tools. It's possible to have the best of both worlds: HTML 4.01 for the browser and XHTML (or some custom XML format) for the server.

    Some of us still believe that XHTML will eventually be supported well, and that when it does, it will be the way to go. You should be able to "flip a switch, make it work" when that day comes instead of doing a massive migration.

    webstring's HTMLTemplate class handles these cases. It can take HTML, even if it is horribly broken, transform it into valid XHTML, and correctly output it as HTML 4.01, XHTML 1.0, or XHTML 1.1 following the standard and practice of the W3C.

LICENSE
webstring is distributed under a BSD license.
DOWNLOAD
webstring is available from the CheeseShop as a: webstring's current release is 0.5 (1.4.2007). The change log for 0.5 is available here: CHANGELOG-0.5.

lwebstring was a standalone lxml-based implementation of webstring available from the CheeseShop as a: The last lwebstring release was 0.5 (10.5.2006). After this release, lwebstring was incorporated into webstring proper. The change log for lwebstring 0.5 is available here: CHANGELOG-lwebstring-0.5.
INSTALLATION
To install webstring using easy_install, run the following command with administrative privileges:
easy_install webstring
REQUIREMENTS
webstring requires cElementTree, elementtree, and lxml. webstring can use either cElementTree or lxml as its XML processing library. Installing webstring with easy_install automatically downloads and installs cElementTree, elementtree, and lxml if necessary along with webstring.

elementtidy is required for webstring's HTMLTemplate class if you need to handle broken HTML with cElementTree.

webstring has been tested and verified to work with Python 2.4 and Python 2.5.

CLASSES
webstring comes with the following specialized classes: These classes can be used individually or accessed through webstring's Template class, which acts as a general purpose frontend to all of webstring's specialized classes.
>>> from webstring import Template
The remaining examples in this document use webstring's XmlTemplate as the backend to Template. LxmlTemplate and EtreeTemplate have minor differences in output. In LxmlTemplate, there is no space between the tag name and the closing /> of a closed tag (i.e. <br/> instead of <br />) and in EtreeTemplate there is a space. Attribute order may also vary and namespaces may be handled differently.
INITIALIZATION
A Template object can be initialized empty:
>>> exampleA = Template()
From a file with the fromfile method:
>>> exampleB.fromfile('example.rss')
By passing the path to the file as the first argument to the class constructor:
>>> exampleC = Template('example.rss')
From a string with the fromstring method:
>>> exampleD = Template.fromstring("""<rss version="2.0">
... <channel>
... <title>Example</title>
... <link>http://www.example.org/</link>
... <description>RSS Example</description>
... <language>en-us</language>
... <pubDate id="cpubdate">$month $day, $year</pubDate>
... <lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate> ... <item class="item">
... <title id="title" />
... <link id="link" />
... <guid id="guid" isPermaLink="true" />
... <description id="description" />
... <pubDate id="ipubdate" />
... </item>
... </channel>
... </rss>""")
By passing a string as the first argument to the class constructor:
>>> example = Template("""<rss version="2.0">
... <channel>
... <title>Example</title>
... <link>http://www.example.org/</link>
... <description>RSS Example</description>
... <language>en-us</language>
... <pubDate id="cpubdate">$month $day, $year</pubDate>
... <lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate> ... <item class="item">
... <title id="title" />
... <link id="link" />
... <guid id="guid" isPermaLink="true" />
... <description id="description" />
... <pubDate id="ipubdate" />
... </item>
... </channel>
... </rss>""")
The choice of whether to use lxml and LxmlTemplate or cElementTree and EtreeTemplate is controlled by using the engine keyword passed to the object constructor:
>>> example = Template(engine="lxml")
This selects LxmlTemplate and uses lxml as the XML processing library. LxmlTemplate and lxml support additional advanced XML features like XSLT and XInclude that EtreeTemplate and cElementTree do not.

HTMLTemplate can be selected using the format keyword passed to the object constructor:
>>> example = Template(format="html", engine="lxml")
HTMLTemplate can also be told to use lxml as its HTML processing library by passing the engine keyword together with the format keyword to the object constructor:
>>> example = Template(format="html", engine="lxml")
OBJECTS
webstring automatically maps an XML document to a root object. Any XML element with an XML attribute (by default, id) that uniquely identifies it within an XML document is mapped to a field object and attached to the root object of its parent document.
<pubDate id="cpubdate">$month $day, $year</pubDate>
Groups of fields can be created by assigning a parent element an attribute (by default, class) whose value is a globally unique identifier within an XML document. webstring then maps the parent element to a group object which is attached to the root object of its parent document. Any child elements marked as fields within that parent element are mapped to field objects and attached to the group object.

Group objects cannot contain other group objects.
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
XML attributes of an element marked as a field are mapped to attribute objects and attached to that element's field object.

At maximum, a root's object hierarchy will never be more than four levels deep.

Root level:
>>> example
<Template "root" at db7dd0>
Group level:
>>> example.item
<Template "item" at f5d870>
Field level:
>>> example.item.guid
<Template "guid" at f5da70>
Attribute level:
>>> example.item.guid.isPermaLink
'true'
At minimum, a root object's depth will only be two levels deep.

Root level:
>>> example
<Template "root" at db7dd0>
Field level:
>>> example.cpubdate
<Template "cpubdate" at e7a350>
By default, all elements tagged as fields or groups become part of a root's object hierarchy except for elements marked as groups that have no child elements marked as fields. However, existing fields or groups within an XML document can be excluded or included before or after a root is initialized by using its exclude or include methods.

Exclusion with the exclude method:
>>> example.exclude('cpubdate', 'guid') 
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
</channel>
</rss>
Inclusion with the include method:
>>> example.include('cpubdate', 'guid')
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">$month $day, $year</pubDate>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate> <item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
</channel>
</rss>
Fields and groups can be removed by deleting their object attribute:
>>> del example.cpubdate
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
</channel>
</rss>
A root, field, or group can be set back to its default state by calling its reset method:
>>> example.reset()
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">$month $day, $year</pubDate>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
</channel>
</rss>
ACCESS
Fields can be accessed by object attribute:
>>> example.cpubdate
<Template "cpubdate" at e7a350>
By keyword:
>>> example['cpubdate']
<Template "cpubdate" at e7a350>
By position:
>>> example[0]
<Template "cpubdate" at e7a350>
Groups are accessed the same way:
>>> example.item 
<Template "item" at f5d870>
>>> example['item']
<Template "item" at f5d870>
>>> example[2]
<Template "item" at f5d870>
Fields within a group are accessed by combining its identifier and its group identifier:
>>> example.item.title 
<Template "title" at f5d9b0>
>>> example['item']['title']
<Template "title" at f5d9b0>
>>> example[2][0]
<Template "title" at f5d9b0>
Attributes can be accessed either by object attribute or by keyword:
>>> example.item.guid.isPermaLink
'true'
>>> example['item']['guid']['isPermaLink']
'true'
By default, webstring automatically maps fields, groups, and attributes to object attributes with the same name as the field, group, or attribute's identifier. This "auto-magical" behavior can be disabled by passing a boolean value of False to the class constructor as the second argument when a Template or HTMLTemplate object is initialized:
>>> exampleZ = Template('example.rss', False)
Fields, groups, and attributes can then be accessed by keyword or position but not by named object attribute.
SUBSTITUTION
Text can be substituted into a field by assigning a string to a field's text property:
>>> example.item.description.text = 'Example of assigning text to a field.'
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">June 06, 2006</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description">
Example of assigning text to a field.</description>
<pubDate id="ipubdate" />
</item>
</channel>
</rss>
Text can also be formatted by substituting text into a field's string template. There are two ways to assign a string template to a field. The first way is to embed a string template directly in the XML source:
<pubDate id="cpubdate">$month $day, $year</pubDate>
This string template follows the pattern used by Python's string.Template class where $ identifies a location (e.g. $month) where strings can be substituted into a template to make a new string. A field's template is used to format its text when a dictionary of location identifier/substitute string pairs is assigned to its text property:
>>> example.cpubdate.text = {'month':'June', 'day':'06', 'year':'2006'}
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">
June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
</channel>
</rss>
lastbuilddate's embedded string template follows a pattern used by Python's built-in string formatting where %(name)s identifies locations (e.g. %(month)s) where strings can be substituted into a template to make a new string:
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
String templates following this pattern are used exactly like string templates that follow the string.Template pattern:
>>> example.lastbuilddate.text = {'month':'June', 'day':'06', 'year':'2006'}
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">
June 06, 2006</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
</channel>
</rss>
String templates embedded in an XML document are automatically assigned to a field's template property:
>>> example.cpubdate.template
<string.Template object at 0x00F81F70>
>>> example.lastbuilddate.template
%(month)s %(day)s, %(year)s
The second way to assign a string template to a field is to manually assign it to a field's template property:
>>> example.item.link.template = 'http://www.example.org/rss/$id'
>>> example.item.link.template
<string.Template object at 0x00DB7E70>
>>> example.item.link.text = {'id':'5423093'}
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">June 06, 2006</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link">
http://www.example.org/rss/5423093</link>
<guid id="guid" isPermaLink="true" />
<description id="description">Example of assigning text to a field.</description>
<pubDate id="ipubdate" />
</item>
</channel>
</rss>
String templates can be assigned to multiple fields in one operation by using a root or group's templates method:
>>> example.item.templates({'title':{'text':'Example Title: $content'},
... 'ipubdate':{'text':'$month $day, $year'}})
>>> example.item.title.template
<string.Template object at 0x00EA75B0>
>>> example.item.ipubdate.template
<string.Template object at 0x00EA7690>
>>> example.item.title.text = {'content':'First Example'}
>>> example.item.ipubdate.text = {'month':'June', 'day':'6', 'year':'2006'}
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">June 06, 2006</lastBuildDate>
<item class="item">
<title id="title">
Example Title: First Example</title>
<link id="link">http://www.example.org/rss/5423093</link>
<guid id="guid" isPermaLink="true" />
<description id="description">Example of assigning text to a field.</description>
<pubDate id="ipubdate">
June 6, 2006</pubDate>
</item>
</channel>
</rss>
ATTRIBUTES
The value of an XML attribute can be set by assigning a string to its object attribute:
>>> example.item.guid.isPermaLink = 'false'
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">June 06, 2006</lastBuildDate>
<item class="item">
<title id="title">Example Title: First Example</title>
<link id="link">http://www.example.org/rss/5423093</link>
<guid id="guid" isPermaLink=
"false" />
<description id="description">Example of assigning text to a field.</description>
<pubDate id="ipubdate">June 6, 2006</pubDate>
</item>
</channel>
</rss>
One or more existing attribute values can be changed or one or more new attributes added using a field's update method:
>>> example.item.guid.update({'isPermaLink':'true', 'id':'GUID',
... '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}resource':'http://www.example.org/rss/5423093'})
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">June 06, 2006</lastBuildDate>
<item class="item">
<title id="title">Example Title: First Example</title>
<link id="link">http://www.example.org/rss/5423093</link>
<guid
id="GUID" isPermaLink="true" rdf:resource="http://www.example.org/rss/5423093" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" />
<description id="description">Example of assigning text to a field.</description>
<pubDate id="ipubdate">June 6, 2006</pubDate>
</item>
</channel>
</rss>
One or more string templates for formatting attribute values can be set by assigning a dictionary of attribute name/attribute template pairs to a field's atemplates property:
>>> example.item.guid.atemplates = {
... '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}resource':'http://www.example.org/rss/$guid'}
The attribute value is then formatted by the attribute's template when a dictionary of attribute name/dictionary pairs is passed to the attribute either with the update method:
>>> example.item.guid.update({
... '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}resource':{'guid':'5423094'}})
or by assigning a dictionary of attribute name/dictionary pairs directly to its object attribute:
>>> example.item.guid.resource = {'guid':'5423093'}
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">June 06, 2006</lastBuildDate>
<item class="item">
<title id="title">Example Title: First Example</title>
<link id="link">http://www.example.org/rss/5423093</link>
<guid id="GUID" isPermaLink="true"
rdf:resource="http://www.example.org/rss/5423093" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" />
<description id="description">Example of assigning text to a field.</description>
<pubDate id="ipubdate">June 6, 2006</pubDate>
</item>
</channel>
</rss>
One or more attributes can be removed by using a field's purge method:
>>> example.item.guid.purge('{http://www.w3.org/1999/02/22-rdf-syntax-ns#}resource')
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">June 06, 2006</lastBuildDate>
<item class="item">
<title id="title">Example Title: First Example</title>
<link id="link">http://www.example.org/rss/5423093</link>
<guid id="GUID" isPermaLink="true" />
<description id="description">Example of assigning text to a field.</description>
<pubDate id="ipubdate">June 6, 2006</pubDate>
</item>
</channel>
</rss>
An attribute can also be removed by deleting its object attribute:
>>> example.item.guid.update(
... {'{http://www.w3.org/1999/02/22-rdf-syntax-ns#}resource':'http://www.example.org/rss/5423093'})
>>> del example.item.guid.resource
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">June 06, 2006</lastBuildDate>
<item class="item">
<title id="title">Example Title: First Example</title>
<link id="link">http://www.example.org/rss/5423093</link>
<guid id="guid" isPermaLink="false" />
<description id="description">Example of assigning text to a field.</description>
<pubDate id="ipubdate">June 6, 2006</pubDate>
</item>
</channel>
</rss>
BATCH SUBSTITUTION
The modulo operator can be used to assign templates and substitute text into elements and attributes in one batch substitution. Using the modulo operator without the assignment operator (%) creates a new object. Using the modulo operator with the assignment operator (%=) modifies the left-hand object.

In a batch substitution, text substitutions are given the keyword 'text' and passed in a dictionary to a field:
>>> example.reset()
>>> example.cpubdate %= {'text':{'month':'June', 'day':'06', 'year':'2006'}}
>>> example.lastbuilddate %= {'text':{'month':'June', 'day':'06', 'year':'2006'}}
Template assignments are identified by the keyword 'templates' and text substitutions are identified by the keyword 'subs':
>>> example.item %= {
... 'templates':{
... 'title':{'text':'Example Title: $content'},
... 'ipubdate':{'text':'$month $day, $year'},
... 'link':{'text':'http://www.example.org/rss/$id'}},
... 'subs':((
... {'text':{'content':'First Example'}},
... {'text':{'id':'5423093'}}, {'attrib':{'id':'GUID'}},
... {'text':'http://www.example.org/rss/5423093'},
... 'Example of assigning text to a field.',
... {'text':{'month':'June', 'day':'6', 'year':'2006'}}),)}
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">June 06, 2006</lastBuildDate>
<item class="item">
<title id="title">
Example Title: First Example</title>
<link id="link">
http://www.example.org/rss/5423093</link>
<guid id="GUID" isPermaLink="true">
http://www.example.org/rss/5423093</guid>
<description id="description">
Example of assigning text to a field.</description>
<pubDate id="ipubdate">
June 6, 2006</pubDate>
</item>
</channel>
</rss>
Templates are stored in a dictionary under the name of the field they are assigned to (e.g. 'title'). This dictionary can contain any number of templates up to but not exceeding the number of fields in the root or group to which it is passed. Text templates are string templates that are stored under the keyword 'text'. Attribute templates, stored under the keyword 'attrib', are a dictionary of pairs consisting of an attribute name and a string template .

Substitutions are stored in a tuple. The number of items in a substitution's tuple must be equal to the number of fields in the root or group to which it is passed. Each item in a substitution's tuple can be a string or a dictionary of substitutions. Within a dictionary of substitutions, the keyword 'text' identifies text substitutions, the value of which can be either a string or a dictionary of text template substitutions, and the keyword 'attrib' identifies attribute substitutions, the value of which is a dictionary containing pairs of attribute names and strings or dictionaries of attribute template substitutions. All tuples containing substitutions are put in another tuple and stored under the 'subs' keyword.

The modulo operator can also substitute a dictionary containing pairs of field names and substitutions into every field or group in a root object in one operation:
>>> example %= {
... 'cpubdate':{'text':{'month':'June', 'day':'06', 'year':'2006'}},
... 'lastbuilddate':{'text':{'month':'June', 'day':'06', 'year':'2006'}},
... 'item':{'templates':{'title':{'text':'Example Title: $content'}, ... 'ipubdate':{'text':'$month $day, $year'},
... 'link':{'text':'http://www.example.org/rss/$id'}},
... 'title':{'text':{'content':'First Example'}},
... 'link':{'text':{'id':'5423093'}},
... 'guid':{'attrib':{'id':'GUID'}, 'text':'http://www.example.org/rss/5423093'},
... 'description':{'text':'Example of assigning text to a field.'},
... 'ipubdate':{'text':{'month':'June', 'day':'6', 'year':'2006'}}}}
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">
June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">
June 06, 2006</lastBuildDate>
<item class="item">
<title id="title">
Example Title: First Example</title>
<link id="link">
http://www.example.org/rss/5423093</link>
<guid id=
"GUID" isPermaLink="true">http://www.example.org/rss/5423093</guid>
<description id="description">
Example of assigning text to a field.</description>
<pubDate id="ipubdate">
June 06, 2006</pubDate>
</item>
</channel>
</rss>
STATE
Each root, field, or group has a current and a default property. The current property returns the object's current state:
>>> example.current
<Template "root" at dcd290>
>>> print example.current
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">June 06, 2006</lastBuildDate>
<item class="item">
<title id="title">Example Title: First Example</title>
<link id="link">http://www.example.org/rss/5423093</link>
<guid id="GUID" isPermaLink="true">http://www.example.org/rss/5423093</guid>
<description id="description">Example of assigning text to a field.</description>
<pubDate id="ipubdate">June 6, 2006</pubDate>
</item>
</channel>
</rss>
The default property returns the object's default state:
>>> example.default
<Template "root" at f62d10>
>>> print example.default
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">$month $day, $year</pubDate>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
</channel>
</rss>
CONCATENATION
Roots, fields, and groups can be concatenated together using the addition operator.

Roots:
>>> example.reset()
>>> print example + example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">$month $day, $year</pubDate>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
</channel>
<rss version="2.0"> <channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">$month $day, $year</pubDate>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
</channel> </rss>
</rss>
Groups:
>>> print example.item + example.item
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
Fields:
>>> print example.item.title + example.item.title
<title id="title" />
<title id="title" />
Using the addition operator (+) without the assignment operator (=) results in a new object. Using the addition and assignment operators together (+=) modifies the left-hand object:
>>> example.item += example.item
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">$month $day, $year</pubDate>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>

</channel>
</rss>
REPETITION
A root, group, or field can be repeated once by calling its repeat method:
>>> example.reset()
>>> example.item.repeat()
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">$month $day, $year</pubDate>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>

</channel>

</rss>
A root, group, or field can be repeated more than once by using the multiplication operator, either by itself (*), which returns a new object, or along with the assignment operator (*=), which modifies the left-hand object:
>>> example.reset()
>>> example.item *= 2
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">$month $day, $year</pubDate>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>

</channel>
</rss>
A root, field, or group can be repeated and have text substituted into it by passing a string, tuple, or dictionary to its repeat method:
>>> example.reset()
>>> example.item %= ( ... 'Example Title: First Example', ... 'http://www.example.org/rss/5423092', ... 'http://www.example.org/rss/5423092', ... 'Example of assigning text to a field.', ... 'June 06, 2006')
>>> example.item.repeat(( ... 'Example Title: Second Example', ... 'http://www.example.org/rss/5423093', ... 'http://www.example.org/rss/5423093', ... 'Example of group repetition.', ... 'June 06, 2006'))
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">$month $day, $year</pubDate>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title">
Example Title: First Example</title>
<link id="link">
http://www.example.org/rss/5423092</link>
<guid id="guid" isPermaLink="true">
http://www.example.org/rss/5423092</guid>
<description id="description">
Example of assigning text to a field.</description>
<pubDate id="ipubdate">
June 06, 2006</pubDate>
</item>
<item class="item">
<title id="title">Example Title: Second Example</title>
<link id="link">http://www.example.org/rss/5423093</link>
<guid id="guid" isPermaLink="true">http://www.example.org/rss/5423093</guid>
<description id="description">Example of group repetition.</description>
<pubDate id="ipubdate">June 06, 2006</pubDate>
</item>

</channel>
</rss>
A root, field, or group can be expanded to fit a sequence of substitutions by using the power operator (**) either alone, which returns a new object, or joined with the assignment operator (**=), which modifies the left-hand object:
>>> example.reset()
>>> example.item **= (( ... 'Example Title: First Example', ... 'http://www.example.org/rss/5423092', ... 'http://www.example.org/rss/5423092', ... 'Example of assigning text to a field.', ... 'June 06, 2006'), ( ... 'Example Title: Second Example', ... 'http://www.example.org/rss/5423093', ... 'http://www.example.org/rss/5423093', ... 'Example of group repetition.', ... 'June 06, 2006'))
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">$month $day, $year</pubDate>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title">
Example Title: First Example</title>
<link id="link">
http://www.example.org/rss/5423092</link>
<guid id="guid" isPermaLink="true">
http://www.example.org/rss/5423092</guid>
<description id="description">
Example of assigning text to a field.</description>
<pubDate id="ipubdate">
June 06, 2006</pubDate>
</item>
<item class="item">
<title id="title">Example Title: Second Example</title>
<link id="link">http://www.example.org/rss/5423093</link>
<guid id="guid" isPermaLink="true">http://www.example.org/rss/5423093</guid>
<description id="description">Example of group repetition.</description>
<pubDate id="ipubdate">June 06, 2006</pubDate>
</item>

</channel>
</rss>
Expansion can be combined with template assignment into a single batch substitution using the modulo operator:
>>> example.reset()
>>> example.item %= { ... 'templates':{ ... 'title':{'text':'Example Title: $content'}, ... 'ipubdate':{'text':'$month $day, $year'}, ... 'link':{'text':'http://www.example.org/rss/$id'}},
... 'subs':( ... ({'text':{'content':'First Example'}}, ... {'text':{'id':'5423092'}}, ... 'http://www.example.org/rss/5423092',
... 'Example of assigning text to a field.', ... {'text':{'year':'June', 'day':'06', 'year':'2006'}}),
... ({'text':{'content':'Second Example'}}, ... {'text':{'id':'5423093'}}, ... 'http://www.example.org/rss/5423093',
... 'Example of group repetition.', ... {'text':{'month':'June', 'day':'06', 'year':'2006'}}))}
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">$month $day, $year</pubDate>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title">
Example Title: First Example</title>
<link id="link">
http://www.example.org/rss/5423092</link>
<guid id="guid" isPermaLink="true">
http://www.example.org/rss/5423092</guid>
<description id="description">
Example of assigning text to a field.</description>
<pubDate id="ipubdate">
June 06, 2006</pubDate>
</item>
<item class="item">
<title id="title">Example Title: Second Example</title>
<link id="link">http://www.example.org/rss/5423093</link>
<guid id="guid" isPermaLink="true">http://www.example.org/rss/5423093</guid>
<description id="description">Example of group repetition.</description>
<pubDate id="ipubdate">June 06, 2006</pubDate>
</item>

</channel>
</rss>
The number of items in each tuple of substitutions must be equal to the number of fields in the root or group to which it is passed. These tuples are grouped together in another tuple and stored in the dictionary under the keyword 'subs'.

The maximum number of repetitions that can be performed on a root, field, or group is controlled by the max property. Assigning a new maximum number of repetitions to the max property assigns the same number to a root or group's child fields or groups. The default value of the max property is 25. Exceeding the maximum repetition value assigned to the max property triggers an exception:
>>> example.reset()
>>> example.max = 1
>>> example.item %= { ... 'templates':{ ... 'title':{'text':'Example Title: $content'}, ... 'ipubdate':{'text':'$month $day, $year'}, ... 'link':{'text':'http://www.example.org/rss/$id'}},
... 'subs':( ... ({'text':{'content':'First Example'}}, ... {'text':{'id':'5423092'}}, ... 'http://www.example.org/rss/5423092',
... 'Example of assigning text to a field.', ... {'text':{'year':'June', 'day':'06', 'year':'2006'}}),
... ({'text':{'content':'Second Example'}}, ... {'text':{'id':'5423093'}}, ... 'http://www.example.org/rss/5423093',
... 'Example of group repetition.', ... {'text':{'month':'June', 'day':'06', 'year':'2006'}}))}
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
File "webstring.py", line 641, in __imod__
self.__ipow__(data.pop('subs'))
File "webstring.py", line 276, in __ipow__
raise TypeError(_exceptions[0])
TypeError: maximum allowed repetitions exceeded
Setting the max property back to a number greater that 1 allows the operation to be completed successfully:
>>> example.reset()
>>> example.max = 1
>>> example.item %= { ... 'templates':{ ... 'title':{'text':'Example Title: $content'}, ... 'ipubdate':{'text':'$month $day, $year'}, ... 'link':{'text':'http://www.example.org/rss/$id'}},
... 'subs':( ... ({'text':{'content':'First Example'}}, ... {'text':{'id':'5423092'}}, ... 'http://www.example.org/rss/5423092',
... 'Example of assigning text to a field.', ... {'text':{'year':'June', 'day':'06', 'year':'2006'}}),
... ({'text':{'content':'Second Example'}}, ... {'text':{'id':'5423093'}}, ... 'http://www.example.org/rss/5423093',
... 'Example of group repetition.', ... {'text':{'month':'June', 'day':'06', 'year':'2006'}}))}
>>>
APPENDING
Other Template objects can be appended to a root, field, or group using its append method:
>>> example.reset()
>>> example.cpubdate %= {'text':{'month':'June', 'day':'06', 'year':'2006'}}
>>> example.lastbuilddate %= {'text':{'month':'June', 'day':'06', 'year':'2006'}}
>>> example.item %= { ... 'templates':{ ... 'title':{'text':'Example Title: $content'}, ... 'ipubdate':{'text':'$month $day, $year'}, ... 'link':{'text':'http://www.example.org/rss/$id'}},
... 'subs':( ... ({'text':{'content':'First Example'}}, ... {'text':{'id':'5423092'}}, ... 'http://www.example.org/rss/5423092',
... 'Example of assigning text to a field.', ... {'text':{'year':'June', 'day':'06', 'year':'2006'}}),
... ({'text':{'content':'Second Example'}}, ... {'text':{'id':'5423093'}}, ... 'http://www.example.org/rss/5423093',
... 'Example of group repetition.', ... {'text':{'month':'June', 'day':'06', 'year':'2006'}}))}
>>> example.item.description.append(Template( ... '<html><head><title>Example</title></head><body><p>Paragraph</p></body></html>'))
>>> del example.item.description.text
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">June 06, 2006</pubDate>
<lastBuildDate id="lastbuilddate">June 06, 2006</lastBuildDate>
<item class="item">
<title id="title">Example Title: First Example</title>
<link id="link">http://www.example.org/rss/5423092</link>
<guid id="guid" isPermaLink="true">http://www.example.org/rss/5423092</guid>
<description id="description">
<html><head><title>Example</title></head><body><p>Paragraph</p></body></html></description>
<pubDate id="ipubdate">June 06, 2006</pubDate>
</item>
<item class="item">
<title id="title">Example Title: Second Example</title>
<link id="link">http://www.example.org/rss/5423093</link>
<guid id="guid" isPermaLink="true">http://www.example.org/rss/5423093</guid>
<description id="description">Example of group repetition.</description>
<pubDate id="ipubdate">June 06, 2006</pubDate>
</item>
</channel>
</rss>
ITERATION
Performing a loop operation on a root or group iterates over its fields or groups in sequence:
>>> for field in example: field.__repr__()
...
'<Template "cpubdate" at f62f50>'
'<Template "lastbuilddate" at e7a350>'
'<Template "item" at f627f0>'
Performing a loop operation on a field iterates over its attributes.
>>> for attr in example.item.guid: print attr.__repr__()
...
'isPermaLink'
'id'
OUTPUT
Identifier attributes for fields can be removed by deleting a root, field, or group's mark property. This operation also deletes field identifier attributes from any child fields or groups:
>>> del example.mark
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate>June 06, 2006</pubDate>
<lastBuildDate>June 06, 2006</lastBuildDate>
<item class="item">
<title>Example Title: First Example</title>
<link>http://www.example.org/rss/5423092</link>
<guid isPermaLink="true">http://www.example.org/rss/5423092</guid>
<description><html><head><title>Example</title></head><body><p>Paragraph</p></body></html></description>
<pubDate>June 06, 2006</pubDate>
</item>
<item class="item">
<title>Example Title: Second Example</title>
<link>http://www.example.org/rss/5423093</link>
<guid isPermaLink="true">http://www.example.org/rss/5423093</guid>
<description>Example of group repetition.</description>
<pubDate>June 06, 2006</pubDate>
</item>
</channel>
</rss>
Deleting the groupmark property deletes all group identifier attributes:
>>> del example.groupmark
>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate>June 06, 2006</pubDate>
<lastBuildDate>June 06, 2006</lastBuildDate>
<item>
<title>Example Title: First Example</title>
<link>http://www.example.org/rss/5423092</link>
<guid isPermaLink="true">http://www.example.org/rss/5423092</guid>
<description><html><head><title>Example</title></head><body><p>Paragraph</p></body></html></description>
<pubDate>June 06, 2006</pubDate>
</item>
<item>
<title>Example Title: Second Example</title>
<link>http://www.example.org/rss/5423093</link>
<guid isPermaLink="true">http://www.example.org/rss/5423093</guid>
<description>Example of group repetition.</description>
<pubDate>June 06, 2006</pubDate>
</item>
</channel>
</rss>
The render method is called to output an XML document as a string:
>>> print example.render()
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate>June 06, 2006</pubDate>
<lastBuildDate>June 06, 2006</lastBuildDate>
<item>
<title>Example Title: First Example</title>
<link>http://www.example.org/rss/5423092</link>
<guid isPermaLink="true">http://www.example.org/rss/5423092</guid>
<description><html><head><title>Example</title></head><body><p>Paragraph</p></body></html></description>
<pubDate>June 06, 2006</pubDate>
</item>
<item>
<title>Example Title: Second Example</title>
<link>http://www.example.org/rss/5423093</link>
<guid isPermaLink="true">http://www.example.org/rss/5423093</guid>
<description>Example of group repetition.</description>
<pubDate>June 06, 2006</pubDate>
</item>
</channel>
</rss>
The write method is called to write an XML document to a file:
>>> example.write('finalexample.rss')
The pipe method outputs an XML document as a string and resets it back to its default state:
>>> print example.pipe()
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate>June 06, 2006</pubDate>
<lastBuildDate>June 06, 2006</lastBuildDate>
<item>
<title>Example Title: First Example</title>
<link>http://www.example.org/rss/5423092</link>
<guid isPermaLink="true">http://www.example.org/rss/5423092</guid>
<description><html><head><title>Example</title></head><body><p>Paragraph</p></body></html></description>
<pubDate>June 06, 2006</pubDate>
</item>
<item>
<title>Example Title: Second Example</title>
<link>http://www.example.org/rss/5423093</link>
<guid isPermaLink="true">http://www.example.org/rss/5423093</guid>
<description>Example of group repetition.</description>
<pubDate>June 06, 2006</pubDate>
</item>
</channel>
</rss>

>>> print example
<rss version="2.0">
<channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate id="cpubdate">$month $day, $year</pubDate>
<lastBuildDate id="lastbuilddate">%(month)s %(day)s, %(year)s</lastBuildDate>
<item class="item">
<title id="title" />
<link id="link" />
<guid id="guid" isPermaLink="true" />
<description id="description" />
<pubDate id="ipubdate" />
</item>
</channel>
</rss>
DEVELOPMENT
Send webstring feature requests, patches, and bug reports to (email address imaged and scrambled for spam-protection):
Contact

Valid XHTML 1.1