def search(expr, &blk)
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!^[>/]!
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
if m[1] == '#'
oid = get_element_by_id(m[2])
nodes = oid ? [oid] : []
expr = $'
else
m[2] = "*" if $' =~ /^\(\)/ || 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