27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
# File 'lib/common/http/fix_hpricot.rb', line 27
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
|