xml-object 0.9.8 → 0.9.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/WHATSNEW CHANGED
@@ -1,3 +1,6 @@
1
+ * 0.9.9 (2008-12-18):
2
+ - Bugfix for the new faster-than-nokogiri Hpricot version (broke the API)
3
+
1
4
  * 0.9.8 (2008-10-23):
2
5
  - Much improved test suite. More granular, better coverage, much faster
3
6
  - The collection proxy behaviour is now a lot faster when called in a loop
@@ -5,43 +5,40 @@ $:.unshift File.join(File.dirname(__FILE__), 'xml-object')
5
5
 
6
6
  require 'adapters'
7
7
  require 'adapters/rexml'
8
- require 'array_notation'
8
+ require 'properties'
9
9
  require 'collection_proxy'
10
10
  require 'element'
11
- require 'method_missing_dispatchers'
12
11
 
13
12
  module XMLObject
14
13
  # Returns a String or Array object representing the given XML, decorated
15
14
  # with methods to access attributes and/or child elements.
16
- def self.new(duck)
15
+ def self.new(duck) # :nodoc:
17
16
  case duck
18
- when adapter::Element then new_decorated_obj(duck)
19
- when Array then duck.map { |d| new_decorated_obj(d) }
20
- else new adapter.new(duck)
17
+ when @adapter::Element then new_decorated_obj duck
18
+ when Array then duck.map! { |d| new_decorated_obj d }
19
+ else new @adapter.new(duck)
21
20
  end
22
21
  end
23
22
 
24
23
  private ##################################################################
25
24
 
26
- # Takes any Element object, and converts it recursively into
25
+ # Takes any adapter Element object, and converts it recursively into
27
26
  # the corresponding tree of decorated objects.
28
27
  def self.new_decorated_obj(xml) # :nodoc:
29
- obj = if ( (xml.value !~ /\S/) && (xml.children.size > 1) &&
30
- xml.children.collect { |e| e.name }.uniq.size == 1 )
28
+ # More than one child, empty value, and all children with the same name?
29
+ obj = if xml.children.size > 1 && xml.value !~ /\S/ &&
30
+ xml.children.map { |c| c.name }.uniq.size == 1
31
31
 
32
- CollectionProxy.new xml.children[0].name.to_sym
32
+ CollectionProxy.new xml # This is an empty array wrap
33
33
  else
34
- # Teach our string to behave like and XML Element
35
- xml.value.extend Element
34
+ Element.new xml # This one is an actual element
36
35
  end
37
36
 
38
- obj.instance_variable_set :@__raw_xml, xml.raw
37
+ xml.children.each { |child| add_child obj, child.name, new(child) }
38
+ xml.attributes.each { |name, value| add_attribute obj, name, value }
39
39
 
40
- xml.children.each { |child| add_child(obj, child.name, new(child)) }
41
- xml.attributes.each { |name, value| add_attribute(obj, name, value) }
42
-
43
- # Let's teach our object some new tricks:
44
- obj.extend ArrayNotation, MethodMissingDispatchers
40
+ # Let's teach our object how to access its XML elements and attributes
41
+ obj.extend Properties
45
42
  end
46
43
 
47
44
  # Decorates the given object 'obj' with a method 'name' that returns the
@@ -65,12 +62,11 @@ module XMLObject
65
62
 
66
63
  # Decorates the given object 'obj' with a method 'name' that returns the
67
64
  # given 'attr_value'.
68
- def self.add_attribute(obj, name, attr_value) # :nodoc:
69
-
65
+ def self.add_attribute(obj, name, value) # :nodoc:
70
66
  attributes = obj.instance_variable_get :@__attributes
71
- attributes[(key = name.to_sym)] = attr_value.strip.gsub(/\s+/, ' ')
67
+ attributes[key = name.to_sym] = value.strip.gsub /\s+/, ' '
72
68
 
73
69
  obj.instance_variable_set :@__attributes, attributes
74
- attr_value
70
+ value
75
71
  end
76
72
  end
