xml_hate 0.8.0

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/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
6
+ .idea
data/.rvmrc ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
7
+ environment_id="ruby-1.8.7-p352@xml_hate"
8
+
9
+ #
10
+ # Uncomment following line if you want options to be set only for given project.
11
+ #
12
+ # PROJECT_JRUBY_OPTS=( --1.9 )
13
+
14
+ #
15
+ # First we attempt to load the desired environment directly from the environment
16
+ # file. This is very fast and efficient compared to running through the entire
17
+ # CLI and selector. If you want feedback on which environment was used then
18
+ # insert the word 'use' after --create as this triggers verbose mode.
19
+ #
20
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
21
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
22
+ then
23
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
24
+
25
+ if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
26
+ then
27
+ . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
28
+ fi
29
+ else
30
+ # If the environment file has not yet been created, use the RVM CLI to select.
31
+ if ! rvm --create "$environment_id"
32
+ then
33
+ echo "Failed to create RVM environment '${environment_id}'."
34
+ return 1
35
+ fi
36
+ fi
37
+
38
+ #
39
+ # If you use an RVM gemset file to install a list of gems (*.gems), you can have
40
+ # it be automatically loaded. Uncomment the following and adjust the filename if
41
+ # necessary.
42
+ #
43
+ # filename=".gems"
44
+ # if [[ -s "$filename" ]]
45
+ # then
46
+ # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
47
+ # fi
48
+
49
+ # If you use bundler, this might be useful to you:
50
+ # if command -v bundle && [[ -s Gemfile ]]
51
+ # then
52
+ # bundle install
53
+ # fi
54
+
55
+
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in xml_hate.gemspec
4
+ gemspec
5
+
6
+ gem 'xml-simple'
7
+ gem 'hashie'
8
+ gem 'activesupport'
9
+
10
+ gem 'minitest'
11
+ group :development do
12
+ gem 'guard'
13
+ gem 'guard-minitest', :git => 'git://github.com/aspiers/guard-minitest.git'
14
+ gem 'ruby_gntp'
15
+ end
data/Guardfile ADDED
@@ -0,0 +1,12 @@
1
+ guard 'minitest' do
2
+ watch(%r|^test/test_(.*)\.rb|)
3
+ watch(%r|^lib/(.*)([^/]+)\.rb|) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
4
+ watch(%r|^test/test_helper\.rb|) { "test" }
5
+ watch(%r|^lib/(.*)\.rb|) { |m| "test/test_#{m[1]}.rb" }
6
+
7
+ watch(%r{^spec/.+_spec\.rb$})
8
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
9
+ watch(%r{^lib/xml_hate/(.+)\.rb$}) { |m| "spec/xml_hate/#{m[1]}_spec.rb" }
10
+ watch(%r{^spec/models/.+\.rb$}) { ["spec/models", "spec/acceptance"] }
11
+ watch('spec/spec_helper.rb') { "spec" }
12
+ end
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,83 @@
1
+ require 'hashie'
2
+ require 'active_support/inflector'
3
+
4
+ module XmlHate
5
+ class Document
6
+ def initialize(xml)
7
+ @document = XmlSimple.xml_in(xml)
8
+ end
9
+
10
+ def method_missing(meth, *args, &blk)
11
+ return "" if @document.has_key?(meth.to_s) == false
12
+ objects = pull_the_objects_from_the_xml_document(meth)
13
+ objects.count == 1 ? objects[0] : objects
14
+ end
15
+
16
+ private
17
+
18
+ def pull_the_objects_from_the_xml_document(meth)
19
+ nodes = read_the_matching_nodes_from_the_xml_document(meth)
20
+ convert_the_hashes_to_objects(nodes)
21
+ end
22
+
23
+ def read_the_matching_nodes_from_the_xml_document(meth)
24
+ @document[meth.to_s].map { |n| process_this_top_level_node(n) }
25
+ end
26
+
27
+ def convert_the_hashes_to_objects(objects)
28
+ objects.map do |v|
29
+ v.class == Hashie::Mash ? Node.new(v) : v
30
+ end
31
+ end
32
+
33
+ def process_this_top_level_node(node)
34
+ return node if node.class == String
35
+ new_object = Hashie::Mash.new(node)
36
+ process_this_inner_node(new_object)
37
+ end
38
+
39
+ def process_this_inner_node(node)
40
+ # get the values to pluralize before modifying the node
41
+ values_to_pluralize = get_values_to_pluralize(node)
42
+
43
+ # this may modify the values checked to be pluralized
44
+ bring_up_single_elements_as_properties(node)
45
+
46
+ # now "pluralize" by setting the pluralized key
47
+ values_to_pluralize.each { |key, value| node[key] = value }
48
+
49
+ node
50
+ end
51
+
52
+ def bring_up_single_elements_as_properties(node)
53
+ get_properties_with_multiple_elements(node).each do |key, value|
54
+ value.each { |v| process_this_inner_node(v) }
55
+ node[key] = value[0] if get_the_number_of_elements(value) == 1
56
+ end
57
+ end
58
+
59
+ def get_values_to_pluralize(node)
60
+ values_to_pluralize = {}
61
+ get_properties_with_multiple_elements(node).each do |key, value|
62
+ values_to_pluralize[key.pluralize] = value if key.pluralize != key
63
+ end
64
+ values_to_pluralize
65
+ end
66
+
67
+ def get_properties_with_multiple_elements(node)
68
+ begin
69
+ node.select{|k,v| get_the_number_of_elements(v) >= 1}
70
+ rescue
71
+ []
72
+ end
73
+ end
74
+
75
+ def get_the_number_of_elements(value)
76
+ begin
77
+ value.count
78
+ rescue
79
+ 0
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,31 @@
1
+ module XmlHate
2
+ class Node
3
+ def initialize(hash)
4
+ hash.each { |k,v| create_accessor_for k, convert_the_value_to_the_appropriate_form(v) }
5
+ end
6
+
7
+ def method_missing(meth, *args, &blk)
8
+ an_empty_array_for_plurals_or_empty_string_for_singulars meth
9
+ end
10
+
11
+ private
12
+
13
+ def an_empty_array_for_plurals_or_empty_string_for_singulars(meth)
14
+ meth.to_s == meth.to_s.pluralize ? [] : ""
15
+ end
16
+
17
+ def create_accessor_for(k, v)
18
+ self.instance_variable_set("@#{k}", v)
19
+ self.instance_eval("
20
+ class << self
21
+ attr_accessor :#{k.to_sym}
22
+ end")
23
+ end
24
+
25
+ def convert_the_value_to_the_appropriate_form(value)
26
+ return Node.new(value) if value.class == Hashie::Mash
27
+ return value.map {|i| i.class == Hashie::Mash ? Node.new(i) : i} if value.class == Array
28
+ value
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module XmlHate
2
+ VERSION = "0.8.0"
3
+ end
data/lib/xml_hate.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "xml_hate/version"
2
+ require "xml_hate/node"
3
+ require "xml_hate/document"
4
+ require "xmlsimple"
5
+
6
+ module XmlHate
7
+ end
data/readme.md ADDED
@@ -0,0 +1,55 @@
1
+ # XML Hate
2
+
3
+ ## Reading XML with my own ten-foot poll.
4
+
5
+ xml_hate is a small gem that describes my feelings for XML imports. I've written a billion of them, yet each time I start another I feel like I'm writing Assembler. Shouldn't it be easier? Shouldn't the code look nicer? Shouldn't this be more fun?
6
+
7
+ I've also noticed a number of things that I always tend to do. I always convert the XML to objects, I parse through the hierarchy to find child objects, I put in defensive checks for data that might-or-might-not exist, etc.
8
+
9
+ This gem is where I'm going to put these conventions and processes of mine. My goal is to take a XML document and immediately get it in the form that I need to use it.
10
+
11
+ ### Example
12
+
13
+ ``` xml
14
+ <root>
15
+ <directory>
16
+ <employee lastname="Galt">
17
+ <address>123 W St</address>
18
+ <address>456 S Blvd</address>
19
+ <firstname>John</firstname>
20
+ </employee>
21
+ <employee lastname="Roark" firstname="Howard">
22
+ <address>789 S</address>
23
+ </employee>
24
+ <employee lastname="Rearden" />
25
+ </directory>
26
+ </root>
27
+ ```
28
+
29
+ ```ruby
30
+ document = XmlHate::Document.new(xml)
31
+
32
+ document.directory.employees.count # 3, note pluralization happened automatically
33
+
34
+ john_galt = document.directory.employees[0]
35
+
36
+ # note how I treat the single-value element and attribute the same
37
+ john_galt.lastname # Galt
38
+ john_galt.firstname # John
39
+
40
+ john_galt.addresses.count # 2, notice pluralization again
41
+
42
+ howard_roark = document.directory.employees[1]
43
+
44
+ howard_roark.firstname # Howard
45
+ howard_roark.lastname # Roark
46
+ howard_roark.addresses.count # 1
47
+ howard_roark.address # 789 S
48
+
49
+ rearden = document.directory.employees[2]
50
+ rearden.lastname # Rearden
51
+ rearden.firstname # "", defaults to empty string if the value cannot be found
52
+ rearden.whatever_i_want # "", see above
53
+ rearden.addresses.count # 0, returns [] by assuming you want the plural version
54
+
55
+ ```
@@ -0,0 +1,3 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+ require './lib/xml_hate.rb'
@@ -0,0 +1,236 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe XmlHate::Document do
4
+
5
+ describe "with a simple car xml block" do
6
+ before do
7
+ xml = <<DOC
8
+ <root>
9
+ <car>a car</car>
10
+ </root>
11
+ DOC
12
+ @document = XmlHate::Document.new(xml)
13
+ end
14
+
15
+ it "should return an object for car" do
16
+ @document.car.wont_be_nil
17
+ end
18
+
19
+ it "should return empty string for anything else" do
20
+ @document.blah.must_equal ""
21
+ @document.something.must_equal ""
22
+ @document.else.must_equal ""
23
+ end
24
+ end
25
+
26
+ describe "with a simple truck xml block" do
27
+ before do
28
+ xml = <<DOC
29
+ <root>
30
+ <truck>a truck</truck>
31
+ </root>
32
+ DOC
33
+ @document = XmlHate::Document.new(xml)
34
+ end
35
+
36
+ it "should return an object for car" do
37
+ @document.truck.wont_be_nil
38
+ end
39
+
40
+ it "should return empty string for anything else" do
41
+ @document.car.must_equal ""
42
+ @document.blah.must_equal ""
43
+ @document.something.must_equal ""
44
+ @document.else.must_equal ""
45
+ end
46
+ end
47
+
48
+ describe "with a more complex boat xml block" do
49
+ before do
50
+ xml = <<DOC
51
+ <root>
52
+ <boat name="Bulstrode" type="Cargo">
53
+ <attitude>grumpy</attitude>
54
+ <location>The ocean</location>
55
+ <episode>ep 10</episode>
56
+ <episode>ep 11</episode>
57
+ <narrator firstname="George" lastname="Carlin" />
58
+ </boat>
59
+ </root>
60
+ DOC
61
+ @document = XmlHate::Document.new(xml)
62
+ end
63
+
64
+ it "should return a node object for boat" do
65
+ @document.boat.class.must_equal XmlHate::Node
66
+ end
67
+
68
+ it "should return Bulstrode as the name" do
69
+ @document.boat.name.must_equal "Bulstrode"
70
+ end
71
+
72
+ it "should return Cargo as the type" do
73
+ @document.boat.type.must_equal "Cargo"
74
+ end
75
+
76
+ it "should return attitude as grumpy" do
77
+ @document.boat.attitude.must_equal "grumpy"
78
+ end
79
+
80
+ it "should return location as the ocean" do
81
+ @document.boat.locations.count.must_equal 1
82
+ end
83
+
84
+ it "should return locations" do
85
+ @document.boat.location.must_equal "The ocean"
86
+ end
87
+
88
+ it "should return both episodes" do
89
+ @document.boat.episode.count.must_equal 2
90
+ @document.boat.episode[0].must_equal "ep 10"
91
+ @document.boat.episode[1].must_equal "ep 11"
92
+ end
93
+
94
+ it "should return all information about the narrator" do
95
+ @document.boat.narrator.firstname.must_equal "George"
96
+ @document.boat.narrator.lastname.must_equal "Carlin"
97
+ end
98
+
99
+ it "should set the narrator to an empty object" do
100
+ @document.boat.narrator.class.must_equal XmlHate::Node
101
+ end
102
+
103
+ end
104
+
105
+ describe "with an even more complex movie xml block" do
106
+ before do
107
+ xml = <<DOC
108
+ <root>
109
+ <movie name="Deep Impact">
110
+ <actor name="Morgan Freeman" gender="Male" />
111
+ <actor name="Tea Leoni" gender="Female" />
112
+ <actor name="Elijah Wood" gender="Male">
113
+ <movie name="Lord of the Rings 1" />
114
+ <movie name="Lord of the Rings 2">
115
+ <actor name="Sean Astin" />
116
+ <year>2004</year>
117
+ </movie>
118
+ </actor>
119
+ </movie>
120
+ </root>
121
+ DOC
122
+ @document = XmlHate::Document.new(xml)
123
+ end
124
+
125
+ it "should have a movie element" do
126
+ @document.movie.nil?.must_equal false
127
+ end
128
+
129
+ it "should have three actors" do
130
+ @document.movie.actor.count.must_equal 3
131
+ end
132
+
133
+ it "should be able to pull acotrs out with plural property" do
134
+ @document.movie.actors.count.must_equal 3
135
+ end
136
+
137
+ it "should have two other movies on the third actor" do
138
+ @document.movie.actor[2].movie.count.must_equal 2
139
+ end
140
+
141
+ it "should be able to pull the actor deep down the chain" do
142
+ @document.movie.actor[2].movie[1].actor.name.must_equal "Sean Astin"
143
+ end
144
+
145
+ it "should be able to pull the year deep down the chain" do
146
+ @document.movie.actor[2].movie[1].year.must_equal "2004"
147
+ end
148
+
149
+ it "should maintain years as an array deep down the list" do
150
+ @document.movie.actor[2].movie[1].years.count.must_equal 1
151
+ @document.movie.actor[2].movie[1].years[0].must_equal "2004"
152
+ end
153
+ end
154
+
155
+
156
+ describe "another xml example" do
157
+ before do
158
+ xml = <<DOC
159
+ <root>
160
+ <product_group>
161
+ <name>A product group</name>
162
+ <listofgroup></listofgroup>
163
+ <listofgroup>
164
+ <product_group id="100"></product_group>
165
+ <product_group id="3">
166
+ <name>Another product group</name>
167
+ </product_group>
168
+ </listofgroup>
169
+ </product_group>
170
+ </root>
171
+ DOC
172
+ @document = XmlHate::Document.new(xml)
173
+ end
174
+
175
+ it "should have data" do
176
+ @document.product_group.listofgroups[1].product_groups[1].name.must_equal "Another product group"
177
+ end
178
+ end
179
+
180
+ describe "another xml example with plurals after the root" do
181
+ before do
182
+ xml = <<DOC
183
+ <root>
184
+ <product_group />
185
+ <product_group>
186
+ <name>A product group</name>
187
+ <listofgroup></listofgroup>
188
+ <listofgroup>
189
+ <product_group id="100"></product_group>
190
+ <product_group id="3">
191
+ <name>Another product group</name>
192
+ </product_group>
193
+ </listofgroup>
194
+ </product_group>
195
+ </root>
196
+ DOC
197
+ @document = XmlHate::Document.new(xml)
198
+ end
199
+
200
+ it "should have data" do
201
+ @document.product_group[1].listofgroups[1].product_groups[1].name.must_equal "Another product group"
202
+ end
203
+ end
204
+
205
+ describe "an example from the readme file" do
206
+ before do
207
+ xml = <<DOC
208
+ <root>
209
+ <directory>
210
+ <employee lastname="Galt">
211
+ <address>123 W St</address>
212
+ <address>456 S Blvd</address>
213
+ <firstname>John</firstname>
214
+ </employee>
215
+ <employee lastname="Roark" firstname="Howard">
216
+ <address>789 S</address>
217
+ </employee>
218
+ <employee lastname="Rearden" />
219
+ </directory>
220
+ </root>
221
+ DOC
222
+ @document = XmlHate::Document.new xml
223
+ end
224
+
225
+ it "should return directory as a Node" do
226
+ @document.directory.class.must_equal XmlHate::Node
227
+ end
228
+
229
+ it "should return the employees as Nodes" do
230
+ @document.directory.employees.each do |e|
231
+ e.class.must_equal XmlHate::Node
232
+ end
233
+ end
234
+
235
+ end
236
+ end
@@ -0,0 +1,80 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe XmlHate::Node do
4
+ describe "creating a node with a simple node" do
5
+ before do
6
+ @object = XmlHate::Node.new({:firstname => "John", :lastname => "Carter" })
7
+ end
8
+
9
+ it "should respond to first name" do
10
+ @object.respond_to?(:firstname).must_equal true
11
+ end
12
+
13
+ it "should respond to last name" do
14
+ @object.respond_to?(:lastname).must_equal true
15
+ end
16
+
17
+ it "should not respond to other things" do
18
+ @object.respond_to?(:something).must_equal false
19
+ @object.respond_to?(:else).must_equal false
20
+ end
21
+
22
+ it "should return the first name" do
23
+ @object.firstname.must_equal "John"
24
+ end
25
+
26
+ it "should return the last name" do
27
+ @object.lastname.must_equal "Carter"
28
+ end
29
+
30
+ it "should return an empty string for a singular name" do
31
+ @object.cat.must_equal ""
32
+ @object.dog.must_equal ""
33
+ end
34
+
35
+ it "should return an empty array for plural names" do
36
+ @object.cats.must_equal []
37
+ @object.dogs.must_equal []
38
+ end
39
+ end
40
+
41
+ describe "creating a node with a child Hashie::Match" do
42
+ before do
43
+ @object = XmlHate::Node.new({:thing => Hashie::Mash.new({:firstname => "John", :lastname => "Carter" })})
44
+ end
45
+
46
+ it "should return a node object for thing" do
47
+ @object.thing.class.must_equal XmlHate::Node
48
+ end
49
+
50
+ end
51
+
52
+ describe "creating a node with an Array" do
53
+ before do
54
+ @object = XmlHate::Node.new({:thing => [Hashie::Mash.new(), "test"]})
55
+ end
56
+
57
+ it "should return a node object for the first item" do
58
+ @object.thing[0].class.must_equal XmlHate::Node
59
+ end
60
+
61
+ it "should return a string for the second item" do
62
+ @object.thing[1].class.must_equal String
63
+ end
64
+ end
65
+
66
+ describe "creating a node will create attributes for single instances of node" do
67
+ before do
68
+ @object1 = XmlHate::Node.new({:first_name => "Tyrone", :last_name => "Groves"})
69
+ @object2 = XmlHate::Node.new({:customer_id => 23})
70
+ end
71
+
72
+ it "should not respond to first name" do
73
+ @object2.respond_to?(:first_name).must_equal false
74
+ end
75
+
76
+ it "should not respond to last name" do
77
+ @object2.respond_to?(:last_name).must_equal false
78
+ end
79
+ end
80
+ end
data/xml_hate.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "xml_hate/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "xml_hate"
7
+ s.version = XmlHate::VERSION
8
+ s.authors = ["Darren Cauthon"]
9
+ s.email = ["darren@cauthon.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Handling xml with my own ten-foot poll.}
12
+ s.description = %q{I hate xml.}
13
+
14
+ s.rubyforge_project = "xml_hate"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_runtime_dependency 'xml-simple'
23
+ s.add_runtime_dependency 'hashie'
24
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xml_hate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Darren Cauthon
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: xml-simple
16
+ requirement: &70214612517320 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70214612517320
25
+ - !ruby/object:Gem::Dependency
26
+ name: hashie
27
+ requirement: &70214612533220 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70214612533220
36
+ description: I hate xml.
37
+ email:
38
+ - darren@cauthon.com
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - .gitignore
44
+ - .rvmrc
45
+ - Gemfile
46
+ - Guardfile
47
+ - Rakefile
48
+ - lib/xml_hate.rb
49
+ - lib/xml_hate/document.rb
50
+ - lib/xml_hate/node.rb
51
+ - lib/xml_hate/version.rb
52
+ - readme.md
53
+ - spec/spec_helper.rb
54
+ - spec/xml_hate/document_spec.rb
55
+ - spec/xml_hate/node_spec.rb
56
+ - xml_hate.gemspec
57
+ homepage: ''
58
+ licenses: []
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project: xml_hate
77
+ rubygems_version: 1.8.10
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: Handling xml with my own ten-foot poll.
81
+ test_files:
82
+ - spec/spec_helper.rb
83
+ - spec/xml_hate/document_spec.rb
84
+ - spec/xml_hate/node_spec.rb