roxml 2.5.3 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/.gitignore +7 -0
  2. data/.gitmodules +3 -0
  3. data/History.txt +38 -1
  4. data/README.rdoc +8 -5
  5. data/Rakefile +35 -36
  6. data/TODO +12 -35
  7. data/VERSION +1 -0
  8. data/examples/amazon.rb +8 -6
  9. data/examples/posts.rb +1 -1
  10. data/examples/{active_record.rb → rails.rb} +2 -2
  11. data/examples/twitter.rb +1 -1
  12. data/lib/roxml.rb +86 -151
  13. data/lib/roxml/definition.rb +64 -152
  14. data/lib/roxml/hash_definition.rb +5 -40
  15. data/lib/roxml/xml.rb +12 -9
  16. data/lib/roxml/xml/parsers/libxml.rb +22 -17
  17. data/lib/roxml/xml/parsers/nokogiri.rb +77 -0
  18. data/lib/roxml/xml/references.rb +66 -57
  19. data/roxml.gemspec +170 -19
  20. data/spec/definition_spec.rb +121 -198
  21. data/spec/examples/active_record_spec.rb +2 -2
  22. data/spec/examples/amazon_spec.rb +3 -2
  23. data/spec/examples/current_weather_spec.rb +2 -2
  24. data/spec/examples/dashed_elements_spec.rb +2 -2
  25. data/spec/examples/library_spec.rb +11 -6
  26. data/spec/examples/post_spec.rb +3 -3
  27. data/spec/examples/twitter_spec.rb +2 -2
  28. data/spec/roxml_spec.rb +15 -15
  29. data/spec/shared_specs.rb +1 -1
  30. data/spec/spec_helper.rb +8 -27
  31. data/spec/support/libxml.rb +3 -0
  32. data/spec/support/nokogiri.rb +3 -0
  33. data/spec/xml/attributes_spec.rb +36 -0
  34. data/spec/xml/namespace_spec.rb +240 -0
  35. data/spec/xml/namespaces_spec.rb +32 -0
  36. data/spec/xml/parser_spec.rb +9 -30
  37. data/tasks/rdoc.rake +13 -0
  38. data/tasks/rspec.rake +21 -17
  39. data/tasks/test.rake +13 -20
  40. data/test/mocks/dictionaries.rb +8 -7
  41. data/test/mocks/mocks.rb +20 -20
  42. data/test/support/fixtures.rb +11 -0
  43. data/test/test_helper.rb +3 -14
  44. data/test/unit/definition_test.rb +21 -95
  45. data/test/unit/deprecations_test.rb +1 -74
  46. data/test/unit/to_xml_test.rb +3 -3
  47. data/test/unit/xml_attribute_test.rb +1 -1
  48. data/test/unit/xml_block_test.rb +3 -3
  49. data/test/unit/xml_bool_test.rb +4 -4
  50. data/test/unit/xml_convention_test.rb +3 -3
  51. data/test/unit/xml_hash_test.rb +5 -14
  52. data/test/unit/xml_initialize_test.rb +2 -6
  53. data/test/unit/xml_name_test.rb +5 -24
  54. data/test/unit/xml_namespace_test.rb +1 -46
  55. data/test/unit/xml_object_test.rb +6 -6
  56. data/test/unit/xml_required_test.rb +3 -2
  57. data/test/unit/xml_text_test.rb +2 -2
  58. data/website/index.html +1 -1
  59. metadata +68 -51
  60. data/Manifest.txt +0 -106
  61. data/lib/roxml/extensions.rb +0 -6
  62. data/lib/roxml/extensions/array.rb +0 -13
  63. data/lib/roxml/extensions/array/conversions.rb +0 -35
  64. data/lib/roxml/extensions/deprecation.rb +0 -33
  65. data/lib/roxml/extensions/string.rb +0 -21
  66. data/lib/roxml/extensions/string/conversions.rb +0 -43
  67. data/lib/roxml/extensions/string/iterators.rb +0 -12
  68. data/lib/roxml/xml/parsers/rexml.rb +0 -84
  69. data/spec/string_spec.rb +0 -15
  70. data/test/bugs/rexml_bugs.rb +0 -15
  71. data/test/release/dependencies_test.rb +0 -32
  72. data/test/unit/xml_construct_test.rb +0 -77
  73. data/vendor/override_rake_task/README +0 -30
  74. data/vendor/override_rake_task/init.rb +0 -1
  75. data/vendor/override_rake_task/install.rb +0 -46
  76. data/vendor/override_rake_task/lib/override_rake_task.rb +0 -16
