roxml 2.4.1 → 2.4.2

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.
Files changed (43) hide show
  1. data/History.txt +21 -0
  2. data/MIT-LICENSE +1 -1
  3. data/Manifest.txt +27 -6
  4. data/Rakefile +2 -2
  5. data/TODO +35 -14
  6. data/config/website.yml +2 -0
  7. data/examples/amazon.rb +33 -0
  8. data/examples/current_weather.rb +27 -0
  9. data/examples/dashed_elements.rb +20 -0
  10. data/examples/posts.rb +27 -0
  11. data/examples/twitter.rb +37 -0
  12. data/examples/xml/amazon.xml +133 -0
  13. data/examples/xml/current_weather.xml +89 -0
  14. data/examples/xml/dashed_elements.xml +52 -0
  15. data/examples/xml/posts.xml +23 -0
  16. data/examples/xml/twitter.xml +422 -0
  17. data/lib/roxml.rb +35 -6
  18. data/lib/roxml/{options.rb → definition.rb} +60 -88
  19. data/lib/roxml/extensions.rb +3 -0
  20. data/lib/roxml/hash_definition.rb +59 -0
  21. data/lib/roxml/xml.rb +15 -272
  22. data/lib/roxml/xml/{libxml.rb → parsers/libxml.rb} +13 -5
  23. data/lib/roxml/xml/{rexml.rb → parsers/rexml.rb} +13 -4
  24. data/lib/roxml/xml/references.rb +290 -0
  25. data/roxml.gemspec +4 -4
  26. data/spec/examples/amazon_spec.rb +53 -0
  27. data/spec/examples/current_weather_spec.rb +37 -0
  28. data/spec/examples/dashed_elements_spec.rb +20 -0
  29. data/spec/examples/post_spec.rb +24 -0
  30. data/spec/examples/twitter_spec.rb +32 -0
  31. data/spec/spec.opts +1 -0
  32. data/spec/spec_helper.rb +16 -0
  33. data/tasks/rspec.rake +21 -0
  34. data/test/unit/definition_test.rb +160 -0
  35. data/test/unit/inheritance_test.rb +22 -1
  36. data/test/unit/roxml_test.rb +30 -1
  37. data/test/unit/xml_name_test.rb +29 -0
  38. data/test/unit/xml_namespace_test.rb +38 -1
  39. data/website/index.html +98 -0
  40. metadata +30 -9
  41. data/html/index.html +0 -278
  42. data/html/style.css +0 -79
  43. data/test/unit/options_test.rb +0 -103
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require example('dashed_elements')
3
+
4
+ describe GitHub::Commit do
5
+ before do
6
+ @commit = GitHub::Commit.from_xml(xml_for('dashed_elements'))
7
+ end
8
+
9
+ it "should extract committed date" do
10
+ @commit.committed_date.should be_an_instance_of(Date)
11
+ end
12
+
13
+ it "should extract url" do
14
+ @commit.url.should_not be_empty
15
+ end
16
+
17
+ it "should extract id" do
18
+ @commit.id.should_not be_empty
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require example('posts')
3
+
4
+ describe Post do
5
+ before do
6
+ @posts = Posts.from_xml(xml_for('posts')).posts
7
+ end
8
+
9
+ it "should extract description" do
10
+ @posts.each {|post| post.description.should_not be_empty }
11
+ end
12
+
13
+ it "should extract href" do
14
+ @posts.each {|post| post.href.should_not be_empty }
15
+ end
16
+
17
+ it "should extract extended" do
18
+ @posts.each {|post| post.extended.should_not be_empty }
19
+ end
20
+
21
+ it "should extract time" do
22
+ @posts.each {|post| post.time.should be_an_instance_of(DateTime) }
23
+ end
24
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require example('twitter')
3
+
4
+ describe Statuses do
5
+ describe Status do
6
+ before do
7
+ @statuses = Statuses.from_xml(xml_for('twitter')).statuses
8
+ end
9
+
10
+ it "should extract text" do
11
+ @statuses.each {|status| status.text.should_not be_empty }
12
+ end
13
+
14
+ it "should extract source" do
15
+ @statuses.each {|status| status.source.should_not be_empty }
16
+ end
17
+
18
+ describe User do
19
+ before do
20
+ @users = @statuses.map(&:user)
21
+ end
22
+
23
+ it "should extract name" do
24
+ @users.each {|user| user.name.should == "John Nunemaker" }
25
+ end
26
+
27
+ it "should extract screen_name" do
28
+ @users.each {|user| user.screen_name.should == "jnunemaker" }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,16 @@
1
+ require 'pathname'
2
+
3
+ module ROXML
4
+ SILENCE_XML_NAME_WARNING = true
5
+ end
6
+
7
+ DIR = Pathname.new(__FILE__).dirname
8
+ require DIR.join('../lib/roxml').expand_path
9
+
10
+ def example(name)
11
+ DIR.join("../examples/#{name}.rb").expand_path
12
+ end
13
+
14
+ def xml_for(name)
15
+ DIR.join("../examples/xml/#{name}.xml").expand_path
16
+ end
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'spec'
6
+ 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)
15
+ end
16
+
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']
21
+ end
@@ -0,0 +1,160 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class TestDefinition < Test::Unit::TestCase
4
+ def assert_hash(opts, kvp)
5
+ assert opts.hash?
6
+ assert !opts.array?
7
+ assert_equal kvp, {opts.hash.key.type => opts.hash.key.name,
8
+ opts.hash.value.type => opts.hash.value.name}
9
+ end
10
+
11
+ def test_text_in_array_means_as_array_for_text
12
+ opts = ROXML::Definition.new(:authors, [:text])
13
+ assert opts.array?
14
+ assert_equal :text, opts.type
15
+ end
16
+
17
+ def test_attr_in_array_means_as_array_for_attr
18
+ opts = ROXML::Definition.new(:authors, [:attr])
19
+ assert opts.array?
20
+ assert_equal :attr, opts.type
21
+ end
22
+
23
+ def test_object_in_array_means_as_array_for_object
24
+ opts = ROXML::Definition.new(:authors, [Hash])
25
+ assert opts.array?
26
+ assert_equal Hash, opts.type
27
+ end
28
+
29
+ def test_content_is_a_recognized_type
30
+ assert ROXML::Definition.new(:author, :content).content?
31
+ end
32
+
33
+ def test_required
34
+ assert !ROXML::Definition.new(:author, :content).required?
35
+ assert ROXML::Definition.new(:author, :content, :required => true).required?
36
+ assert !ROXML::Definition.new(:author, :content, :required => false).required?
37
+ end
38
+
39
+ def test_required_conflicts_with_else
40
+ assert_raise ArgumentError do
41
+ ROXML::Definition.new(:author, :content, :required => true, :else => 'Johnny')
42
+ end
43
+ assert_nothing_raised do
44
+ ROXML::Definition.new(:author, :content, :required => false, :else => 'Johnny')
45
+ end
46
+ end
47
+
48
+ def test_hash_of_attrs
49
+ opts = ROXML::Definition.new(:attributes, {:attrs => [:name, :value]})
50
+ assert_hash(opts, :attr => 'name', :attr => 'value')
51
+ end
52
+
53
+ def test_hash_with_attr_key_and_text_val
54
+ opts = ROXML::Definition.new(:attributes, {:key => {:attr => :name},
55
+ :value => :value})
56
+ assert_hash(opts, :attr => 'name', :text => 'value')
57
+ end
58
+
59
+ def test_hash_with_string_class_for_type
60
+ opts = ROXML::Definition.new(:attributes, {:key => {String => 'name'},
61
+ :value => {String => 'value'}})
62
+ assert_hash(opts, :text => 'name', :text => 'value')
63
+ end
64
+
65
+ def test_hash_with_attr_key_and_content_val
66
+ opts = ROXML::Definition.new(:attributes, {:key => {:attr => :name},
67
+ :value => :content})
68
+ assert_hash(opts, :attr => 'name', :content => '')
69
+ end
70
+
71
+ def test_hash_with_options
72
+ opts = ROXML::Definition.new(:definitions, {:attrs => [:dt, :dd]},
73
+ :in => :definitions)
74
+ assert_hash(opts, :attr => 'dt', :attr => 'dd')
75
+ end
76
+
77
+ def test_no_block_shorthand_means_no_block
78
+ assert ROXML::Definition.new(:count).blocks.empty?
79
+ assert ROXML::Definition.new(:count, :as => :intager).blocks.empty?
80
+ assert ROXML::Definition.new(:count, :as => :foat).blocks.empty?
81
+ end
82
+
83
+ def test_block_integer_shorthand
84
+ assert_equal 3, ROXML::Definition.new(:count, :as => Integer).blocks.first['3']
85
+ end
86
+
87
+ def test_block_float_shorthand
88
+ assert_equal 3.1, ROXML::Definition.new(:count, :as => Float).blocks.first['3.1']
89
+ end
90
+
91
+ def test_multiple_shorthands_raises
92
+ assert_raise ArgumentError do
93
+ ROXML::Definition.new(:count, :as => [Float, Integer])
94
+ end
95
+ end
96
+
97
+ def test_stacked_blocks
98
+ assert_equal 2, ROXML::Definition.new(:count, :as => Integer) {|val| val.to_i }.blocks.size
99
+ assert_equal 2, ROXML::Definition.new(:count, :as => Float) {|val| val.object_id }.blocks.size
100
+ end
101
+
102
+ def test_symbol_shorthands_are_deprecated
103
+ assert_deprecated do
104
+ ROXML::Definition.new(:junk, :as => :integer)
105
+ end
106
+ assert_deprecated do
107
+ ROXML::Definition.new(:junk, :as => :float)
108
+ end
109
+ end
110
+
111
+ def test_block_shorthand_supports_bool
112
+ assert_equal true, ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("1")
113
+ assert_equal [true, false, nil], ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call(["TrUe", "0", "328"])
114
+ end
115
+
116
+ def test_block_shorthand_supports_integer
117
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call(" ")
118
+ assert_equal 792, ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call("792")
119
+ assert_raise ArgumentError do
120
+ ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call("792.13")
121
+ end
122
+ assert_equal [792, 12, 328], ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call(["792", "12", "328"])
123
+ end
124
+
125
+ def test_block_shorthand_supports_float
126
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call(" ")
127
+ assert_equal 792.13, ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call("792.13")
128
+ assert_equal 240.0, ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call("240")
129
+ assert_equal [792.13, 240.0, 3.14], ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call(["792.13", "240", "3.14"])
130
+ end
131
+
132
+ def test_block_shorthand_supports_time
133
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Time).blocks.first.call(" ")
134
+ assert_equal 31, ROXML::Definition.new(:datevalue, :as => Time).blocks.first.call("12:31am").min
135
+ assert_equal [31, 0, 59], ROXML::Definition.new(:datevalue, :as => Time).blocks.first.call(["12:31am", "3:00pm", "11:59pm"]).map(&:min)
136
+ end
137
+
138
+ def test_block_shorthand_supports_date
139
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Date).blocks.first.call(" ")
140
+ assert_equal "1970-09-03", ROXML::Definition.new(:datevalue, :as => Date).blocks.first.call("September 3rd, 1970").to_s
141
+ assert_equal ["1970-09-03", "1776-07-04"], ROXML::Definition.new(:datevalue, :as => Date).blocks.first.call(["September 3rd, 1970", "1776-07-04"]).map(&:to_s)
142
+ end
143
+
144
+ def test_block_shorthand_supports_datetime
145
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => DateTime).blocks.first.call(" ")
146
+ assert_equal "1970-09-03T12:05:00+00:00", ROXML::Definition.new(:datevalue, :as => DateTime).blocks.first.call("12:05pm, September 3rd, 1970").to_s
147
+ assert_equal ["1970-09-03T12:05:00+00:00", "1700-05-22T15:00:00+00:00"], ROXML::Definition.new(:datevalue, :as => DateTime).blocks.first.call(["12:05pm, September 3rd, 1970", "3:00pm, May 22, 1700"]).map(&:to_s)
148
+ end
149
+
150
+ def test_name_explicit_indicates_whether_from_option_is_present
151
+ assert_equal true, ROXML::Definition.new(:element, :from => 'somewhere').name_explicit?
152
+ assert_equal false, ROXML::Definition.new(:element).name_explicit?
153
+ end
154
+
155
+ def test_xpath_in_is_formed_properly
156
+ opts = ROXML::Definition.new(:manufacturer, :in => './')
157
+ assert_equal "manufacturer", opts.name
158
+ assert_equal "./", opts.wrapper
159
+ end
160
+ end
@@ -1,5 +1,17 @@
1
1
  require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
