From 97e59fe449ed864bcf5e053b0198e8f33118196c Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 7 Aug 2014 20:03:26 +0200 Subject: [PATCH] Use the Namespace class for namespaces vs Strings. --- lib/oga/xml/attribute.rb | 13 +++-- lib/oga/xml/element.rb | 24 +++++++--- lib/oga/xml/parser.y | 9 +++- lib/oga/xpath/evaluator.rb | 2 +- spec/oga/xml/attribute_spec.rb | 21 ++++++-- spec/oga/xml/element_spec.rb | 58 ++++++++++++++++++----- spec/oga/xml/parser/elements_spec.rb | 6 +-- spec/oga/xpath/evaluator/general_spec.rb | 4 +- spec/oga/xpath/evaluator/wildcard_spec.rb | 8 ++-- 9 files changed, 110 insertions(+), 35 deletions(-) diff --git a/lib/oga/xml/attribute.rb b/lib/oga/xml/attribute.rb index ae1af3f..7b940bb 100644 --- a/lib/oga/xml/attribute.rb +++ b/lib/oga/xml/attribute.rb @@ -9,7 +9,7 @@ module Oga # # @!attribute [rw] namespace # The namespace of the attribute. - # @return [String] + # @return [Oga::XML::Namespace] # # @!attribute [rw] value # The value of the attribute. @@ -22,10 +22,17 @@ module Oga # @param [Hash] options # # @option options [String] :name - # @option options [String] :namespace + # @option options [Oga::XML::Namespace] :namespace # @option options [String] :value # def initialize(options = {}) + if options[:namespace] and !options[:namespace].is_a?(Namespace) + raise( + TypeError, + ':namespace must be an instance of Oga::XML::Namespace' + ) + end + @name = options[:name] @namespace = options[:namespace] @value = options[:value] @@ -54,7 +61,7 @@ module Oga [:name, :namespace, :value].each do |attr| value = send(attr) - if value and !value.empty? + if value segments << "#{attr}: #{value.inspect}" end end diff --git a/lib/oga/xml/element.rb b/lib/oga/xml/element.rb index 6fedff4..78c80f3 100644 --- a/lib/oga/xml/element.rb +++ b/lib/oga/xml/element.rb @@ -10,7 +10,7 @@ module Oga # # @!attribute [rw] namespace # The namespace of the element, if any. - # @return [String] + # @return [Oga::XML::Namespace] # # @!attribute [rw] attributes # The attributes of the element. @@ -23,11 +23,21 @@ module Oga # @param [Hash] options # # @option options [String] :name The name of the element. - # @option options [String] :namespace The namespace of the element. + # + # @option options [Oga::XML::Namespace] :namespace The namespace of the + # element. + # # @option options [Array] :attributes The attributes # of the element as an Array. # def initialize(options = {}) + if options[:namespace] and !options[:namespace].is_a?(Namespace) + raise( + TypeError, + ':namespace must be an instance of Oga::XML::Namespace' + ) + end + super @name = options[:name] @@ -100,7 +110,7 @@ module Oga attrs = " #{attrs}" unless attrs.empty? - return "<#{ns}#{name}#{attrs}>#{body}" + return "<#{ns}#{name}#{attrs}>#{body}" end ## @@ -119,9 +129,11 @@ module Oga [:name, :namespace, :attributes].each do |attr| value = send(attr) - if value and !value.empty? - segments << "#{attr}: #{value.inspect}" + if !value or (value.respond_to?(:empty?) and value.empty?) + next end + + segments << "#{attr}: #{value.inspect}" end return <<-EOF.chomp @@ -163,7 +175,7 @@ module Oga ns_matches = false if ns - ns_matches = attr.namespace == ns + ns_matches = attr.namespace.to_s == ns elsif name_matches ns_matches = true diff --git a/lib/oga/xml/parser.y b/lib/oga/xml/parser.y index 52c1f2f..f7de1c7 100644 --- a/lib/oga/xml/parser.y +++ b/lib/oga/xml/parser.y @@ -148,7 +148,12 @@ rule : T_ATTR { Attribute.new(:name => val[0]) } # foo:bar - | T_ATTR_NS T_ATTR { Attribute.new(:namespace => val[0], :name => val[1]) } + | T_ATTR_NS T_ATTR + { + ns = Namespace.new(:name => val[0]) + + Attribute.new(:namespace => ns, :name => val[1]) + } ; # XML declarations @@ -334,7 +339,7 @@ Unexpected #{name} with value #{value.inspect} on line #{@line}: # def on_element(namespace, name, attributes = {}) element = Element.new( - :namespace => namespace, + :namespace => Namespace.new(:name => namespace), :name => name, :attributes => attributes ) diff --git a/lib/oga/xpath/evaluator.rb b/lib/oga/xpath/evaluator.rb index ee34e32..02206e3 100644 --- a/lib/oga/xpath/evaluator.rb +++ b/lib/oga/xpath/evaluator.rb @@ -439,7 +439,7 @@ module Oga ns_matches = false if ns - ns_matches = xml_node.namespace == ns || ns == '*' + ns_matches = xml_node.namespace.to_s == ns || ns == '*' # If there's no namespace given but the name matches we'll also mark # the namespace as matching. diff --git a/spec/oga/xml/attribute_spec.rb b/spec/oga/xml/attribute_spec.rb index 59faadc..8b940fb 100644 --- a/spec/oga/xml/attribute_spec.rb +++ b/spec/oga/xml/attribute_spec.rb @@ -7,7 +7,16 @@ describe Oga::XML::Attribute do end example 'set the namespace' do - described_class.new(:namespace => 'a').namespace.should == 'a' + ns = Oga::XML::Namespace.new(:name => 'foo') + attr = described_class.new(:namespace => ns) + + attr.namespace.should == ns + end + + example 'raise TypeError when using a String for the namespace' do + block = lambda { described_class.new(:namespace => 'x') } + + block.should raise_error(TypeError) end example 'set the value' do @@ -35,9 +44,15 @@ describe Oga::XML::Attribute do context '#inspect' do example 'return the inspect value' do - obj = described_class.new(:name => 'a', :namespace => 'b', :value => 'c') + obj = described_class.new( + :name => 'a', + :namespace => Oga::XML::Namespace.new(:name => 'b'), + :value => 'c' + ) - obj.inspect.should == 'Attribute(name: "a" namespace: "b" value: "c")' + obj.inspect.should == <<-EOF.strip +Attribute(name: "a" namespace: Namespace(name: "b") value: "c") +EOF end end end diff --git a/spec/oga/xml/element_spec.rb b/spec/oga/xml/element_spec.rb index 71a6876..b117152 100644 --- a/spec/oga/xml/element_spec.rb +++ b/spec/oga/xml/element_spec.rb @@ -6,6 +6,12 @@ describe Oga::XML::Element do described_class.new(:name => 'p').name.should == 'p' end + example 'raise TypeError when the namespace is a String' do + block = lambda { described_class.new(:namespace => 'x') } + + block.should raise_error(TypeError) + end + example 'set the name via a setter' do instance = described_class.new instance.name = 'p' @@ -25,7 +31,7 @@ describe Oga::XML::Element do Oga::XML::Attribute.new( :name => 'key', :value => 'foo', - :namespace => 'x' + :namespace => Oga::XML::Namespace.new(:name => 'x') ) ] @@ -103,9 +109,12 @@ describe Oga::XML::Element do end example 'include the namespace if present' do - instance = described_class.new(:name => 'p', :namespace => 'foo') + instance = described_class.new( + :name => 'p', + :namespace => Oga::XML::Namespace.new(:name => 'foo') + ) - instance.to_xml.should == '