@@ -0,0 +1,32 @@
1
+ require 'spec/spec_helper.rb'
2
+
3
+ describe ROXML, "#xml_namespaces" do
4
+ class Tires
5
+ include ROXML
6
+
7
+ xml_namespaces \
8
+ :bobsbike => 'http://bobsbikes.example.com',
9
+ :alicesauto => 'http://alicesautosupply.example.com/'
10
+
11
+ xml_reader :bike_tires, :as => [], :from => '@name', :in => 'bobsbike:tire'
12
+ xml_reader :car_tires, :as => [], :from => '@name', :in => 'alicesauto:tire'
13
+ end
14
+
15
+ before do
16
+ @xml = %{<?xml version="1.0"?>
17
+ <inventory xmlns="http://alicesautosupply.example.com/" xmlns:bike="http://bobsbikes.example.com">
18
+ <tire name="super slick racing tire" />
19
+ <tire name="all weather tire" />
20
+ <bike:tire name="skinny street" />
21
+ </inventory>
22
+ }
23
+ end
24
+
25
+ it "should remap default namespaces" do
26
+ Tires.from_xml(@xml).car_tires.should =~ ['super slick racing tire', 'all weather tire']
27
+ end
28
+
29
+ it "should remap prefix namespaces" do
30
+ Tires.from_xml(@xml).bike_tires.should == ['skinny street']
31
+ end
32
+ end
@@ -1,47 +1,26 @@
1
- require File.dirname(__FILE__) + '/../spec_helper.rb'
1
+ require 'spec/spec_helper.rb'
2
2
 
3
3
  describe ROXML::XML::Parser do
4
4
  before do
5
5
  # quiet the error handler
6
- ROXML::XML::Error.reset_handler
6
+ ROXML::XML::Error.reset_handler if ROXML::XML::Error.respond_to?(:reset_handler)
7
7
  end
8
8
 
9
9
  it "should raise on malformed xml" do
10
- proc { Book.from_xml(fixture(:book_malformed)) }.should raise_error(ROXML::XML::Error)
10
+ unless ROXML::XML_PARSER == 'nokogiri' # nokogiri is less strict and auto-closes for some reason
11
+ proc { Book.from_xml(fixture(:book_malformed)) }.should raise_error(ROXML::XML::Error)
12
+ end
11
13
  end
12
14
 
13
15
  it "should escape invalid characters on output to text node" do
14
- node = ROXML::XML::Node.new("entities")
16
+ node = ROXML::XML::Node.create("entities")
15
17
  node.content = " < > ' \" & "
16
- if ROXML::XML_PARSER == 'libxml'
17
- node.to_s.should == "<entities> &lt; &gt; ' \" &amp; </entities>"
18
- else
19
- node.to_s.should == "<entities> &lt; &gt; &apos; &quot; &amp; </entities>"
20
- end
18
+ node.to_s.should == "<entities> &lt; &gt; ' \" &amp; </entities>"
21
19
  end
22
20
 
23
21
  it "should esape invalid characters for attribute name" do
24
- node = ROXML::XML::Node.new("attr_holder")
22
+ node = ROXML::XML::Node.create("attr_holder")
25
23
  node.attributes["entities"] = "\"'<>&"
26
- if ROXML::XML_PARSER == 'libxml'
27
- node.to_s.should == %{<attr_holder entities="&quot;'&lt;&gt;&amp;"/>}
28
- else
29
- node.to_s.should == %{<attr_holder entities='&quot;&apos;&lt;&gt;&amp;'/>}
30
- end
24
+ node.to_s.should == %{<attr_holder entities="&quot;'&lt;&gt;&amp;"/>}
31
25
  end
32
26
  end
33
-
34
- describe ROXML::XML::Document do
35
- describe "#save" do
36
- context "with rexml parser" do
37
- it "should defer to existing XMLDecl" do
38
- if ROXML::XML_PARSER == 'rexml'
39
- @doc = ROXML::XML::Document.new
40
- @doc << REXML::XMLDecl.new('1.1')
41
- @doc.save('spec/xml/decl_test.xml')
42
- ROXML::XML::Parser.parse(File.read('spec/xml/decl_test.xml')).to_s.should == ROXML::XML::Parser.parse(%{<?xml version="1.1"?>}).to_s
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -0,0 +1,13 @@
1
+ require 'rake/rdoctask'
2
+ Rake::RDocTask.new do |rdoc|
3
+ if File.exist?('VERSION')
4
+ version = File.read('VERSION')
5
+ else
6
+ version = ""
7
+ end
8
+
9
+ rdoc.rdoc_dir = 'rdoc'
10
+ rdoc.title = "roxml-new #{version}"
11
+ rdoc.rdoc_files.include('README*')
12
+ rdoc.rdoc_files.include('lib/**/*.rb')
13
+ end
@@ -1,21 +1,25 @@
1
- begin
2
- require 'spec'
3
- rescue LoadError
4
- require 'rubygems'
5
- require 'spec'
1
+ require 'spec/rake/spectask'
2
+ desc "Run specs"
3
+ Spec::Rake::SpecTask.new(:spec) do |spec|
4
+ spec.libs << 'lib' << 'spec' << 'examples'
5
+ spec.spec_opts = ['--options', "spec/spec.opts"]
6
+ spec.spec_files = FileList['spec/**/*_spec.rb']
6
7
  end
7
- begin
8
- require 'spec/rake/spectask'
9
- rescue LoadError
10
- puts <<-EOS
11
- To use rspec for testing you must install rspec gem:
12
- gem install rspec
13
- EOS
14
- exit(0)
8
+
9
+ namespace :spec do
10
+ [:libxml, :nokogiri].each do |parser|
11
+ desc "Spec ROXML under the #{parser} parser"
12
+ Spec::Rake::SpecTask.new(parser) do |spec|
13
+ spec.libs << 'lib' << 'spec' << 'examples'
14
+ spec.spec_opts = ['--options=spec/spec.opts']
15
+ spec.spec_files = ["spec/support/#{parser}.rb"] + FileList['spec/**/*_spec.rb']
16
+ end
17
+ end
15
18
  end
16
19
 
17
- desc "Run the specs under spec/models"
18
- Spec::Rake::SpecTask.new do |t|
19
- t.spec_opts = ['--options', "spec/spec.opts"]
20
- t.spec_files = FileList['spec/**/*_spec.rb']
20
+ desc "Run specs with rcov"
21
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
22
+ spec.libs << 'lib' << 'spec'
23
+ spec.pattern = 'spec/**/*_spec.rb'
24
+ spec.rcov = true
21
25
  end
@@ -1,42 +1,35 @@
1
- # We need to override hoe's test task in order to support separate REXML & LibXML testing
2
- require File.join(File.dirname(__FILE__), '../vendor/override_rake_task/lib/override_rake_task')
3
-
4
- Rake::TestTask.new(:bugs) do |t|
5
- t.libs << 'test'
6
- t.test_files = FileList['test/bugs/*_bugs.rb']
7
- t.verbose = true
1
+ require 'rake/testtask'
2
+ Rake::TestTask.new(:bugs) do |test|
3
+ test.libs << 'lib' << 'test'
4
+ test.pattern = 'test/bugs/*_bugs.rb'
5
+ test.verbose = true
8
6
  end
9
7
 
10
- remove_task :test
11
8
  desc "Test ROXML using the default parser selection behavior"
12
9
  task :test do
13
- module ROXML
14
- SILENCE_XML_NAME_WARNING = true
15
- end
16
- require 'lib/roxml'
17
10
  require 'rake/runtest'
18
- Rake.run_tests $hoe.test_globs
11
+ Rake.run_tests 'test/unit/*_test.rb'
19
12
  end
20
13
 
21
14
  namespace :test do
22
- desc "Test ROXML under the LibXML parser"
23
- task :libxml do
15
+ desc "Test ROXML under the Nokogiri parser"
16
+ task :nokogiri do
24
17
  module ROXML
25
- XML_PARSER = 'libxml'
18
+ XML_PARSER = 'nokogiri'
26
19
  end
27
20
  Rake::Task["test"].invoke
28
21
  end
29
22
 
30
- desc "Test ROXML under the REXML parser"
31
- task :rexml do
23
+ desc "Test ROXML under the LibXML parser"
24
+ task :libxml do
32
25
  module ROXML
33
- XML_PARSER = 'rexml'
26
+ XML_PARSER = 'libxml'
34
27
  end
35
28
  Rake::Task["test"].invoke
36
29
  end
37
30
 
38
31
  desc "Runs tests under RCOV"
39
32
  task :rcov do
40
- system "rcov -T --no-html -x '^/' #{FileList[$hoe.test_globs]}"
33
+ system "rcov -T --no-html -x '^/' #{FileList['test/unit/*_test.rb']}"
41
34
  end
42
35
  end
@@ -4,14 +4,15 @@ class DictionaryOfAttrs
4
4
  include ROXML
5
5
 
6
6
  xml_name :dictionary
7
- xml_reader :definitions, {:attrs => [:dt, :dd]}, :in => :definitions
7
+ xml_reader :definitions, :as => {:key => '@dt',
8
+ :value => '@dd'}, :in => :definitions
8
9
  end
9
10
 
10
11
  class DictionaryOfTexts
11
12
  include ROXML
12
13
 
13
14
  xml_name :dictionary
