Search Reference

    This narrative covers all the possible ways to search for elements
    when using Twiddler.

    We'll demonstrate this using the following example:
 
    >>> from twiddler import Twiddler
    >>> t = Twiddler('''<html>
    ...   <body>
    ...   <div id="one" name="aname">
    ...     <div id="subone" name="subone"/>
    ...     <div id="subtwo" name="subtwo"/>
    ...   </div>
    ...   <div id="two" name="aname">
    ...     <div id="subone" name="subone"/>
    ...     <div id="subtwo" name="subtwo"/>
    ...   </div>
    ...   </body>
    ... </html>''')

    As we've already seen, Twiddlers allow elements to be looked up
    using python's item access syntax:

    >>> t['aname'].replace(name='name2')

    By default, elements can be looked up by either their 'name' or
    their 'id' attributes:

    >>> t['one'].replace(name='name1')
    
    TwiddlerElements can also be searched in the same way, but the
    search will be limited to the contents of the TwiddlerElement:

    >>> t['one']['subone'].replace('one')
    >>> t['one']['subtwo'].replace('two')
    >>> t['two']['subone'].replace('three')
    >>> t['two']['subtwo'].replace('four')
    
    We can see the results of all this by rendering the Twiddler:

    >>> print t.render()
    <html>
      <body>
      <div id="one" name="name1">
        <div id="subone" name="subone">one</div>
        <div id="subtwo" name="subtwo">two</div>
      </div>
      <div id="two" name="name2">
        <div id="subone" name="subone">three</div>
        <div id="subtwo" name="subtwo">four</div>
      </div>
      </body>
    </html>

    Beware, however, that when you change a Twiddler, the promise that
    the "last" element will always be returned will probably not be
    met in the way you expect:

    >>> t['one'].replace(name='name2')
    >>> t['name2'].replace('Oops!')
    >>> print t.render()
    <html>
      <body>
      <div id="one" name="name2">Oops!</div>
      <div id="two" name="name2">
        <div id="subone" name="subone">three</div>
        <div id="subtwo" name="subtwo">four</div>
      </div>
      </body>
    </html>

    This is an artifact of trying to keep Twiddlers as quick as
    possible. You can avoid this by using more unique identifiers.

    You may be wondering what happens if two different nodes share an
    id and a name:

    >>> t = Twiddler('''<tag>
    ...   <taga name="something"/>
    ...   <tagb id="something"/>
    ... </tag>''')
    
    The answer, for the default setup of a Twiddler, is that the
    element with a matching id will be found instead of the element
    with a matching name:

    >>> t['something'].replace('found!')
    >>> print t.render()
    <tag>
      <taga name="something" />
      <tagb id="something">found!</tagb>
    </tag>

    If you need to be specific about which attribute you'd like to
    match, both Twiddler and TwiddlerElement instances have a 'getBy'
    method that will let you search more specifically:

    >>> t.getBy(name='something').replace('found by name')
    >>> t.getBy(id='something').replace('found by id')
    >>> print t.render()
    <tag>
      <taga name="something">found by name</taga>
      <tagb id="something">found by id</tagb>
    </tag>

    Now, you may be generating XML or some other flavour of tagged
    language where you want to search by something other than the 'id'
    or 'name' attributes. In this case, you can tell the Twiddler what
    attributes to index when you construct it:

    >>> t = Twiddler('''<tag>
    ...   <taga x="something"/>
    ...   <tagb y="something"/>
    ... </tag>''',
    ...              indexes=('x','y'))

    The order in which the indexes are specified is the order in which
    they will be searched:

    >>> t['something'].replace('found!')
    >>> print t.render()
    <tag>
      <taga x="something">found!</taga>
      <tagb y="something" />
    </tag>

    But, as you'd expect, you can use the 'getBy' method to search
    more specifically:

    >>> t.getBy(x='something').replace('found by x')
    >>> t.getBy(y='something').replace('found by y')
    >>> print t.render()
    <tag>
      <taga x="something">found by x</taga>
      <tagb y="something">found by y</tagb>
    </tag>
