diff --git a/lib/oga/xpath/evaluator.rb b/lib/oga/xpath/evaluator.rb
index d503351..47c9644 100644
--- a/lib/oga/xpath/evaluator.rb
+++ b/lib/oga/xpath/evaluator.rb
@@ -188,30 +188,32 @@ module Oga
#
def on_predicate(ast_node, context)
test, predicate = *ast_node
+ final_nodes = XML::NodeSet.new
- initial_nodes = process(test, context)
- final_nodes = XML::NodeSet.new
- xpath_index = 1
+ context.each do |context_node|
+ initial_nodes = process(test, XML::NodeSet.new([context_node]))
+ xpath_index = 1
- initial_nodes.each do |xml_node|
- retval = with_node_set(initial_nodes) do
- process(predicate, XML::NodeSet.new([xml_node]))
- end
-
- # Numeric values are used as node set indexes.
- if retval.is_a?(Numeric)
- final_nodes << xml_node if retval.to_i == xpath_index
-
- # Node sets, strings, booleans, etc
- elsif retval
- if retval.respond_to?(:empty?) and retval.empty?
- next
+ initial_nodes.each do |xml_node|
+ retval = with_node_set(initial_nodes) do
+ process(predicate, XML::NodeSet.new([xml_node]))
end
- final_nodes << xml_node
- end
+ # Numeric values are used as node set indexes.
+ if retval.is_a?(Numeric)
+ final_nodes << xml_node if retval.to_i == xpath_index
- xpath_index += 1
+ # Node sets, strings, booleans, etc
+ elsif retval
+ if retval.respond_to?(:empty?) and retval.empty?
+ next
+ end
+
+ final_nodes << xml_node
+ end
+
+ xpath_index += 1
+ end
end
return final_nodes
diff --git a/spec/oga/xpath/evaluator/predicates_spec.rb b/spec/oga/xpath/evaluator/predicates_spec.rb
index 1e1d10d..1643735 100644
--- a/spec/oga/xpath/evaluator/predicates_spec.rb
+++ b/spec/oga/xpath/evaluator/predicates_spec.rb
@@ -3,18 +3,23 @@ require 'spec_helper'
describe Oga::XPath::Evaluator do
context 'predicates' do
before do
- @document = parse('1020')
+ @document = parse(<<-EOF)
+
+ 10
+
+ 20
+ 303>
+
+
+ EOF
- @b1 = @document.children[0].children[0]
- @b2 = @document.children[0].children[1]
+ @a1 = @document.at_xpath('root/a[1]')
+ @a2 = @document.at_xpath('root/b/a[1]')
end
- example 'evaluate a predicate that returns the first node' do
- evaluate_xpath(@document, 'root/b[1]').should == node_set(@b1)
- end
-
- example 'evaluate a predicate that returns the second node' do
- evaluate_xpath(@document, 'root/b[2]').should == node_set(@b2)
+ example 'return a node set containing all first nodes' do
+ evaluate_xpath(@document, 'descendant-or-self::node()/a[1]')
+ .should == node_set(@a1, @a2)
end
end
end