14
- xml_reader :definitions, {:key => :word,
15
+ xml_reader :definitions, :as => {:key => :word,
15
16
  :value => :meaning}
16
17
  end
17
18
 
@@ -19,7 +20,7 @@ class DictionaryOfMixeds
19
20
  include ROXML
20
21
 
21
22
  xml_name :dictionary
22
- xml_reader :definitions, {:key => {:attr => :word},
23
+ xml_reader :definitions, :as => {:key => '@word',
23
24
  :value => :content}
24
25
  end
25
26
 
@@ -27,7 +28,7 @@ class DictionaryOfNames
27
28
  include ROXML
28
29
 
29
30
  xml_name :dictionary
30
- xml_reader :definitions, {:key => :name,
31
+ xml_reader :definitions, :as => {:key => :name,
31
32
  :value => :content}
32
33
  end
33
34
 
@@ -35,7 +36,7 @@ class DictionaryOfGuardedNames
35
36
  include ROXML
36
37
 
37
38
  xml_name :dictionary
38
- xml_reader :definitions, {:key => :name,
39
+ xml_reader :definitions, :as => {:key => :name,
39
40
  :value => :content}, :in => :definitions
40
41
  end
41
42
 
@@ -43,7 +44,7 @@ class DictionaryOfNameClashes
43
44
  include ROXML
44
45
 
45
46
  xml_name :dictionary
46
- xml_reader :definitions, {:key => 'name',
47
+ xml_reader :definitions, :as => {:key => 'name',
47
48
  :value => 'content'}, :from => :definition
48
49
  end
49
50
 
@@ -51,6 +52,6 @@ class DictionaryOfAttrNameClashes
51
52
  include ROXML
52
53
 
53
54
  xml_name :dictionary
54
- xml_reader :definitions, {:key => {:attr => :name},
55
+ xml_reader :definitions, :as => {:key => '@name',
55
56
  :value => 'content'}, :from => :definition
56
57
  end
@@ -15,7 +15,7 @@ end
15
15
  class Numerology
16
16
  include ROXML
17
17
 
18
- xml_reader :predictions, {:attrs => ['number', 'meaning']} do |k, v|
18
+ xml_reader :predictions, :as => {:key => '@number', :value => '@meaning'} do |k, v|
19
19
  [Integer(k), v]
20
20
  end
21
21
  end
@@ -41,7 +41,7 @@ class Book
41
41
  xml_reader :title
42
42
  xml_reader :description, :cdata => true
43
43
  xml_reader :author
44
- xml_accessor :pages, :text => 'pagecount', :as => Integer
44
+ xml_accessor :pages, :from => 'pagecount', :as => Integer
45
45
  end
46
46
 
47
47
  class BookWithRequired
@@ -49,8 +49,8 @@ class BookWithRequired
49
49
 
50
50
  xml_accessor :isbn, :from => '@ISBN', :required => true
51
51
  xml_reader :title, :required => true
52
- xml_reader :contributors, [Contributor], :in => 'contributor_array', :required => true
53
- xml_reader :contributor_hash, {:attrs => ['role', 'name']},
52
+ xml_reader :contributors, :as => [Contributor], :in => 'contributor_array', :required => true
53
+ xml_reader :contributor_hash, :as => {:key => '@role', :value => '@name'},
54
54
  :from => 'contributor', :in => 'contributor_hash', :required => true
55
55
  end
56
56
 
@@ -107,7 +107,7 @@ class BookWithDepth
107
107
  xml_reader :title
108
108
  xml_reader :description, :cdata => true
109
109
  xml_reader :author
110
- xml_reader :depth, Measurement
110
+ xml_reader :depth, :as => Measurement
111
111
  end
112
112
 
113
113
  class Author
@@ -124,7 +124,7 @@ class BookWithAuthors
124
124
  xml_reader :isbn, :from => '@ISBN'
125
125
  xml_reader :title
126
126
  xml_reader :description, :cdata => true
127
- xml_reader :authors, []
127
+ xml_reader :authors, :as => []
128
128
  end
129
129
 
130
130
  class BookWithAuthorTextAttribute
@@ -134,7 +134,7 @@ class BookWithAuthorTextAttribute
134
134
  xml_reader :isbn, :from => '@ISBN'
135
135
  xml_reader :title
136
136
  xml_reader :description, :cdata => true
137
- xml_reader :author, Author
137
+ xml_reader :author, :as => Author
138
138
  end
139
139
 
140
140
  class BookWithContributions
@@ -144,7 +144,7 @@ class BookWithContributions
144
144
  xml_reader :isbn, :from => :attr
145
145
  xml_reader :title
146
146
  xml_reader :description
147
- xml_reader :contributions, [Contributor], :from => 'contributor', :in => "contributions"
147
+ xml_reader :contributions, :as => [Contributor], :from => 'contributor', :in => "contributions"
148
148
  end
149
149
 
150
150
  class BookWithContributors
@@ -154,7 +154,7 @@ class BookWithContributors
154
154
  xml_reader :isbn, :from => :attr
155
155
  xml_reader :title
156
156
  xml_reader :description
157
- xml_reader :contributors, [Contributor]
157
+ xml_reader :contributors, :as => [Contributor]
158
158
  end
159
159
 
160
160
  class WriteableBookWithContributors
@@ -164,7 +164,7 @@ class WriteableBookWithContributors
164
164
  xml_accessor :isbn, :from => :attr
165
165
  xml_accessor :title
166
166
  xml_accessor :description
167
- xml_accessor :contributors, [Contributor]
167
+ xml_accessor :contributors, :as => [Contributor]
168
168
  end
169
169
 
170
170
  class NamelessBook
@@ -173,7 +173,7 @@ class NamelessBook
173
173
  xml_reader :isbn, :from => :attr
174
174
  xml_reader :title
175
175
  xml_reader :description
176
- xml_reader :contributors, [Contributor]
176
+ xml_reader :contributors, :as => [Contributor]
177
177
  end
178
178
 
179
179
  class Publisher
@@ -189,7 +189,7 @@ class BookWithPublisher
189
189
  xml_reader :isbn, :from => :attr
190
190
  xml_reader :title
191
191
  xml_reader :description
192
- xml_reader :publisher, Publisher
192
+ xml_reader :publisher, :as => Publisher
193
193
  end
194
194
 
195
195
  class BookPair
@@ -199,14 +199,14 @@ class BookPair
199
199
  xml_reader :title
200
200
  xml_reader :description
201
201
  xml_reader :author
202
- xml_reader :book, Book
202
+ xml_reader :book, :as => Book
203
203
  end
204
204
 
205
205
  class Library
206
206
  include ROXML
207
207
 
208
208
  xml_reader :name
209
- xml_reader :books, [BookWithContributions]
209
+ xml_reader :books, :as => [BookWithContributions]
210
210
  end
211
211
 
212
212
  class UppercaseLibrary
@@ -214,14 +214,14 @@ class UppercaseLibrary
214
214
 
215
215
  xml_name :library
216
216
  xml_reader :name, :from => 'NAME'
217
- xml_reader :books, [BookWithContributions], :from => 'BOOK'
217
+ xml_reader :books, :as => [BookWithContributions], :from => 'BOOK'
218
218
  end
219
219
 
220
220
  class LibraryWithBooksOfUnderivableName
221
221
  include ROXML
222
222
 
223
223
  xml_accessor :name
224
- xml_reader :novels, [NamelessBook]
224
+ xml_reader :novels, :as => [NamelessBook]
225
225
  end
226
226
 
227
227
  class NodeWithNameConflicts
@@ -247,7 +247,7 @@ class Person
247
247
  xml_accessor :name, :from => :content, :else => 'Unknown'
248
248
 
249
249
  def self.blank
250
- returning new do |instance|
250
+ new.tap do |instance|
251
251
  instance.age = 21
252
252
  instance.name = 'Unknown'
253
253
  end
@@ -259,7 +259,7 @@ class PersonWithMother
259
259
 
260
260
  xml_name :person
261
261
  xml_reader :name
262
- xml_reader :mother, PersonWithMother, :from => 'mother'
262
+ xml_reader :mother, :as => PersonWithMother, :from => 'mother'
263
263
  end
264
264
 
265
265
  class PersonWithGuardedMother
@@ -267,7 +267,7 @@ class PersonWithGuardedMother
267
267
 
268
268
  xml_name :person
269
269
  xml_reader :name
270
- xml_reader :mother, PersonWithGuardedMother, :from => :person, :in => :mother
270
+ xml_reader :mother, :as => PersonWithGuardedMother, :from => :person, :in => :mother
271
271
  end
272
272
 
273
273
  class PersonWithMotherOrMissing
@@ -275,5 +275,5 @@ class PersonWithMotherOrMissing
275
275
 
276
276
  xml_reader :age, :from => :attr, :else => 21
277
277
  xml_reader :name, :else => 'Anonymous'
278
- xml_reader :mother, PersonWithMotherOrMissing, :else => Person.blank
278
+ xml_reader :mother,:as => PersonWithMotherOrMissing, :else => Person.blank
279
279
  end
@@ -0,0 +1,11 @@
1
+ def fixture(name)
2
+ File.read(fixture_path(name))
3
+ end
4
+
5
+ def xml_fixture(name)
6
+ ROXML::XML::Parser.parse_file(fixture_path(name)).root
7
+ end
8
+
9
+ def fixture_path(name)
10
+ "test/fixtures/#{name}.xml"
11
+ end
@@ -1,22 +1,11 @@
1
- require "lib/roxml"
1
+ require 'rubygems'
2
2
  require 'active_support/test_case'
3
3
  require 'test/mocks/mocks'
4
4
  require 'test/mocks/dictionaries'
5
-
6
- def fixture(name)
7
- File.read(fixture_path(name))
8
- end
9
-
10
- def xml_fixture(name)
11
- ROXML::XML::Parser.parse_file(fixture_path(name)).root
12
- end
13
-
14
- def fixture_path(name)
15
- "test/fixtures/#{name}.xml"
16
- end
5
+ require 'test/support/fixtures'
17
6
 
18
7
  def to_xml_test(*names)
19
- names = names.first if names.one? && names.first.is_a?(Hash)
8
+ names = names.first if names.size == 1 && names.first.is_a?(Hash)
20
9
  names.each do |name, xml_name|
21
10
  xml_name ||= name
22
11