2
 
3
+ class ParentWithNamespace
4
+ include ROXML
5
+ xml_namespace 'parent_namespace'
6
+ end
7
+
8
+ class ChildWithInheritedNamespace < ParentWithNamespace
9
+ end
10
+
11
+ class ChildWithOwnNamespace < ParentWithNamespace
12
+ xml_namespace 'child_namespace'
13
+ end
14
+
3
15
  class InheritedBookWithDepth < Book
4
16
  xml_reader :depth, Measurement
5
17
  end
@@ -13,6 +25,7 @@ class TestInheritance < Test::Unit::TestCase
13
25
  <author>David Thomas, Andrew Hunt, Dave Thomas</author>
14
26
  <depth units="hundredths-meters">1130</depth>
15
27
  <publisher>Pragmattic Programmers</publisher>
28
+ <pagecount>500</pagecount>
16
29
  </book>
17
30
  }
18
31
 
@@ -24,7 +37,7 @@ class TestInheritance < Test::Unit::TestCase
24
37
  assert_equal 'The PickAxe', @b.title
25
38
  assert_equal 'Probably the best Ruby book out there', @b.description
26
39
  assert_equal 'David Thomas, Andrew Hunt, Dave Thomas', @b.author
27
- assert_equal 0, @b.pages
40
+ assert_equal 500, @b.pages
28
41
  end