@@ -18,7 +18,7 @@ module XMLObject # :nodoc:
18
18
  private ###########################################################
19
19
 
20
20
  def text_value
21
- @text_nodes.reject { |n| n !~ /\S/ }.join
21
+ @text_value_memo ||= @text_nodes.reject { |n| n !~ /\S/ }.join
22
22
  end
23
23
 
24
24
  def cdata_value
@@ -7,9 +7,10 @@ module XMLObject::Adapters::Hpricot
7
7
  # either +read+ or +to_s+.
8
8
  def self.new(duck)
9
9
  case
10
- when duck.is_a?(::Hpricot::Elem) then Element.new(duck)
11
- when duck.respond_to?(:read) then new(::Hpricot::XML(duck.read).root)
12
- when duck.respond_to?(:to_s) then new(::Hpricot::XML(duck.to_s).root)
10
+ when duck.respond_to?(:read)
11
+ then Element.new(::Hpricot::XML(duck.read).root)
12
+ when duck.respond_to?(:to_s)
13
+ then Element.new(::Hpricot::XML(duck.to_s).root)
13
14
  else raise "Don't know how to deal with '#{duck.class}' object"
14
15
  end
15
16
  end
@@ -18,17 +19,18 @@ module XMLObject::Adapters::Hpricot
18
19
 
19
20
  class Element < XMLObject::Adapters::Base::Element # :nodoc:
20
21
  def initialize(xml)
21
- @raw, @name, @attributes = xml, xml.name, xml.attributes
22
+ @raw, @name = xml, xml.name
23
+ @attributes = xml.attributes || {}
22
24
 
23
25
  @element_nodes = xml.children.select { |c| c.elem? }
24
26
 
25
27
  @text_nodes = xml.children.select do |c|
26
28
  c.text? && !c.is_a?(::Hpricot::CData)
27
- end.map { |c| c.to_s }
29
+ end.map! { |c| c.to_s }
28
30
 
29
31
  @cdata_nodes = xml.children.select do |c|
30
32
  c.is_a? ::Hpricot::CData
31
- end.map { |c| c.to_s }
33
+ end.map! { |c| c.to_s }
32
34
 
33
35
  super
34
36
  end
@@ -6,11 +6,10 @@ module XMLObject::Adapters::LibXML
6
6
  # either +read+ or +to_s+.
7
7
  def self.new(duck)
8
8
  case
9
- when duck.is_a?(::LibXML::XML::Node) then Element.new(duck)
10
9
  when duck.respond_to?(:read)
11
- then new(::LibXML::XML::Parser.string(duck.read).parse.root)
10
+ then Element.new(::LibXML::XML::Parser.string(duck.read).parse.root)
12
11
  when duck.respond_to?(:to_s)
13
- then new(::LibXML::XML::Parser.string(duck.to_s).parse.root)
12
+ then Element.new(::LibXML::XML::Parser.string(duck.to_s).parse.root)
14
13
  else raise "Don't know how to deal with '#{duck.class}' object"
15
14
  end
16
15
  end
@@ -23,8 +22,8 @@ module XMLObject::Adapters::LibXML
23
22
 
24
23
  @element_nodes = xml.children.select { |c| c.element? }
25
24
 
26
- @text_nodes = xml.children.select { |c| c.text? }.map { |c| c.to_s }
27
- @cdata_nodes = xml.children.select { |c| c.cdata? }.map do |c|
25
+ @text_nodes = xml.children.select { |c| c.text? }.map! { |c| c.to_s }
26
+ @cdata_nodes = xml.children.select { |c| c.cdata? }.map! do |c|
28
27
  c.to_s.chomp(']]>').sub('<![CDATA[', '')
29
28
  end
30
29
 
@@ -6,11 +6,10 @@ module XMLObject::Adapters::REXML
6
6
  # either +read+ or +to_s+.
7
7
  def self.new(duck)
8
8
  case
9
- when duck.is_a?(::REXML::Element) then Element.new(duck)
10
9
  when duck.respond_to?(:read)
