From fe8f77cf452e29827f7a098cae96cc2d46aee5bf Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 8 Aug 2014 19:03:42 +0200 Subject: [PATCH] Basic work for supporting namespace URIs. --- lib/oga/xml/element.rb | 21 +++++++ lib/oga/xpath/evaluator.rb | 50 ++++++++++++++--- spec/oga/xml/element_spec.rb | 4 ++ .../xpath/evaluator/axes/namespace_spec.rb | 55 +++++++++++++++++++ spec/oga/xpath/evaluator/general_spec.rb | 14 ----- 5 files changed, 121 insertions(+), 23 deletions(-) create mode 100644 spec/oga/xpath/evaluator/axes/namespace_spec.rb diff --git a/lib/oga/xml/element.rb b/lib/oga/xml/element.rb index 5c2643d..9b490cd 100644 --- a/lib/oga/xml/element.rb +++ b/lib/oga/xml/element.rb @@ -145,6 +145,27 @@ module Oga return :element end + ## + # Returns a node set of all the namespaces that are available to the + # current node. This includes the namespaces registered on the current + # node. + # + # @return [Oga::XML::NodeSet] + # + def available_namespaces + + end + + ## + # Returns a node set of all the namespaces registered with the current + # node. + # + # @return [Oga::XML::NodeSet] + # + def namespaces + + end + private ## diff --git a/lib/oga/xpath/evaluator.rb b/lib/oga/xpath/evaluator.rb index 02206e3..4f6f90f 100644 --- a/lib/oga/xpath/evaluator.rb +++ b/lib/oga/xpath/evaluator.rb @@ -398,6 +398,24 @@ module Oga return nodes end + ## + # Evaluates the `namespace` axis. + # + # @param [Oga::XPath::Node] ast_node + # @param [Oga::XML::NodeSet] context + # @return [Oga::XML::NodeSet] + # + def on_axis_namespace(ast_node, context) + nodes = XML::NodeSet.new + name = ast_node.children[1] + + context.each do |context_node| + + end + + return nodes + end + ## # Returns a node set containing all the child nodes of the given set of # nodes. @@ -431,15 +449,13 @@ module Oga # @return [Oga::XML::NodeSet] # def node_matches?(xml_node, ast_node) - return false unless can_match_node?(xml_node) - ns, name = *ast_node - name_matches = xml_node.name == name || name == '*' + name_matches = name_matches?(xml_node, name) ns_matches = false if ns - ns_matches = xml_node.namespace.to_s == ns || ns == '*' + ns_matches = namespace_matches?(xml_node, ns) # If there's no namespace given but the name matches we'll also mark # the namespace as matching. @@ -454,13 +470,29 @@ module Oga end ## - # Returns `true` if the given XML node can be compared using - # {#node_matches?}. + # Returns `true` if the name of the XML node matches the given name *or* + # matches a wildcard. # - # @param [Oga::XML::Node] ast_node + # @param [Oga::XML::Node] xml_node + # @param [String] name # - def can_match_node?(ast_node) - return ast_node.respond_to?(:name) && ast_node.respond_to?(:namespace) + def name_matches?(xml_node, name) + return false unless xml_node.respond_to?(:name) + + return xml_node.name == name || name == '*' + end + + ## + # Returns `true` if the namespace of the XML node matches the given + # namespace *or* matches a wildcard. + # + # @param [Oga::XML::Node] xml_node + # @param [String] ns + # + def namespace_matches?(xml_node, ns) + return false unless xml_node.respond_to?(:namespace) + + return xml_node.namespace.to_s == ns || ns == '*' end ## diff --git a/spec/oga/xml/element_spec.rb b/spec/oga/xml/element_spec.rb index f1eebba..cd9a353 100644 --- a/spec/oga/xml/element_spec.rb +++ b/spec/oga/xml/element_spec.rb @@ -177,4 +177,8 @@ describe Oga::XML::Element do described_class.new.node_type.should == :element end end + + context '#available_namespaces' do + # TODO: write me + end end diff --git a/spec/oga/xpath/evaluator/axes/namespace_spec.rb b/spec/oga/xpath/evaluator/axes/namespace_spec.rb new file mode 100644 index 0000000..6df1acb --- /dev/null +++ b/spec/oga/xpath/evaluator/axes/namespace_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe Oga::XPath::Evaluator do + context 'namespace axis' do + before do + @document = parse(<<-EOF.strip) + + + + EOF + + @evaluator = described_class.new(@document) + end + + context 'matching namespaces in the root element' do + before do + @set = @evaluator.evaluate('root/namespace::x') + end + + it_behaves_like :node_set, :length => 1 + + example 'return a Namespace instance' do + @set[0].is_a?(Oga::XML::Namespace).should == true + end + + example 'return the "x" namespace' do + @set[0].name.should == 'x' + end + end + + context 'matching namespaces in a nested element' do + before do + @set = @evaluator.evaluate('root/namespace::x') + end + + it_behaves_like :node_set, :length => 2 + + example 'return the "x" namespace' do + @set[0].name.should == 'x' + end + + example 'return the "y" namespace' do + @set[1].name.should == 'y' + end + end + + context 'matching namespace nodes using a wildcard' do + before do + @set = @evaluator.evaluate('root/namespace::*') + end + + it_behaves_like :node_set, :length => 1 + end + end +end diff --git a/spec/oga/xpath/evaluator/general_spec.rb b/spec/oga/xpath/evaluator/general_spec.rb index fca0a91..b73f2d0 100644 --- a/spec/oga/xpath/evaluator/general_spec.rb +++ b/spec/oga/xpath/evaluator/general_spec.rb @@ -71,20 +71,6 @@ describe Oga::XPath::Evaluator do end end - context '#can_match_node?' do - example 'return true for an XML::Element instance' do - @evaluator.can_match_node?(Oga::XML::Element.new).should == true - end - - example 'return true for an XML::Attribute instance' do - @evaluator.can_match_node?(Oga::XML::Attribute.new).should == true - end - - example 'return false for an XML::Text instance' do - @evaluator.can_match_node?(Oga::XML::Text.new).should == false - end - end - context '#has_parent?' do before do @parent = Oga::XML::Element.new