29
42
 
30
43
  def test_it_should_include_its_own_attributes
@@ -39,4 +52,12 @@ class TestInheritance < Test::Unit::TestCase
39
52
  book = InheritedBookWithDepth.from_xml(@book_xml)
40
53
  assert_equal "Pragmattic Programmers", book.publisher
41
54
  end
55
+
56
+ def test_it_should_inherit_namespace
57
+ assert_equal 'parent_namespace', ChildWithInheritedNamespace.roxml_namespace
58
+ end
59
+
60
+ def test_inherited_namespace_should_be_overridable
61
+ assert_equal 'child_namespace', ChildWithOwnNamespace.roxml_namespace
62
+ end
42
63
  end
@@ -25,7 +25,36 @@ class TestROXML < Test::Unit::TestCase
25
25
  def test_tag_refs_is_deprecated
26
26
  assert_deprecated do
27
27
  Class.new do
28
- include ROXML
29
28
  end.tag_refs
29
+ include ROXML
30
+ end.tag_refs
31
+ end
32
+ end
33
+
34
+ def test_from_xml_should_support_pathnames
35
+ book = BookWithContributors.from_xml(Pathname.new(fixture_path(:book_with_contributors)))
36
+ expected_contributors = ["David Thomas","Andrew Hunt","Chad Fowler"]
37
+ assert_equal("Programming Ruby - 2nd Edition", book.title)
38
+ book.contributors.each do |contributor|
39
+ assert(expected_contributors.include?(contributor.name))
40
+ end
41
+ end
42
+
43
+ def test_from_xml_should_support_uris
44
+ uri = URI.parse("file://#{File.expand_path(File.expand_path(fixture_path(:book_with_contributors)))}")
45
+ book = BookWithContributors.from_xml(uri)
46
+ expected_contributors = ["David Thomas","Andrew Hunt","Chad Fowler"]
47
+ assert_equal("Programming Ruby - 2nd Edition", book.title)
48
+ book.contributors.each do |contributor|
49
+ assert(expected_contributors.include?(contributor.name))
50
+ end
51
+ end
52
+
53
+ def test_from_xml_should_support_files
54
+ book = BookWithContributors.from_xml(File.new(fixture_path(:book_with_contributors)))
55
+ expected_contributors = ["David Thomas","Andrew Hunt","Chad Fowler"]
56
+ assert_equal("Programming Ruby - 2nd Edition", book.title)
57
+ book.contributors.each do |contributor|
58
+ assert(expected_contributors.include?(contributor.name))
30
59
  end
31
60
  end
32
61
  end
@@ -128,4 +128,33 @@ class TestXMLName < Test::Unit::TestCase
128
128
  NamedChild.xml_name?
129
129
  end
130
130
  end
131
+
132
+ def test_xml_name_should_not_be_conventionalized_if_explicitly_set
133
+ reference = ROXML::XMLTextRef.new(ROXML::Definition.new(:name, :from => 'georss:name'), WrapModule::InstanceStandin.new)
134
+ assert_equal "georss:name", reference.name
135
+ end
136
+
137
+ def test_xml_name_not_screwed_up_by_xml_convention
138
+ reference = ROXML::XMLTextRef.new(ROXML::Definition.new(:name, :in => './'), WrapModule::InstanceStandin.new)
139
+ assert_equal "name value", reference.value_in(ROXML::XML::Parser.parse(%(
140
+ <Wrapper>
141
+ <MoreStuff>
142
+ <DeepWrapper>
143
+ <Name>name value</Name>
144
+ </DeepWrapper>
145
+ </MoreStuff>
146
+ </Wrapper>
147
+ )).root)
148
+ end
149
+ end
150
+
151
+ module WrapModule
152
+ class BaseClass
153
+ include ROXML
154
+ xml_convention :camelcase
155
+ end
156
+
157
+ class InstanceStandin < BaseClass
158
+ xml_reader :name, :in => './'
159
+ end
131
160
  end