' + instance.to_xml.should == '' end example 'include the attributes if present' do @@ -130,22 +139,47 @@ describe Oga::XML::Element do end context '#inspect' do - before do - children = [Oga::XML::Comment.new(:text => 'foo')] - @instance = described_class.new( - :name => 'p', - :children => children, - :attributes => {'class' => 'foo'} - ) + example 'inspect a node with a name' do + node = described_class.new(:name => 'a') + + node.inspect.should == <<-EOF.strip +Element( + name: "a" + children: [ + +]) + EOF end - example 'pretty-print the node' do - @instance.inspect.should == <<-EOF.strip + example 'inspect a node with attributes and children' do + node = described_class.new( + :name => 'p', + :children => [Oga::XML::Comment.new(:text => 'foo')], + :attributes => {'class' => 'foo'} + ) + + node.inspect.should == <<-EOF.strip Element( name: "p" attributes: {"class"=>"foo"} children: [ Comment(text: "foo") +]) + EOF + end + + example 'inspect a node with a namespace' do + node = described_class.new( + :name => 'p', + :namespace => Oga::XML::Namespace.new(:name => 'x') + ) + + node.inspect.should == <<-EOF.strip +Element( + name: "p" + namespace: Namespace(name: "x") + children: [ + ]) EOF end diff --git a/spec/oga/xml/parser/elements_spec.rb b/spec/oga/xml/parser/elements_spec.rb index d751531..61c5285 100644 --- a/spec/oga/xml/parser/elements_spec.rb +++ b/spec/oga/xml/parser/elements_spec.rb @@ -17,7 +17,7 @@ describe Oga::XML::Parser do context 'elements with namespaces' do before :all do - @element = parse('

