Class: Leptris::XML::NodeSet
- Inherits:
-
Object
- Object
- Leptris::XML::NodeSet
show all
- Includes:
- Enumerable, Searchable
- Defined in:
- lib/leptris/xml/node_set.rb
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Methods included from Searchable
#at, #at_css, #at_xpath, #css, #search, wrap_xpath_result
Constructor Details
#initialize(document, source = nil) ⇒ NodeSet
Two construction modes:
- eager: pass an Array of Nodes (e.g. Element#children builds one)
- lazy: pass an FFI::Pointer to a LeptrisXPathResult that this NodeSet
will keep alive and free on GC. Each [i] / each call goes
through leptris_xpath_result_get instead of pre-materializing.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
# File 'lib/leptris/xml/node_set.rb', line 16
def initialize(document, source = nil)
@document = document
case source
when ::FFI::Pointer
if source.null?
@result_ptr = nil
@array = []
else
@result_ptr = ::FFI::AutoPointer.new(source, Leptris::XML::FFI.method(:leptris_xpath_result_free))
@array = nil
end
when nil
@result_ptr = nil
@array = []
else
@result_ptr = nil
@array = source.to_a
end
end
|
Instance Attribute Details
#document ⇒ Object
Returns the value of attribute document.
9
10
11
|
# File 'lib/leptris/xml/node_set.rb', line 9
def document
@document
end
|
Class Method Details
.from_result(document, result_ptr) ⇒ Object
39
40
41
|
# File 'lib/leptris/xml/node_set.rb', line 39
def self.from_result(document, result_ptr)
new(document, result_ptr)
end
|
Instance Method Details
#[](idx) ⇒ Object
52
53
54
55
56
57
58
59
60
61
|
# File 'lib/leptris/xml/node_set.rb', line 52
def [](idx)
if @result_ptr
return nil if idx < 0 || idx >= length
ptr = Leptris::XML::FFI.leptris_xpath_result_get_node(@result_ptr, idx)
return nil if ptr.null?
Leptris::XML::Node.wrap(ptr, @document)
else
@array[idx]
end
end
|
#each ⇒ Object
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
|
# File 'lib/leptris/xml/node_set.rb', line 63
def each
return enum_for(:each) unless block_given?
if @result_ptr
n = length
if n > 0
pointers = Leptris::XML::FFI.fetch_result_nodes(@result_ptr, n)
pointers.each do |ptr|
next if ptr.null?
yield Leptris::XML::Node.wrap(ptr, @document)
end
(pointers.length...n).each do |i|
ptr = Leptris::XML::FFI.leptris_xpath_result_get_node(@result_ptr, i)
next if ptr.null?
yield Leptris::XML::Node.wrap(ptr, @document)
end
end
else
@array.each { |n| yield n }
end
self
end
|
#empty? ⇒ Boolean
48
49
50
|
# File 'lib/leptris/xml/node_set.rb', line 48
def empty?
length == 0
end
|
#first(n = nil) ⇒ Object
102
103
104
105
|
# File 'lib/leptris/xml/node_set.rb', line 102
def first(n = nil)
return self[0] if n.nil?
n.times.map { |i| self[i] }.take_while { |x| !x.nil? }
end
|
#inner_text ⇒ Object
Also known as:
text
115
116
117
|
# File 'lib/leptris/xml/node_set.rb', line 115
def inner_text
map(&:content).join
end
|
#inspect ⇒ Object
140
141
142
|
# File 'lib/leptris/xml/node_set.rb', line 140
def inspect
to_a.inspect
end
|
#last ⇒ Object
107
108
109
110
111
112
113
|
# File 'lib/leptris/xml/node_set.rb', line 107
def last
if @result_ptr
self[length - 1]
else
@array.last
end
end
|
#length ⇒ Object
Also known as:
size
43
44
45
|
# File 'lib/leptris/xml/node_set.rb', line 43
def length
@result_ptr ? Leptris::XML::FFI.leptris_xpath_result_count(@result_ptr) : @array.length
end
|
#to_a ⇒ Object
Also known as:
to_ary
92
93
94
95
96
97
98
99
|
# File 'lib/leptris/xml/node_set.rb', line 92
def to_a
return @array if @array
return [] if @result_ptr.nil?
out = []
each { |n| out << n }
@array = out out
end
|
#xpath(*paths) ⇒ Object
Union semantics: evaluate the expression against each element
member (one C eval per member — the engine has no multi-context
eval yet; leptris/leptris ask pending) and accumulate into ONE
NodeSet, instead of merging NodeSets per member.
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
# File 'lib/leptris/xml/node_set.rb', line 124
def xpath(*paths)
handler, _ns, _vars = parse_search_args(paths)
raise ArgumentError, "custom XPath handlers not supported" if handler
expr = paths.join(" | ")
accumulated = []
each do |node|
next unless node.is_a?(Leptris::XML::Element)
result_ptr = Leptris::XML::FFI.leptris_xpath_eval(
@document.c_ptr, node.c_ptr, expr)
next if result_ptr.null?
accumulated.concat(
Leptris::XML::NodeSet.from_result(@document, result_ptr).to_a)
end
Leptris::XML::NodeSet.new(@document, accumulated)
end
|