11
- then new(::REXML::Document.new(duck.read).root)
10
+ then Element.new(::REXML::Document.new(duck.read).root)
12
11
  when duck.respond_to?(:to_s)
13
- then new(::REXML::Document.new(duck.to_s).root)
12
+ then Element.new(::REXML::Document.new(duck.to_s).root)
14
13
  else raise "Don't know how to deal with '#{duck.class}' object"
15
14
  end
16
15
  end
@@ -25,11 +24,11 @@ module XMLObject::Adapters::REXML
25
24
 
26
25
  @text_nodes = xml.children.select do |child|
27
26
  child.class == ::REXML::Text
28
- end.collect { |child| child.to_s }
27
+ end.map! { |child| child.to_s }
29
28
 
30
29
  @cdata_nodes = xml.children.select do |child|
31
30
  child.class == ::REXML::CData
32
- end.collect { |child| child.to_s }
31
+ end.map! { |child| child.to_s }
33
32
 
34
33
  super
35
34
  end
@@ -3,15 +3,16 @@ class XMLObject::CollectionProxy # :nodoc:
3
3
  instance_methods.each do |m|
4
4
  meth_str, meth_sym = m.to_s, m.to_sym # Ruby 1.8 and 1.9 differ, so...
5
5
 
6
- undef_method meth_sym unless ( (meth_str =~ /^__/) ||
7
- (meth_str =~ /^instance_/) ||
8
- (meth_sym == :extend) ||
9
- (meth_sym == :nil?) ||
10
- (meth_sym == :object_id) )
6
+ undef_method meth_sym unless meth_str =~ /^__/ ||
7
+ meth_str =~ /^instance_/ ||
8
+ meth_sym == :extend ||
9
+ meth_sym == :nil? ||
10
+ meth_sym == :object_id
11
11
  end
12
12
 
13
- def initialize(target_kid_key) # :nodoc:
14
- @__children, @__attributes, @__target_kid = {}, {}, target_kid_key
13
+ def initialize(xml) # :nodoc:
14
+ @__children, @__attributes = {}, {}
15
+ @__target_kid = xml.children[0].name.to_sym
15
16
  end
16
17
 
17
18
  private ##################################################################
@@ -23,13 +24,13 @@ class XMLObject::CollectionProxy # :nodoc:
23
24
  if dispatched.nil? && @__children[@__target_kid].respond_to?(m)
24
25
  dispatched = @__children[@__target_kid].__send__(m, *a, &b)
25
26
 
26
- unless dispatched.nil?
27
+ unless nil == dispatched
27
28
  # All is fair in Love and War. And 100% coverage.
28
29
  instance_eval \