').children[0] + @element = parse('').children[0] end example 'return an Element instance' do @@ -29,7 +29,7 @@ describe Oga::XML::Parser do end example 'set the namespace of the element' do - @element.namespace.should == 'foo' + @element.namespace.name.should == 'foo' end end @@ -57,7 +57,7 @@ describe Oga::XML::Parser do end example 'include the namespace of the attribute' do - @element.attribute('x:bar').namespace.should == 'x' + @element.attribute('x:bar').namespace.name.should == 'x' end example 'include the name of the attribute' do diff --git a/spec/oga/xpath/evaluator/general_spec.rb b/spec/oga/xpath/evaluator/general_spec.rb index 5424def..fca0a91 100644 --- a/spec/oga/xpath/evaluator/general_spec.rb +++ b/spec/oga/xpath/evaluator/general_spec.rb @@ -26,8 +26,10 @@ describe Oga::XPath::Evaluator do context '#node_matches?' do before do + ns = Oga::XML::Namespace.new(:name => 'x') + @name_node = Oga::XML::Element.new(:name => 'a') - @name_ns_node = Oga::XML::Element.new(:name => 'b', :namespace => 'x') + @name_ns_node = Oga::XML::Element.new(:name => 'b', :namespace => ns) end example 'return true if a node is matched by its name' do diff --git a/spec/oga/xpath/evaluator/wildcard_spec.rb b/spec/oga/xpath/evaluator/wildcard_spec.rb index a30191f..c096156 100644 --- a/spec/oga/xpath/evaluator/wildcard_spec.rb +++ b/spec/oga/xpath/evaluator/wildcard_spec.rb @@ -22,8 +22,8 @@ describe Oga::XPath::Evaluator do end example 'include the node' do - @set[2].name.should == 'c' - @set[2].namespace.should == 'ns1' + @set[2].name.should == 'c' + @set[2].namespace.name.should == 'ns1' end end @@ -55,8 +55,8 @@ describe Oga::XPath::Evaluator do it_behaves_like :node_set, :length => 1 example 'include the correct node' do - @set[0].name.should == 'c' - @set[0].namespace.should == 'ns1' + @set[0].name.should == 'c' + @set[0].namespace.name.should == 'ns1' end end