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.
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")
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>
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.
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>
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>
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>
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.
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.
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>'
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>