Previously, you could use the .elements() method to find matching elements
nested within an HTML helper object (such as a form), and you could mutuate
the matched elements (e.g., add attributes and insert components), but you
could not completely replace or remove the matched elements. The only way
to replace or remove elements was to use list indexing (e.g.,
form[0][0][1], etc.), but that requires you to know the exact index values
ahead of time. Now (in trunk) you can use the .elements() method to replace
or remove nested elements or text using the new "replace" and "find_text"
arguments. Below is the updated docstring, including some examples (will be
added to the book as well). Please test and report any problems
(particularly if any of the old .elements() functionality has broken).
Anthony
Docstring:
Elements that are matched can also be replaced or removed by
specifying
a "replace" argument (note, a list of the original matching elements
is still returned as usual).
>>> a = DIV(DIV(SPAN('x', _class='abc'), DIV(SPAN('y',
_class='abc'), SPAN('z', _class='abc'))))
>>> b = a.elements('span.abc', replace=P('x', _class='xyz'))
>>> print a
<div><div><p class="xyz">x</p><div><p class="xyz">x</p><p
class="xyz">x</p></div></div></div>
"replace" can be a callable, which will be passed the original
element and
should return a new element to replace it.
>>> a = DIV(DIV(SPAN('x', _class='abc'), DIV(SPAN('y',
_class='abc'), SPAN('z', _class='abc'))))
>>> b = a.elements('span.abc', replace=lambda el: P(el[0],
_class='xyz'))
>>> print a
<div><div><p class="xyz">x</p><div><p class="xyz">y</p><p
class="xyz">z</p></div></div></div>
If replace=None, matching elements will be removed completely.
>>> a = DIV(DIV(SPAN('x', _class='abc'), DIV(SPAN('y',
_class='abc'), SPAN('z', _class='abc'))))
>>> b = a.elements('span', find='y', replace=None)
>>> print a
<div><div><span class="abc">x</span><div><span
class="abc">z</span></div></div></div>
If a "find_text" argument is specified, elements will be searched
for text
components that match find_text, and any matching text components
will be
replaced (find_text is ignored if "replace" is not also specified).
Like the "find" argument, "find_text" can be a string or a compiled
regex.
>>> a = DIV(DIV(SPAN('x', _class='abc'), DIV(SPAN('y',
_class='abc'), SPAN('z', _class='abc'))))
>>> b = a.elements(find_text=re.compile('x|y|z'), replace='hello')
>>> print a
<div><div><span class="abc">hello</span><div><span
class="abc">hello</span><span class="abc">hello</span></div></div></div>
If other attributes are specified along with find_text, then only
components
that match the specified attributes will be searched for find_text.
>>> a = DIV(DIV(SPAN('x', _class='abc'), DIV(SPAN('y',
_class='efg'), SPAN('z', _class='abc'))))
>>> b = a.elements('span.efg', find_text=re.compile('x|y|z'),
replace='hello')
>>> print a
<div><div><span class="abc">x</span><div><span
class="efg">hello</span><span class="abc">z</span></div></div></div>
--