Basic support for the XPath node() function.

This commit is contained in:
Yorick Peterse 2014-08-14 18:17:08 +02:00
parent a133b923a2
commit 23441bb5a4
2 changed files with 103 additions and 0 deletions

View File

@ -420,6 +420,59 @@ module Oga
return nodes return nodes
end end
##
# Dispatches function calls to specific handlers.
#
# @param [Oga::XPath::Node] ast_node
# @param [Oga::XML::NodeSet] context
# @return [Oga::XML::NodeSet]
#
def on_call(ast_node, context)
name, test = *ast_node
handler = name.gsub('-', '_')
return send("on_call_#{handler}", test, context)
end
##
# Processes the `node` function call. The W3 was apparently too lazy to
# properly document this function in their official specification. From
# Wikipedia:
#
# node()
# finds any node at all.
#
# Based on trial and error this function appears to match the following:
#
# * elements
# * text nodes
# * comments
# * CDATA nodes
#
# In Oga this translates to the following two classes:
#
# * {Oga::XML::Element}
# * {Oga::XML::Text}
#
# @param [Oga::XPath::Node] ast_node
# @param [Oga::XML::NodeSet] context
# @return [Oga::XML::NodeSet]
#
def on_call_node(ast_node, context)
nodes = XML::NodeSet.new
context.each do |context_node|
context_node.children.each do |child|
if child.is_a?(XML::Element) or child.is_a?(XML::Text)
nodes << child
end
end
end
return nodes
end
## ##
# Returns a node set containing all the child nodes of the given set of # Returns a node set containing all the child nodes of the given set of
# nodes. # nodes.

View File

@ -0,0 +1,50 @@
require 'spec_helper'
describe Oga::XPath::Evaluator do
context 'node function' do
before do
@document = parse('<a><b>foo</b></a>')
@evaluator = described_class.new(@document)
end
context 'matching elements' do
before do
@set = @evaluator.evaluate('node()')
end
it_behaves_like :node_set, :length => 1
example 'return the <a> node' do
@set[0].name.should == 'a'
end
end
context 'matching nested elements' do
before do
@set = @evaluator.evaluate('a/node()')
end
it_behaves_like :node_set, :length => 1
example 'return the <b> node' do
@set[0].name.should == 'b'
end
end
context 'matching text nodes' do
before do
@set = @evaluator.evaluate('a/b/node()')
end
it_behaves_like :node_set, :length => 1
example 'return a Text instance' do
@set[0].is_a?(Oga::XML::Text).should == true
end
example 'include the text' do
@set[0].text.should == 'foo'
end
end
end
end