xml_hate 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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