29
30
  %{ def #{m}(*a, &b); @__children[@__target_kid].#{m}(*a, &b); end }
30
31
  end
31
32
  end
32
33
 
33
- dispatched.nil? ? raise(NameError.new(m.to_s)) : dispatched
34
+ (nil == dispatched) ? raise(NameError.new(m.to_s)) : dispatched
34
35
  end
35
36
  end
@@ -1,8 +1,10 @@
1
1
  module XMLObject::Element
2
- def self.extended(obj) # :nodoc:
3
- obj.instance_variable_set :@__children, {}
4
- obj.instance_variable_set :@__attributes, {}
5
- obj
2
+ def self.new(xml) # :nodoc:
3
+ element = xml.value
4
+ element.instance_variable_set :@__raw_xml, xml.raw
5
+ element.instance_variable_set :@__children, {}
6
+ element.instance_variable_set :@__attributes, {}
7
+ element.extend self
6
8
  end
7
9
 
8
10
  # The raw, unadapted XML object. Whatever this is, it really depends on
@@ -1,4 +1,5 @@
1
- module XMLObject::ArrayNotation
1
+ module XMLObject::Properties
2
+
2
3
  # Array-bracket (+[]+) notation access to elements and attributes. Use
3
4
  # when the element or attribute you need to reach is not reachable via dot
4
5
  # notation (because it's not a valid method name, or because the method
@@ -42,4 +43,54 @@ module XMLObject::ArrayNotation
42
43
  end
43
44
  end
44
45
  end
46
+
47
+ private ##################################################################
48
+
49
+ def __question_dispatch(meth, *args, &block)
50
+ return nil unless meth.to_s.match(/\?$/) && args.empty? && block.nil?
51
+
52
+ method_sans_question = meth.to_s.chomp('?').to_sym
53
+
54
+ if boolish = __send__(method_sans_question)
55
+ bool = case
56
+ when %w[ true yes t y ].include?(boolish.downcase) then true
57
+ when %w[ false no f n ].include?(boolish.downcase) then false
58
+ else nil
59
+ end
60
+
61
+ unless bool.nil?
62
+ instance_eval %{ def #{meth}; #{bool ? 'true' : 'false'}; end }
63
+ end
64
+
65
+ bool
66
+ end
67
+ end
68
+
69
+ def __dot_notation_dispatch(meth, *args, &block)
70
+ return nil unless args.empty? && block.nil?
71
+
72
+ if @__children.has_key?(meth)
73
+ instance_eval %{ def #{meth}; @__children[%s|#{meth}|]; end }
74
+ @__children[meth]
75
+
76
+ elsif @__attributes.has_key?(meth)
77
+ instance_eval %{ def #{meth}; @__attributes[%s|#{meth}|]; end }
78
+ @__attributes[meth]
79
+
80
+ elsif @__children.has_key?(naive_sing = meth.to_s.chomp('s').to_sym) &&
81
+ @__children[naive_sing].is_a?(Array)
82
+
83
+ instance_eval %{ def #{meth}; @__children[%s|#{naive_sing}|]; end }
84
+ @__children[naive_sing]
85
+
86
+ elsif defined?(ActiveSupport::Inflector) &&
87
+ @__children.has_key?(singular = meth.to_s.singularize.to_sym) &&
88
+ @__children[singular].is_a?(Array)
89
+
90
+ instance_eval %{ def #{meth}; @__children[%s|#{singular}|]; end }
91
+ @__children[singular]
92
+ else
93
+ nil
94
+ end
95
+ end
45
96
  end
@@ -1,11 +1,9 @@
1
- Gem::Specification.new do |gem|
2
- gem.rubyforge_project = 'xml-object'
1
+ XMLOBJECT_GEMSPEC = Gem::Specification.new do |gem|
2
+ gem.name = gem.rubyforge_project = 'xml-object'
3
+ gem.homepage = 'http://xml-object.rubyforge.org'
3
4
 
4
- gem.name = 'xml-object'
5
- gem.homepage = 'http://github.com/jordi/xml-object'
6
-
7
- gem.version, gem.date = '0.9.8', '2008-10-23'
8
- gem.author, gem.email = 'Jordi Bunster', 'jordi@bunster.org'
5
+ gem.version, gem.date = '0.9.9', '2008-12-18'
6
+ gem.author, gem.email = 'Jordi Bunster', 'jordi@bunster.org'
9
7
 
10
8
  gem.summary = "The Rubyista's way to do quick XML sit-ups"
11
9
  gem.description = %{ XMLObject is a library for reading (not writing) XML.
@@ -13,6 +11,10 @@ Gem::Specification.new do |gem|
13
11
  documents of a known structure. While not devoid of caveats, it does
14
12
  have a very pleasant, idiomatic Ruby syntax. }.strip!.gsub! /\s+/, ' '
15
13
 
14
+ gem.has_rdoc = !!(gem.extra_rdoc_files = %w[ README.rdoc ])
15
+ gem.rdoc_options += %w[
16
+ --title XMLObject --main README.rdoc --inline-source ]
17
+
16
18
  gem.files = %w[
17
19
  MIT-LICENSE
18
20
  README.rdoc
@@ -26,16 +28,10 @@ Gem::Specification.new do |gem|
26
28
  lib/xml-object/adapters/libxml.rb
27
29
  lib/xml-object/adapters/rexml.rb
28
30
  lib/xml-object/adapters.rb
29
- lib/xml-object/array_notation.rb
30
31
  lib/xml-object/collection_proxy.rb
31
32
  lib/xml-object/element.rb
32
- lib/xml-object/method_missing_dispatchers.rb
33
+ lib/xml-object/properties.rb
33
34
  lib/xml-object.rb
34
35
  xml-object.gemspec
35
36
  ]
36
-
37
- gem.has_rdoc = !!(gem.extra_rdoc_files = %w[ README.rdoc ])
38
- gem.rdoc_options << '--title' << 'XMLObject' <<
39
- '--main' << 'README.rdoc' <<
40
- '--inline-source'
41
37
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xml-object
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.8
4
+ version: 0.9.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordi Bunster
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-10-23 00:00:00 -04:00
12
+ date: 2008-12-18 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -34,14 +34,13 @@ files:
34
34
  - lib/xml-object/adapters/libxml.rb
35
35
  - lib/xml-object/adapters/rexml.rb
36
36
  - lib/xml-object/adapters.rb
37
- - lib/xml-object/array_notation.rb
38
37
  - lib/xml-object/collection_proxy.rb
39
38
  - lib/xml-object/element.rb
40
- - lib/xml-object/method_missing_dispatchers.rb
39
+ - lib/xml-object/properties.rb
41
40
  - lib/xml-object.rb
42
41
  - xml-object.gemspec
43
42
  has_rdoc: true
44
- homepage: http://github.com/jordi/xml-object
43
+ homepage: http://xml-object.rubyforge.org
45
44
  post_install_message:
46
45
  rdoc_options:
47
46
  - --title
@@ -66,7 +65,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
65
  requirements: []
67
66
 
68
67
  rubyforge_project: xml-object
69
- rubygems_version: 1.3.0
68
+ rubygems_version: 1.3.1
70
69
  signing_key:
71
70
  specification_version: 2
72
71
  summary: The Rubyista's way to do quick XML sit-ups
@@ -1,52 +0,0 @@
1
- module XMLObject::MethodMissingDispatchers # :nodoc:
2
-
3
- private ##################################################################
4
-
5
- def __question_dispatch(meth, *args, &block)
6
- return nil unless meth.to_s.match(/\?$/) && args.empty? && block.nil?
7
-
8
- method_sans_question = meth.to_s.chomp('?').to_sym
9
-
10
- if boolish = __send__(method_sans_question)
11
- bool = case
12
- when %w[ true yes t y ].include?(boolish.downcase) then true
13
- when %w[ false no f n ].include?(boolish.downcase) then false
14
- else nil
15
- end
16
-
17
- unless bool.nil?
18
- instance_eval %{ def #{meth}; #{bool ? 'true' : 'false'}; end }
19
- end
20
-
21
- bool
22
- end
23
- end
24
-
25
- def __dot_notation_dispatch(meth, *args, &block)
26
- return nil unless args.empty? && block.nil?
27
-
28
- if @__children.has_key?(meth)
29
- instance_eval %{ def #{meth}; @__children[%s|#{meth}|]; end }
30
- @__children[meth]
31
-
32
- elsif @__attributes.has_key?(meth)
33
- instance_eval %{ def #{meth}; @__attributes[%s|#{meth}|]; end }
34
- @__attributes[meth]
35
-
36
- elsif @__children.has_key?(naive_sing = meth.to_s.chomp('s').to_sym) &&
37
- @__children[naive_sing].is_a?(Array)
38
-
39
- instance_eval %{ def #{meth}; @__children[%s|#{naive_sing}|]; end }
40
- @__children[naive_sing]
41
-
42
- elsif defined?(ActiveSupport::Inflector) &&
43
- @__children.has_key?(singular = meth.to_s.singularize.to_sym) &&
44
- @__children[singular].is_a?(Array)
45
-
46
- instance_eval %{ def #{meth}; @__children[%s|#{singular}|]; end }
47
- @__children[singular]
48
- else
49
- nil
50
- end
51
- end
52
- end