def select_pattern(node, pattern, state=None):
if state is None:<EOL><INDENT>state = _prep_pattern(pattern)<EOL><DEDENT>if isinstance(node, element):<EOL><INDENT>for child in node.xml_children:<EOL><INDENT>new_state = state(child)<EOL>if new_state == MATCHED_STATE:<EOL><INDENT>yield child<EOL><DEDENT>elif new_state is not None:<EOL><INDENT>yield from select_pattern(child, None, state=new_state)<EOL><DEDENT><DEDENT><DEDENT>return<EOL>
Yield descendant nodes matching the given pattern specification
pattern - tuple of steps, each of which matches an element by name, with "*" acting like a wildcard, descending the tree in tuple order
            sort of like a subset of XPath in Python tuple form
state - for internal use only

pattern examples:

("a", "b", "c") - all c elements whose parent is a b element whose parent is an a element whose parent is node
("*", "*") - any "grandchild" of node
("*", "*", "*") - any "great grandchild" of node
("**", "a") - any a descendant of node

>>> from amara3.uxml import tree
>>> from amara3.uxml.treeutil import *
>>>
>>> tb = tree.treebuilder()
>>> DOC = '<a xmlns="urn:namespaces:suck"><b><x>1</x></b><c><x>2</x><d><x>3</x></d></c><x>4</x><y>5</y></a>'
>>> root = tb.parse(DOC)
>>> results = [ e.xml_value for e in select_pattern(root, ('**', 'x')) ]
>>> results
['1', '2', '3', '4']