Evaluate XPath predicates for every context node.
Instead of evaluating a predicate once for all context nodes, they should instead be evaluated separately per context node.
This commit is contained in:
parent
6daa3e7a00
commit
f1d574f342
|
@ -188,30 +188,32 @@ module Oga
|
||||||
#
|
#
|
||||||
def on_predicate(ast_node, context)
|
def on_predicate(ast_node, context)
|
||||||
test, predicate = *ast_node
|
test, predicate = *ast_node
|
||||||
|
final_nodes = XML::NodeSet.new
|
||||||
|
|
||||||
initial_nodes = process(test, context)
|
context.each do |context_node|
|
||||||
final_nodes = XML::NodeSet.new
|
initial_nodes = process(test, XML::NodeSet.new([context_node]))
|
||||||
xpath_index = 1
|
xpath_index = 1
|
||||||
|
|
||||||
initial_nodes.each do |xml_node|
|
initial_nodes.each do |xml_node|
|
||||||
retval = with_node_set(initial_nodes) do
|
retval = with_node_set(initial_nodes) do
|
||||||
process(predicate, XML::NodeSet.new([xml_node]))
|
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
final_nodes << xml_node
|
# Numeric values are used as node set indexes.
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
return final_nodes
|
return final_nodes
|
||||||
|
|
|
@ -3,18 +3,23 @@ require 'spec_helper'
|
||||||
describe Oga::XPath::Evaluator do
|
describe Oga::XPath::Evaluator do
|
||||||
context 'predicates' do
|
context 'predicates' do
|
||||||
before do
|
before do
|
||||||
@document = parse('<root><b>10</b><b>20</b></root>')
|
@document = parse(<<-EOF)
|
||||||
|
<root>
|
||||||
|
<a>10</a>
|
||||||
|
<b>
|
||||||
|
<a>20</a>
|
||||||
|
<a>30</3>
|
||||||
|
</b>
|
||||||
|
</root>
|
||||||
|
EOF
|
||||||
|
|
||||||
@b1 = @document.children[0].children[0]
|
@a1 = @document.at_xpath('root/a[1]')
|
||||||
@b2 = @document.children[0].children[1]
|
@a2 = @document.at_xpath('root/b/a[1]')
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'evaluate a predicate that returns the first <b> node' do
|
example 'return a node set containing all first <a> nodes' do
|
||||||
evaluate_xpath(@document, 'root/b[1]').should == node_set(@b1)
|
evaluate_xpath(@document, 'descendant-or-self::node()/a[1]')
|
||||||
end
|
.should == node_set(@a1, @a2)
|
||||||
|
|
||||||
example 'evaluate a predicate that returns the second <b> node' do
|
|
||||||
evaluate_xpath(@document, 'root/b[2]').should == node_set(@b2)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue