XPath compiler support for sum()
This commit is contained in:
parent
e7e5b123cf
commit
106d83e780
|
@ -1103,6 +1103,28 @@ module Oga
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @param [Oga::Ruby::Node] input
|
||||||
|
# @param [AST::Node] arg
|
||||||
|
# @return [Oga::Ruby::Node]
|
||||||
|
def on_call_sum(input, arg)
|
||||||
|
unless return_nodeset?(arg)
|
||||||
|
raise TypeError, 'sum() can only operate on a path, axis or predicate'
|
||||||
|
end
|
||||||
|
|
||||||
|
sum_var = unique_literal(:sum)
|
||||||
|
conversion = literal(Conversion)
|
||||||
|
|
||||||
|
sum_var.assign(literal(0.0))
|
||||||
|
.followed_by do
|
||||||
|
process(arg, input) do |matched_node|
|
||||||
|
sum_var.assign(sum_var + conversion.to_float(matched_node.text))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
.followed_by do
|
||||||
|
block_given? ? sum_var.zero?.not.if_true { yield } : sum_var
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Delegates type tests to specific handlers.
|
# Delegates type tests to specific handlers.
|
||||||
#
|
#
|
||||||
|
|
|
@ -4,25 +4,36 @@ describe Oga::XPath::Compiler do
|
||||||
describe 'sum() spec' do
|
describe 'sum() spec' do
|
||||||
before do
|
before do
|
||||||
@document = parse('<root><a>1</a><b>2</b></root>')
|
@document = parse('<root><a>1</a><b>2</b></root>')
|
||||||
|
|
||||||
|
@a1 = @document.children[0].children[0]
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns the sum of the <root> node' do
|
describe 'at the top-level' do
|
||||||
# The test of <root> is "12", which is then converted to a number.
|
it 'returns the sum of the <root> node' do
|
||||||
evaluate_xpath(@document, 'sum(root)').should == 12.0
|
# The test of <root> is "12", which is then converted to a number.
|
||||||
|
evaluate_xpath(@document, 'sum(root)').should == 12.0
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the sum of the child nodes of the <root> node' do
|
||||||
|
evaluate_xpath(@document, 'sum(root/*)').should == 3.0
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns zero by default' do
|
||||||
|
evaluate_xpath(@document, 'sum(foo)').should be_zero
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'raises a TypeError for non node set arguments' do
|
||||||
|
block = -> { evaluate_xpath(@document, 'sum("foo")') }
|
||||||
|
|
||||||
|
block.should raise_error(TypeError)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns the sum of the child nodes of the <root> node' do
|
describe 'in a predicate' do
|
||||||
evaluate_xpath(@document, 'sum(root/*)').should == 3.0
|
it 'returns a NodeSet containing all matching nodes' do
|
||||||
end
|
evaluate_xpath(@document, 'root/a[sum(/root/*)]')
|
||||||
|
.should == node_set(@a1)
|
||||||
it 'returns zero by default' do
|
end
|
||||||
evaluate_xpath(@document, 'sum(foo)').should be_zero
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'raises a TypeError for non node set arguments' do
|
|
||||||
block = -> { evaluate_xpath(@document, 'sum("foo")') }
|
|
||||||
|
|
||||||
block.should raise_error(TypeError)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue