Class
Initialization
Objects
Access
Substitution
Batch Substitution
State
Concatenation
Repetition
Iteration
Output
webstring
Introduction to TextTemplate
CLASS
While webstring's other specialized classes only handle XML and HTML templating, TextTemplate can handle templating for any text format, including XML and HTML.

TextTemplate can be used as a standalone import:
>>> from webstring import TextTemplate
It can also be used through webstring's Template class, a general frontend to all of webstring's specialized classes.
INITIALIZATION
A TextTemplate object can be initialized empty:
>>> exampleA = TextTemplate()
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 = TextTemplate('example.rss')
From a string with the fromstring method:
>>> exampleD = TextTemplate.fromstring("""<rss version="2.0">
... <channel>
... <title>Example</title>
... <link>http://www.example.org/</link>
... <description>RSS Example</description>
... <language>en-us</language>
... $$cpubdate<pubDate>$month$ $day$, $year$</pubDate>$$
... $$lastbuilddate<lastBuildDate>$month$ $day$, $year$</lastBuildDate>$$ ... $$item<item>
... <title>$title$</title>
... <link>$link$</link>
... <guid isPermaLink="true">$guid$</guid>
... <description>$description$</description>
... <pubDate>$ipubdate$</pubDate>
... </item>
... $$</channel>
... </rss>""")
By passing a string as the first argument to the class constructor:
>>> example = TextTemplate("""<rss version="2.0">
... <channel>
... <title>Example</title>
... <link>http://www.example.org/</link>
... <description>RSS Example</description>
... <language>en-us</language>
... $$cpubdate<pubDate>$month$ $day$, $year$</pubDate>$$
... $$lastbuilddate<lastBuildDate>$month$ $day$, $year$</lastBuildDate>$$ ... $$item<item>
... <title>$title$</title>
... <link>$link$</link>
... <guid isPermaLink="true">$guid$</guid>
... <description>$description$</description>
... <pubDate>$ipubdate$</pubDate>
... </item>
... $$</channel>
... </rss>""")
To use TextTemplate through the Template class, you pass the value text with the format keyword to the Template class's constructor:
>>> example = Template(format="text")
OBJECTS
webstring automatically maps a template to a root object. Field placeholders within the template are an alphanumeric value that uniquely identifies the field placeholder within the template preceded and terminated by a placeholder marker (by default, $). Field placeholders are automatically mapped to field objects with the same name as the field placeholder and attached to the parent template's root object.
$$cpubdate<pubDate>$month$ $day$, $year$</pubDate>$$
Group placeholders within the template are blocks of text containing field placeholders preceded and terminated by a group placeholder marker (by default, $$). The alphanumeric value immediately following the opening group placeholder marker uniquely identifies the group within the template. webstring automatically maps the group placeholder to a group object with the same name as the group placeholder and attaches it to the parent template's root object. Field placeholders within group are mapped to field objects and attached to the group object.
$$cpubdate<pubDate>$month$ $day$, $year$</pubDate>$$
Group objects cannot contain other group objects. At maximum, a root's object hierarchy will never be more than three 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>
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 field or group placeholders become part of a root's object hierarchy except for groups that have no field placeholders within them. However, existing fields or groups within an template can be excluded or included before or after a root object is initialized by using its exclude or include methods.

