diff --git a/lib/oga/xpath/evaluator.rb b/lib/oga/xpath/evaluator.rb index dbcbb2f..df1eef7 100644 --- a/lib/oga/xpath/evaluator.rb +++ b/lib/oga/xpath/evaluator.rb @@ -601,7 +601,7 @@ module Oga # @return [Oga::XML::NodeSet] # def on_call(ast_node, context) - name, args = *ast_node + name, *args = *ast_node handler = name.gsub('-', '_') @@ -633,6 +633,36 @@ module Oga return index.to_f end + ## + # Processes the `count()` function call. This function counts the amount + # of nodes in `expression` and returns the result as a float. + # + # @param [Oga::XML::NodeSet] context + # @param [Oga::XPath::Node] expression + # @return [Float] + # + def on_call_count(context, expression) + retval = process(expression, context) + + unless retval.is_a?(XML::NodeSet) + raise TypeError, 'count() can only operate on NodeSet instances' + end + + return retval.length.to_f + end + + ## + # Processes an `(int)` node. This method simply returns the value as a + # Float. + # + # @param [Oga::XPath::Node] ast_node + # @param [Oga::XML::NodeSet] context + # @return [Float] + # + def on_int(ast_node, context) + return ast_node.children[0].to_f + end + ## # Returns a node set containing all the child nodes of the given set of # nodes. diff --git a/spec/oga/xpath/evaluator/calls/count_spec.rb b/spec/oga/xpath/evaluator/calls/count_spec.rb new file mode 100644 index 0000000..379d284 --- /dev/null +++ b/spec/oga/xpath/evaluator/calls/count_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Oga::XPath::Evaluator do + context 'count() function' do + before do + @document = parse('') + @evaluator = described_class.new(@document) + end + + example 'return the amount of nodes as a Float' do + @evaluator.evaluate('count(root)').is_a?(Float).should == true + end + + example 'count the amount of nodes' do + @evaluator.evaluate('count(root)').should == 1 + end + + example 'count the amount of nodes' do + @evaluator.evaluate('count(root/a)').should == 2 + end + + example 'count the amount of nodes' do + @evaluator.evaluate('count(root/a/b)').should == 1 + end + + example 'raise ArgumentError if no arguments are given' do + block = lambda { @evaluator.evaluate('count()') } + + block.should raise_error(ArgumentError) + end + + example 'raise TypeError if the argument is not a NodeSet' do + block = lambda { @evaluator.evaluate('count(1)') } + + block.should raise_error(TypeError) + end + end +end diff --git a/spec/oga/xpath/evaluator/types/int_spec.rb b/spec/oga/xpath/evaluator/types/int_spec.rb new file mode 100644 index 0000000..7321f2f --- /dev/null +++ b/spec/oga/xpath/evaluator/types/int_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe Oga::XPath::Evaluator do + context 'integer types' do + before do + document = parse('') + evaluator = described_class.new(document) + @number = evaluator.evaluate('1') + end + + example 'return literal integers' do + @number.should == 1 + end + + example 'return integers as floats' do + @number.is_a?(Float).should == true + end + end +end