XPath queries match nodes in the default namespace

When querying an XML document that explicitly defines the default XML
namespace the XPath evaluator now correctly matches all nodes within
that namespace if no namespace prefix is given in the query. Previously
this would always return an empty set.
This commit is contained in:
Yorick Peterse 2015-03-26 01:13:55 +01:00
parent f175414917
commit 5adeae18d0
2 changed files with 79 additions and 46 deletions

View File

@ -1657,6 +1657,11 @@ module Oga
ns_matches = true
end
if !ns and !ns_matches
ns_matches = xml_node.respond_to?(:default_namespace?) &&
xml_node.default_namespace?
end
return name_matches && ns_matches
end

View File

@ -62,61 +62,89 @@ describe Oga::XPath::Evaluator do
end
describe '#node_matches?' do
before do
@name_node = Oga::XML::Element.new(:name => 'a')
@name_ns_node = Oga::XML::Element.new(:name => 'b', :namespace_name => 'x')
describe 'without a namespace' do
before do
@node = Oga::XML::Element.new(:name => 'a')
end
@name_ns_node.register_namespace('x', 'y')
it 'returns true if a node is matched by its name' do
@evaluator.node_matches?(@node, s(:test, nil, 'a')).should == true
end
it 'returns true if a node is matched by a wildcard name' do
@evaluator.node_matches?(@node, s(:test, nil, '*')).should == true
end
it 'returns false if a node is not matched by its name' do
@evaluator.node_matches?(@node, s(:test, nil, 'foo')).should == false
end
it 'returns true if a node is matched without having a namespace' do
@evaluator.node_matches?(@node, s(:test, '*', 'a')).should == true
end
it 'returns true if the node type matches' do
@evaluator.node_matches?(@node, s(:type_test, 'node')).should == true
end
it 'returns false when trying to match an XML::Text instance' do
text = Oga::XML::Text.new(:text => 'Foobar')
@evaluator.node_matches?(text, s(:test, nil, 'a')).should == false
end
end
it 'returns true if a node is matched by its name' do
@evaluator.node_matches?(@name_node, s(:test, nil, 'a')).should == true
describe 'with a custom namespace' do
before do
@node = Oga::XML::Element.new(:name => 'b', :namespace_name => 'x')
@node.register_namespace('x', 'y')
end
it 'returns true if a node is matched by its name and namespace' do
@evaluator.node_matches?(@node, s(:test, 'x', 'b')).should == true
end
it 'returns false if a node is not matched by its namespace' do
@evaluator.node_matches?(@node, s(:test, 'y', 'b')).should == false
end
it 'returns true if a node is matched by a wildcard namespace' do
@evaluator.node_matches?(@node, s(:test, '*', 'b')).should == true
end
it 'returns true if a node is matched by a full wildcard search' do
@evaluator.node_matches?(@node, s(:test, '*', '*')).should == true
end
it 'returns false when the node has a namespace that is not given' do
@evaluator.node_matches?(@node, s(:test, nil, 'b')).should == false
end
it 'returns true if a node with a namespace is matched using a wildcard' do
@evaluator.node_matches?(@node, s(:test, nil, '*')).should == true
end
end
it 'returns true if a node is matched by a wildcard name' do
@evaluator.node_matches?(@name_node, s(:test, nil, '*')).should == true
end
describe 'using the default XML namespace' do
before do
@node = Oga::XML::Element.new(:name => 'a')
ns = Oga::XML::DEFAULT_NAMESPACE
it 'returns false if a node is not matched by its name' do
@evaluator.node_matches?(@name_node, s(:test, nil, 'foo')).should == false
end
@node.register_namespace(ns.name, ns.uri)
end
it 'returns true if a node is matched by its name and namespace' do
@evaluator.node_matches?(@name_ns_node, s(:test, 'x', 'b')).should == true
end
it 'returns true when the node name matches' do
@evaluator.node_matches?(@node, s(:test, nil, 'a')).should == true
end
it 'returns false if a node is not matched by its namespace' do
@evaluator.node_matches?(@name_ns_node, s(:test, 'y', 'b')).should == false
end
it 'returns true when the namespace prefix and node name match' do
@evaluator.node_matches?(@node, s(:test, 'xmlns', 'a')).should == true
end
it 'returns true if a node is matched by a wildcard namespace' do
@evaluator.node_matches?(@name_ns_node, s(:test, '*', 'b')).should == true
end
it 'returns true if a node is matched by a full wildcard search' do
@evaluator.node_matches?(@name_ns_node, s(:test, '*', '*')).should == true
end
it 'returns true if a node is matched without having a namespace' do
@evaluator.node_matches?(@name_node, s(:test, '*', 'a')).should == true
end
it 'returns false when trying to match an XML::Text instance' do
text = Oga::XML::Text.new(:text => 'Foobar')
@evaluator.node_matches?(text, s(:test, nil, 'a')).should == false
end
it 'returns false when the node has a namespace that is not given' do
@evaluator.node_matches?(@name_ns_node, s(:test, nil, 'b')).should == false
end
it 'returns true if a node with a namespace is matched using a wildcard' do
@evaluator.node_matches?(@name_ns_node, s(:test, nil, '*')).should == true
end
it 'returns true if the node type matches' do
@evaluator.node_matches?(@name_node, s(:type_test, 'node')).should == true
it 'returns false when the node name does not match' do
@evaluator.node_matches?(@node, s(:test, nil, 'b')).should == false
end
end
end