Exclusion with the exclude method:
>>> example.exclude('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> , </lastBuildDate>
<item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</item>
</channel>
</rss>
Inclusion with the include method:
>>> example.include('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>
<pubDate> , </pubDate>
<lastBuildDate> , </lastBuildDate> <item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</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> , </lastBuildDate>
<item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</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> , </pubDate>
<lastBuildDate> , </lastBuildDate> <item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</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>
By default, webstring automatically maps fields, groups, and attributes to object attributes with the same name as the field or group placeholder'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 TextTemplate object is initialized:
>>> exampleZ = TextTemplate('example.rss', False)
Fields and groups 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 = '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> , </pubDate>
<lastBuildDate> , </lastBuildDate> <item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description>
Assigning text to a field.</description>
<pubDate></pubDate>
</item>
</channel>
</rss>
Alternatively, text can be substituted into a field using the modulo assignment operator (%=). 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.
>>> example.item.description %= '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> , </pubDate>
<lastBuildDate> , </lastBuildDate> <item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description>
Example of assigning text to a field.</description>
<pubDate></pubDate>
</item>
</channel>
</rss>
The %= operator can also be used to substitute text into a group using a dictionary containing key/value pairs where the key is the name of the field inside the group and the value is the text that will be assigned to the field:
>>> example.cpubdate %= {'month':'June', 'day':'06', 'year':'2006'}
>>> example.lastbuilddate %= {'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>
June 06, 2006</pubDate>
<lastBuildDate>
June 06, 2006</lastBuildDate> <item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description>Example of assigning text to a field.</description>
<pubDate></pubDate>

</item>
</channel>
</rss>
BATCH SUBSTITUTION
The modulo operator can also be used to substitute text into a template in one batch substitution. Text values for fields and groups within a template are passed in a dictionary containing key/value pairs where the key is the field or group identifier and the value is the text to be substituted. Fields within a group are passed in a dictionary that is stored under the keyword identifying the group:
>>> example %= {
... 'cpubdate':{'month':'June', 'day':'06', 'year':'2006'},
... 'lastbuilddate':{'month':'June', 'day':'06', 'year':'2006'},
... 'item':{'title':Example Title: First Example',
... 'link':'http://www.example.org/rss/5423093',
... 'guid':'http://www.example.org/rss/5423093',
... 'description':'Example of assigning text to a field.',
... 'ipubdate':'June 6, 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>
June 06, 2006</pubDate>
<lastBuildDate>
June 06, 2006</lastBuildDate>
<item>
<title>
Example Title: First Example</title>
<link>
http://www.example.org/rss/5423093</link>
<guid
isPermaLink="true">http://www.example.org/rss/5423093</guid>
<description>
Example of assigning text to a field.</description>
<pubDate>
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>June 06, 2006</pubDate>
<lastBuildDate>June 06, 2006</lastBuildDate>
<item>
<title>Example Title: First Example</title>
<link>http://www.example.org/rss/5423093</link>
<guid isPermaLink="true">http://www.example.org/rss/5423093</guid>
<description>Example of assigning text to a field.</description>
<pubDate>June 06, 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> , </pubDate>
<lastBuildDate> , </lastBuildDate> <item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</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> , </pubDate>
<lastBuildDate> , </lastBuildDate> <item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</item>
</channel>
</rss>
<rss version="2.0"> <channel>
<title>Example</title>
<link>http://www.example.org/</link>
<description>RSS Example</description>
<language>en-us</language>
<pubDate> , </pubDate>
<lastBuildDate> , </lastBuildDate> <item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</item>
</channel> </rss>
Groups:
>>> print example.item + example.item
<item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</item>
<item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</item>
Concatenating empty fields produces no output:
>>> print example.item.title + example.item.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> , </pubDate>
<lastBuildDate> , </lastBuildDate> <item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</item>
<item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</item>

</channel>
</rss>
Other Template objects or strings can be appended to a root, field, or group using their append method.
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> , </pubDate>
<lastBuildDate> , </lastBuildDate> <item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</item>
<item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</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> , </pubDate>
<lastBuildDate> , </lastBuildDate> <item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</item>
<item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</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> , </pubDate>
<lastBuildDate> , </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>
Example of assigning text to a field.</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>
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> , </pubDate>
<lastBuildDate> , </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>
Example of assigning text to a field.</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 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.

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 **= (( ... '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'))
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
File "base.py", line 158, in __ipow__
raise TypeError(_exceptions[0])
TypeError: maximum allowed repetitions exceeded
Setting the max property to a number greater than 1 allows the operation to be completed successfully.
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>'
OUTPUT
The render method is called to output an template 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> , </pubDate>
<lastBuildDate> , </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>Example of assigning text to a field.</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 a template's string output to a file:
>>> example.write('finalexample.rss')
The pipe method outputs a string and resets the template 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> , </pubDate>
<lastBuildDate> , </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>Example of assigning text to a field.</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> , </pubDate>
<lastBuildDate> , </lastBuildDate> <item>
<title></title>
<link></link>
<guid isPermaLink="true"></guid>
<description></description>
<pubDate></pubDate>
</item>
</channel>
</rss>

Valid XHTML 1.1