module Hpricot::Traverse

def search(expr, &blk)

is used to iterate through the matching set.
containing the matching nodes. If +blk+ is given, it
the CSS or XPath +expr+. Returns an Elements array
Searches this node for all elements matching
def search(expr, &blk)
  if Range === expr
    return Elements.expand(at(expr.begin), at(expr.end), expr.exclude_end?)
  end
  last = nil
  nodes = [self]
  done = []
  expr = expr.to_s
  hist = []
  until expr.empty?
      expr = clean_path(expr)
      expr.gsub!(%r!^//!, '')
      case expr
      when %r!^/?\.\.!
          last = expr = $'
          nodes.map! { |node| node.parent }
      when %r!^[>/]\s*!
          last = expr = $'
          nodes = Elements[*nodes.map { |node| node.children if node.respond_to? :children }.flatten.compact]
      when %r!^\+!
          last = expr = $'
          nodes.map! do |node|
              siblings = node.parent.children
              siblings[siblings.index(node)+1]
          end
          nodes.compact!
      when %r!^~!
          last = expr = $'
          nodes.map! do |node|
              siblings = node.parent.children
              siblings[(siblings.index(node)+1)..-1]
          end
          nodes.flatten!
      when %r!^[|,]!
          last = expr = " #$'"
          nodes.shift if nodes.first == self
          done += nodes
          nodes = [self]
      else
          m = expr.match(%r!^([#.]?)([a-z0-9\\*_-]*)!i).to_a
          after = $'
          mt = after[%r!:[a-z0-9\\*_-]+!i, 0]
          oop = false
          if mt and not (mt == ":not" or Traverse.method_defined? "filter[#{mt}]")
            after = $' 
            m[2] += mt
            expr = after
          end
          if m[1] == '#'
              oid = get_element_by_id(m[2])
              nodes = oid ? [oid] : []
              expr = after
          else
              m[2] = "*" if after =~ /^\(\)/ || m[2] == "" || m[1] == "."
              ret = []
              nodes.each do |node|
                  case m[2]
                  when '*'
                      node.traverse_element { |n| ret << n }
                  else
                      if node.respond_to? :get_elements_by_tag_name
                        ret += [*node.get_elements_by_tag_name(m[2])] - [*(node unless last)]
                      end
                  end
              end
              nodes = ret
          end
          last = nil
      end
      hist << expr
      break if hist[-1] == hist[-2]
      nodes, expr = Elements.filter(nodes, expr)
  end
  nodes = done + nodes.flatten.uniq
  if blk
      nodes.each(&blk)
      self
  else
      Elements[*nodes]
  end
end