From b06eadc8122f457cb5f38ac0f0eadfaa2ac31bd9 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Mon, 15 Sep 2014 17:06:58 +0200 Subject: [PATCH] XPath support for absolute paths without tests. This allows Oga to parse and evaluate the XPath expression "/". This expression can be used to select just the root node/document. This fixes #35. --- lib/oga/xpath/evaluator.rb | 3 ++- lib/oga/xpath/parser.y | 1 + spec/oga/xpath/evaluator/paths_spec.rb | 12 ++++++++++++ spec/oga/xpath/parser/paths_spec.rb | 4 ++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/oga/xpath/evaluator.rb b/lib/oga/xpath/evaluator.rb index 197b566..2ad4913 100644 --- a/lib/oga/xpath/evaluator.rb +++ b/lib/oga/xpath/evaluator.rb @@ -131,7 +131,8 @@ module Oga context = XML::NodeSet.new([@document]) end - return on_path(ast_node, context) + # If the expression is just "/" we'll just return the current context. + return ast_node.children.empty? ? context : on_path(ast_node, context) end ## diff --git a/lib/oga/xpath/parser.y b/lib/oga/xpath/parser.y index 6d1ee3b..1a796ec 100644 --- a/lib/oga/xpath/parser.y +++ b/lib/oga/xpath/parser.y @@ -66,6 +66,7 @@ rule absolute_path : T_SLASH path_members { s(:absolute_path, *val[1]) } | T_SLASH path_member { s(:absolute_path, val[1]) } + | T_SLASH { s(:absolute_path) } ; # Whenever a bare test is used (e.g. just "A") this actually means "child::A". diff --git a/spec/oga/xpath/evaluator/paths_spec.rb b/spec/oga/xpath/evaluator/paths_spec.rb index d239c3c..7833c83 100644 --- a/spec/oga/xpath/evaluator/paths_spec.rb +++ b/spec/oga/xpath/evaluator/paths_spec.rb @@ -30,6 +30,18 @@ describe Oga::XPath::Evaluator do end end + context 'absolute paths without node tests' do + before do + @set = described_class.new(@document).evaluate('/') + end + + it_behaves_like :node_set, :length => 1 + + example 'return the root document' do + @set[0].is_a?(Oga::XML::Document).should == true + end + end + context 'invalid absolute paths' do before do @set = described_class.new(@document).evaluate('/x/a') diff --git a/spec/oga/xpath/parser/paths_spec.rb b/spec/oga/xpath/parser/paths_spec.rb index 482eae6..ec907c8 100644 --- a/spec/oga/xpath/parser/paths_spec.rb +++ b/spec/oga/xpath/parser/paths_spec.rb @@ -20,5 +20,9 @@ describe Oga::XPath::Parser do s(:axis, 'child', s(:test, nil, 'B')) ) end + + example 'parse an absolute path without a node test' do + parse_xpath('/').should == s(:absolute_path) + end end end