@@ -1,6 +1,6 @@
1
1
  require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
2
 
3
- class TestXMLNamespaces < Test::Unit::TestCase
3
+ class TestDefaultXMLNamespaces < Test::Unit::TestCase
4
4
  def setup
5
5
  @book = BookWithContributions.from_xml(fixture(:book_with_default_namespace))
6
6
  end
@@ -35,4 +35,41 @@ class TestXMLNamespaces < Test::Unit::TestCase
35
35
  assert_equal nil, xml.find_first('ns:node/subnode', 'ns:http://defaultnamespace.org')
36
36
  assert_equal "Another", xml.find_first('ns:node/ns:subnode', 'ns:http://defaultnamespace.org').content
37
37
  end
38
+ end
39
+
40
+ class NamespaceyObject
41
+ include ROXML
42
+ xml_namespace :aws
43
+
44
+ xml_reader :default_namespace
45
+ xml_reader :different_namespace, :from => 'different:namespace'
46
+ xml_reader :no_namespace, :from => 'no_namespace'
47
+ end
48
+
49
+ class TestXMLNamespaceDeclarations < Test::Unit::TestCase
50
+ def setup
51
+ @instance = NamespaceyObject.from_xml(%{
52
+ <aws:book xmlns:aws="http://www.aws.com/aws" xmlns:different="http://www.aws.com/different">
53
+ <aws:default_namespace>default_value</aws:default_namespace>
54
+ <different:namespace>different_value</different:namespace>
55
+ <no_namespace>no_value</no_namespace>
56
+ </aws:book>
57
+ })
58
+ end
59
+
60
+ def test_namespace_is_accessible
61
+ assert_equal "aws", @instance.class.roxml_namespace
62
+ end
63
+
64
+ def test_namespace_declaration_should_be_followed_on_attributes
65
+ assert_equal "default_value", @instance.default_namespace
66
+ end
67
+
68
+ def test_namespace_declaration_can_be_overriden_for_different_namespace_elements
69
+ assert_equal "different_value", @instance.different_namespace
70
+ end
71
+
72
+ def test_namespace_declaration_can_be_overriden_for_no_namespace_elements
73
+ assert_equal "no_value", @instance.no_namespace
74
+ end
38
75
  end