'Return an iterable containing
* self (if include_self is true)
* all descendants in tree traversal order (if descend is true)
* all siblings (if siblings is true) and their descendants (if
also descend is true)
* the siblings of the parent (if ascend is true) and their
descendants (if also descend is true), and so on
If `condition` is not None, the iterable contains only nodes
for which ``condition(node)`` is true.  If `condition` is a
node class ``cls``, it is equivalent to a function consisting
of ``return isinstance(node, cls)``.
If ascend is true, assume siblings to be true as well.
For example, given the following tree::
<paragraph>
<emphasis>      <--- emphasis.traverse() and
<strong>    <--- strong.traverse() are called.
Foo
Bar
<reference name="Baz" refid="baz">
Baz
Then list(emphasis.traverse()) equals ::
[<emphasis>, <strong>, <#text: Foo>, <#text: Bar>]
and list(strong.traverse(ascend=1)) equals ::
[<strong>, <#text: Foo>, <#text: Bar>, <reference>, <#text: Baz>]'

def traverse(self, condition=None, include_self=1, descend=1, siblings=0, ascend=0):

    r = []
    if ascend:
        siblings = 1
    if isinstance(condition, (ClassType, TypeType)):
        node_class = condition
        def condition(node, node_class=node_class):
            return isinstance(node, node_class)
    if (include_self and ((condition is None) or condition(self))):
        r.append(self)
    if (descend and len(self.children)):
        for child in self:
            r.extend(child.traverse(include_self=1, descend=1, siblings=0, ascend=0, condition=condition))
    if (siblings or ascend):
        node = self
        while node.parent:
            index = node.parent.index(node)
            for sibling in node.parent[(index + 1):]:
                r.extend(sibling.traverse(include_self=1, descend=descend, siblings=0, ascend=0, condition=condition))
            if (not ascend):
                break
            else:
                node = node.parent
    return r
