ROXML 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.gitmodules +3 -0
- data/History.txt +299 -0
- data/MIT-LICENSE +18 -0
- data/README.rdoc +161 -0
- data/Rakefile +95 -0
- data/TODO +39 -0
- data/VERSION +1 -0
- data/config/website.yml +2 -0
- data/examples/amazon.rb +35 -0
- data/examples/current_weather.rb +27 -0
- data/examples/dashed_elements.rb +20 -0
- data/examples/library.rb +40 -0
- data/examples/posts.rb +27 -0
- data/examples/rails.rb +70 -0
- data/examples/twitter.rb +37 -0
- data/examples/xml/active_record.xml +70 -0
- data/examples/xml/amazon.xml +133 -0
- data/examples/xml/current_weather.xml +89 -0
- data/examples/xml/dashed_elements.xml +52 -0
- data/examples/xml/posts.xml +23 -0
- data/examples/xml/twitter.xml +422 -0
- data/lib/roxml.rb +547 -0
- data/lib/roxml/definition.rb +236 -0
- data/lib/roxml/hash_definition.rb +25 -0
- data/lib/roxml/xml.rb +43 -0
- data/lib/roxml/xml/parsers/libxml.rb +91 -0
- data/lib/roxml/xml/parsers/nokogiri.rb +77 -0
- data/lib/roxml/xml/references.rb +297 -0
- data/roxml.gemspec +201 -0
- data/spec/definition_spec.rb +486 -0
- data/spec/examples/active_record_spec.rb +40 -0
- data/spec/examples/amazon_spec.rb +54 -0
- data/spec/examples/current_weather_spec.rb +37 -0
- data/spec/examples/dashed_elements_spec.rb +20 -0
- data/spec/examples/library_spec.rb +46 -0
- data/spec/examples/post_spec.rb +24 -0
- data/spec/examples/twitter_spec.rb +32 -0
- data/spec/roxml_spec.rb +372 -0
- data/spec/shared_specs.rb +15 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/libxml.rb +3 -0
- data/spec/support/nokogiri.rb +3 -0
- data/spec/xml/attributes_spec.rb +36 -0
- data/spec/xml/namespace_spec.rb +240 -0
- data/spec/xml/namespaces_spec.rb +32 -0
- data/spec/xml/parser_spec.rb +26 -0
- data/tasks/rdoc.rake +13 -0
- data/tasks/rspec.rake +25 -0
- data/tasks/test.rake +35 -0
- data/test/fixtures/book_malformed.xml +5 -0
- data/test/fixtures/book_pair.xml +8 -0
- data/test/fixtures/book_text_with_attribute.xml +5 -0
- data/test/fixtures/book_valid.xml +5 -0
- data/test/fixtures/book_with_authors.xml +7 -0
- data/test/fixtures/book_with_contributions.xml +9 -0
- data/test/fixtures/book_with_contributors.xml +7 -0
- data/test/fixtures/book_with_contributors_attrs.xml +7 -0
- data/test/fixtures/book_with_default_namespace.xml +9 -0
- data/test/fixtures/book_with_depth.xml +6 -0
- data/test/fixtures/book_with_octal_pages.xml +4 -0
- data/test/fixtures/book_with_publisher.xml +7 -0
- data/test/fixtures/book_with_wrapped_attr.xml +3 -0
- data/test/fixtures/dictionary_of_attr_name_clashes.xml +8 -0
- data/test/fixtures/dictionary_of_attrs.xml +6 -0
- data/test/fixtures/dictionary_of_guarded_names.xml +6 -0
- data/test/fixtures/dictionary_of_mixeds.xml +4 -0
- data/test/fixtures/dictionary_of_name_clashes.xml +10 -0
- data/test/fixtures/dictionary_of_names.xml +4 -0
- data/test/fixtures/dictionary_of_texts.xml +10 -0
- data/test/fixtures/library.xml +30 -0
- data/test/fixtures/library_uppercase.xml +30 -0
- data/test/fixtures/muffins.xml +3 -0
- data/test/fixtures/nameless_ageless_youth.xml +2 -0
- data/test/fixtures/node_with_attr_name_conflicts.xml +1 -0
- data/test/fixtures/node_with_name_conflicts.xml +4 -0
- data/test/fixtures/numerology.xml +4 -0
- data/test/fixtures/person.xml +1 -0
- data/test/fixtures/person_with_guarded_mothers.xml +13 -0
- data/test/fixtures/person_with_mothers.xml +10 -0
- data/test/mocks/dictionaries.rb +57 -0
- data/test/mocks/mocks.rb +279 -0
- data/test/support/fixtures.rb +11 -0
- data/test/test_helper.rb +34 -0
- data/test/unit/definition_test.rb +235 -0
- data/test/unit/deprecations_test.rb +24 -0
- data/test/unit/to_xml_test.rb +81 -0
- data/test/unit/xml_attribute_test.rb +39 -0
- data/test/unit/xml_block_test.rb +81 -0
- data/test/unit/xml_bool_test.rb +122 -0
- data/test/unit/xml_convention_test.rb +150 -0
- data/test/unit/xml_hash_test.rb +115 -0
- data/test/unit/xml_initialize_test.rb +49 -0
- data/test/unit/xml_name_test.rb +141 -0
- data/test/unit/xml_namespace_test.rb +31 -0
- data/test/unit/xml_object_test.rb +207 -0
- data/test/unit/xml_required_test.rb +94 -0
- data/test/unit/xml_text_test.rb +71 -0
- data/website/index.html +98 -0
- metadata +254 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class TestDefaultXMLNamespaces < ActiveSupport::TestCase
|
4
|
+
def setup
|
5
|
+
@book = BookWithContributions.from_xml(fixture(:book_with_default_namespace))
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_default_namespace_doesnt_interfere_with_normal_operation
|
9
|
+
assert_equal("Programming Ruby - 2nd Edition", @book.title)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_default_namespace_is_applied_to_in_element
|
13
|
+
expected_authors = ["David Thomas","Andrew Hunt","Chad Fowler"]
|
14
|
+
assert !@book.contributions.empty?
|
15
|
+
@book.contributions.each do |contributor|
|
16
|
+
assert expected_authors.include?(contributor.name)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_default_namespace_on_root_node_should_be_found
|
21
|
+
require 'libxml'
|
22
|
+
xml = LibXML::XML::Parser.string(
|
23
|
+
'<container xmlns="http://defaultnamespace.org"><node>Yeah, content</node><node><subnode>Another</subnode></node></container>').parse
|
24
|
+
|
25
|
+
assert_equal nil, xml.find_first('node')
|
26
|
+
assert_equal "Yeah, content", xml.find_first('ns:node', 'ns:http://defaultnamespace.org').content
|
27
|
+
assert_equal nil, xml.find_first('ns:node/subnode', 'ns:http://defaultnamespace.org')
|
28
|
+
assert_equal "Another", xml.find_first('ns:node/ns:subnode', 'ns:http://defaultnamespace.org').content
|
29
|
+
rescue LoadError
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class EmptyCart
|
4
|
+
include ROXML
|
5
|
+
|
6
|
+
xml_reader :id
|
7
|
+
|
8
|
+
def empty?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class CartHolder
|
14
|
+
include ROXML
|
15
|
+
|
16
|
+
xml_reader :cart, :as => EmptyCart, :required => true
|
17
|
+
end
|
18
|
+
|
19
|
+
class TestXMLObject < ActiveSupport::TestCase
|
20
|
+
# Test book with text and attribute
|
21
|
+
def test_book_author_text_attribute
|
22
|
+
book = BookWithAuthorTextAttribute.from_xml(fixture(:book_text_with_attribute))
|
23
|
+
assert_equal("primary",book.author.role)
|
24
|
+
assert_equal("David Thomas",book.author.text)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Test XML object containing list of other XML objects (one-to-many)
|
28
|
+
# In this case, book with contibutions
|
29
|
+
def test_one_to_many_with_container
|
30
|
+
expected_authors = ["David Thomas","Andrew Hunt","Chad Fowler"]
|
31
|
+
book = BookWithContributions.from_xml(fixture(:book_with_contributions))
|
32
|
+
assert_equal("Programming Ruby - 2nd Edition", book.title)
|
33
|
+
book.contributions.each do |contributor|
|
34
|
+
assert expected_authors.include?(contributor.name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Test XML object containing 1-n other XML objects without container (one-to-many)
|
39
|
+
# In this case, book with contibutions
|
40
|
+
def test_one_to_many_without_container
|
41
|
+
expected_contributors = ["David Thomas","Andrew Hunt","Chad Fowler"]
|
42
|
+
book = BookWithContributors.from_xml(fixture(:book_with_contributors))
|
43
|
+
assert_equal("Programming Ruby - 2nd Edition", book.title)
|
44
|
+
book.contributors.each do |contributor|
|
45
|
+
assert(expected_contributors.include?(contributor.name))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# when building objects that contain arrays, the second object seems to
|
50
|
+
# inherit data from the first
|
51
|
+
#
|
52
|
+
def test_one_to_many_without_container_sequence
|
53
|
+
contrib = WriteableContributor.new
|
54
|
+
contrib.name = "David Thomas"
|
55
|
+
|
56
|
+
book_one = WriteableBookWithContributors.new
|
57
|
+
book_one.isbn = "9781843549161"
|
58
|
+
book_one.title = "Anathem"
|
59
|
+
book_one.description = "A new title from Neal Stephenson"
|
60
|
+
book_one.contributors = [contrib]
|
61
|
+
|
62
|
+
# this book should be completely empty
|
63
|
+
book_two = WriteableBookWithContributors.new
|
64
|
+
|
65
|
+
assert_equal(nil, book_two.isbn)
|
66
|
+
assert_equal(nil, book_two.title)
|
67
|
+
assert_equal(nil, book_two.description)
|
68
|
+
assert_equal(nil, book_two.contributors)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Test XML object containing one other XML object (one-to-one)
|
72
|
+
# In this case, book with publisher
|
73
|
+
def test_one_to_one
|
74
|
+
book = BookWithPublisher.from_xml(fixture(:book_with_publisher))
|
75
|
+
assert_equal("Programming Ruby - 2nd Edition", book.title)
|
76
|
+
assert_equal("Pragmatic Bookshelf", book.publisher.name)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Test XML object containing type of self (self-reference)
|
80
|
+
def test_self_reference
|
81
|
+
book = BookPair.from_xml(fixture(:book_pair))
|
82
|
+
assert_equal("Programming Ruby - 2nd Edition", book.title)
|
83
|
+
assert_equal("Agile Web Development with Rails", book.book.title)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Test three-level composition (one-to-many-to-many)
|
87
|
+
def test_one_to_many_to_many
|
88
|
+
expected_contributors = ["David Thomas","Andrew Hunt","Chad Fowler", "David Heinemeier Hansson"]
|
89
|
+
expected_books = ["Programming Ruby - 2nd Edition", "Agile Web Development with Rails"]
|
90
|
+
library = Library.from_xml(fixture(:library))
|
91
|
+
assert_equal("Ruby library", library.name)
|
92
|
+
assert !library.books.empty?
|
93
|
+
library.books.each do |book|
|
94
|
+
assert expected_books.include?(book.title)
|
95
|
+
book.contributions.each do |contributor|
|
96
|
+
assert(expected_contributors.include?(contributor.name))
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_without_needed_from
|
102
|
+
assert_equal [], UppercaseLibrary.from_xml(fixture(:library)).books
|
103
|
+
assert_equal [], Library.from_xml(fixture(:library_uppercase)).books
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_with_needed_from
|
107
|
+
assert Library.from_xml(fixture(:library)).books
|
108
|
+
assert UppercaseLibrary.from_xml(fixture(:library_uppercase)).books
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_with_recursion
|
112
|
+
p = PersonWithMother.from_xml(fixture(:person_with_mothers))
|
113
|
+
assert_equal 'Ben Franklin', p.name
|
114
|
+
assert_equal 'Abiah Folger', p.mother.name
|
115
|
+
assert_equal 'Madeup Mother', p.mother.mother.name
|
116
|
+
assert_equal nil, p.mother.mother.mother
|
117
|
+
end
|
118
|
+
|
119
|
+
class Node
|
120
|
+
include ROXML
|
121
|
+
|
122
|
+
xml_reader :name, :from => 'node_name'
|
123
|
+
xml_reader :nodes, :as => [Node]
|
124
|
+
end
|
125
|
+
|
126
|
+
class Taxonomy
|
127
|
+
include ROXML
|
128
|
+
|
129
|
+
xml_reader :name, :from => 'taxonomy_name'
|
130
|
+
xml_reader :nodes, :as => [Node]
|
131
|
+
end
|
132
|
+
|
133
|
+
class Taxonomies
|
134
|
+
include ROXML
|
135
|
+
xml_reader :taxonomies, :as => [Taxonomy]
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_more_recursion
|
139
|
+
# quiet the error handler
|
140
|
+
ROXML::XML::Error.reset_handler if ROXML::XML::Error.respond_to?(:reset_handler)
|
141
|
+
taxonomies = Taxonomies.from_xml(<<HERE)
|
142
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
143
|
+
<!DOCTYPE taxonomies SYSTEM "taxonomy.dtd">
|
144
|
+
<taxonomies>
|
145
|
+
<taxonomy>
|
146
|
+
<taxonomy_name>World</taxonomy_name>
|
147
|
+
<node node_id="2" content_object_id="82534" object_type_id="2">
|
148
|
+
<node_name lang_iso="eng">Africa</node_name>
|
149
|
+
<node node_id="331" content_object_id="11" object_type_id="4">
|
150
|
+
<node_name lang_iso="eng">Algeria</node_name>
|
151
|
+
<node node_id="7271" content_object_id="117629" object_type_id="8">
|
152
|
+
<node_name lang_iso="eng">Algiers</node_name>
|
153
|
+
</node>
|
154
|
+
<node node_id="7272" content_object_id="117630" object_type_id="8">
|
155
|
+
<node_name lang_iso="eng">Ghardaïa</node_name>
|
156
|
+
</node>
|
157
|
+
<node node_id="7871" content_object_id="1000713999" object_type_id="8">
|
158
|
+
<node_name lang_iso="eng">El Oued</node_name>
|
159
|
+
</node>
|
160
|
+
<node node_id="7872" content_object_id="1000714008" object_type_id="8">
|
161
|
+
<node_name lang_iso="eng">Timimoun</node_name>
|
162
|
+
</node>
|
163
|
+
<node node_id="8903" content_object_id="1000565565" object_type_id="8">
|
164
|
+
<node_name lang_iso="eng">Annaba</node_name>
|
165
|
+
</node>
|
166
|
+
</node>
|
167
|
+
</node>
|
168
|
+
</taxonomy>
|
169
|
+
</taxonomies>
|
170
|
+
HERE
|
171
|
+
assert_equal 1, taxonomies.taxonomies.size
|
172
|
+
assert_equal 'World', taxonomies.taxonomies.first.name
|
173
|
+
node = taxonomies.taxonomies.first.nodes.first
|
174
|
+
assert_equal 'Africa', node.name
|
175
|
+
assert_equal 'Algeria', node.nodes.first.name
|
176
|
+
assert_equal ['Algiers', "Gharda\303\257a", 'El Oued', 'Timimoun', 'Annaba'],
|
177
|
+
node.nodes.first.nodes.map(&:name)
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_with_guarded_recursion
|
181
|
+
p = PersonWithGuardedMother.from_xml(fixture(:person_with_guarded_mothers))
|
182
|
+
assert_equal 'Ben "Benji" Franklin', p.name
|
183
|
+
assert_equal 'Abiah \'Abby\' Folger', p.mother.name
|
184
|
+
assert_equal 'Madeup Mother < the third >', p.mother.mother.name
|
185
|
+
assert_equal nil, p.mother.mother.mother
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_recursive_with_default_initialization
|
189
|
+
p = PersonWithMotherOrMissing.from_xml(fixture(:person_with_mothers))
|
190
|
+
assert_equal 'Unknown', p.mother.mother.mother.name
|
191
|
+
assert_equal Person, p.mother.mother.mother.class
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_defining_empty_on_object_doesnt_cause_it_to_be_seen_as_absent
|
195
|
+
# absent means defaulting, failing required
|
196
|
+
|
197
|
+
holder = CartHolder.from_xml(%{
|
198
|
+
<cartholder>
|
199
|
+
<cart>
|
200
|
+
<id>111111</id>
|
201
|
+
</cart>
|
202
|
+
</cartholder>
|
203
|
+
})
|
204
|
+
|
205
|
+
assert_equal "111111", holder.cart.id
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class TestXMLRequired < ActiveSupport::TestCase
|
4
|
+
def setup
|
5
|
+
@full_book = <<BOOK
|
6
|
+
<book ISBN="1234">
|
7
|
+
<title>This & that</title>
|
8
|
+
<contributor_array>
|
9
|
+
<contributor role="Author">
|
10
|
+
<name>Johnny</name>
|
11
|
+
</contributor>
|
12
|
+
</contributor_array>
|
13
|
+
<contributor_hash>
|
14
|
+
<contributor role="Author" name="Johnny" />
|
15
|
+
</contributor_hash>
|
16
|
+
</book>
|
17
|
+
BOOK
|
18
|
+
|
19
|
+
@book_missing_attr = <<BOOK
|
20
|
+
<book>
|
21
|
+
<title>This & that</title>
|
22
|
+
<contributor_array>
|
23
|
+
<contributor role="Author">
|
24
|
+
<name>Johnny</name>
|
25
|
+
</contributor>
|
26
|
+
</contributor_array>
|
27
|
+
<contributor_hash>
|
28
|
+
<contributor role="Author" name="Johnny" />
|
29
|
+
</contributor_hash>
|
30
|
+
</book>
|
31
|
+
BOOK
|
32
|
+
|
33
|
+
@book_missing_text = <<BOOK
|
34
|
+
<book ISBN="1234">
|
35
|
+
<contributor_array>
|
36
|
+
<contributor role="Author">
|
37
|
+
<name>Johnny</name>
|
38
|
+
</contributor>
|
39
|
+
</contributor_array>
|
40
|
+
<contributor_hash>
|
41
|
+
<contributor role="Author" name="Johnny" />
|
42
|
+
</contributor_hash>
|
43
|
+
</book>
|
44
|
+
BOOK
|
45
|
+
|
46
|
+
@book_missing_array = <<BOOK
|
47
|
+
<book ISBN="1234">
|
48
|
+
<title>This & that</title>
|
49
|
+
<contributor_hash>
|
50
|
+
<contributor role="Author" name="Johnny" />
|
51
|
+
</contributor_hash>
|
52
|
+
</book>
|
53
|
+
BOOK
|
54
|
+
|
55
|
+
@book_missing_hash = <<BOOK
|
56
|
+
<book ISBN="1234">
|
57
|
+
<title>This & that</title>
|
58
|
+
<contributor_array>
|
59
|
+
<contributor role="Author">
|
60
|
+
<name>Johnny</name>
|
61
|
+
</contributor>
|
62
|
+
</contributor_array>
|
63
|
+
</book>
|
64
|
+
BOOK
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_required_passes_on_prescence
|
68
|
+
BookWithRequired.from_xml(@full_book)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_required_throws_on_attr_absence
|
72
|
+
assert_raise ROXML::RequiredElementMissing do
|
73
|
+
BookWithRequired.from_xml(@book_missing_attr)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_required_throws_on_text_absence
|
78
|
+
assert_raise ROXML::RequiredElementMissing do
|
79
|
+
BookWithRequired.from_xml(@book_missing_text)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_required_throws_on_array_absence
|
84
|
+
assert_raise ROXML::RequiredElementMissing do
|
85
|
+
BookWithRequired.from_xml(@book_missing_array)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_required_throws_on_hash_absence
|
90
|
+
assert_raise ROXML::RequiredElementMissing do
|
91
|
+
BookWithRequired.from_xml(@book_missing_hash)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class TestXMLText < ActiveSupport::TestCase
|
4
|
+
# Test a simple mapping with no composition
|
5
|
+
def test_valid_simple
|
6
|
+
book = Book.from_xml(fixture(:book_valid))
|
7
|
+
assert_equal("The PickAxe", book.title)
|
8
|
+
assert_equal("David Thomas, Andrew Hunt & Dave Thomas", book.author)
|
9
|
+
|
10
|
+
assert_equal xml_fixture(:book_valid).to_s.gsub("\n", ''), book.to_xml.to_s.gsub("\n", '')
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_without_needed_from
|
14
|
+
assert !Library.from_xml(fixture(:library_uppercase)).name
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_with_needed_from
|
18
|
+
assert_equal "Ruby library", Library.from_xml(fixture(:library)).name
|
19
|
+
assert_equal "Ruby library", UppercaseLibrary.from_xml(fixture(:library_uppercase)).name
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_as_array
|
23
|
+
assert_equal ["David Thomas","Andrew Hunt","Dave Thomas"].sort,
|
24
|
+
BookWithAuthors.from_xml(fixture(:book_with_authors)).authors.sort
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_empty_array_result_returned_properly
|
28
|
+
empty_array = Class.new do
|
29
|
+
include ROXML
|
30
|
+
|
31
|
+
xml_reader :missing_array, :as => [], :from => 'missing'
|
32
|
+
end
|
33
|
+
|
34
|
+
obj = empty_array.from_xml('<empty_array></empty_array>')
|
35
|
+
assert_equal [], obj.missing_array
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_text_modification
|
39
|
+
person = Person.from_xml(fixture(:person))
|
40
|
+
assert_equal("Ben Franklin", person.name)
|
41
|
+
person.name = "Fred"
|
42
|
+
xml=person.to_xml.to_s
|
43
|
+
assert(/Fred/=~xml)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_default_initialization
|
47
|
+
person = PersonWithMotherOrMissing.from_xml(fixture(:nameless_ageless_youth))
|
48
|
+
assert_equal "Anonymous", person.name
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_default_initialization_of_content
|
52
|
+
person = Person.from_xml(fixture(:nameless_ageless_youth))
|
53
|
+
assert_equal "Unknown", person.name
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_recursive_with_default_initialization
|
57
|
+
p = PersonWithMotherOrMissing.from_xml(fixture(:person_with_mothers))
|
58
|
+
assert_equal 'Unknown', p.mother.mother.mother.name
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_get_with_block
|
62
|
+
p = Book.from_xml(fixture(:book_valid))
|
63
|
+
assert_equal 357, p.pages
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_no_name_clashes
|
67
|
+
n = NodeWithNameConflicts.from_xml(fixture(:node_with_name_conflicts))
|
68
|
+
assert_equal "Just junk... really", n.content
|
69
|
+
assert_equal "Cartwheel", n.name
|
70
|
+
end
|
71
|
+
end
|
data/website/index.html
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
7
|
+
|
8
|
+
<title>Empact/roxml @ GitHub</title>
|
9
|
+
|
10
|
+
<style type="text/css">
|
11
|
+
body {
|
12
|
+
margin-top: 1.0em;
|
13
|
+
background-color: #baafdb;
|
14
|
+
font-family: "helvetica";
|
15
|
+
color: #000000;
|
16
|
+
}
|
17
|
+
#container {
|
18
|
+
margin: 0 auto;
|
19
|
+
width: 700px;
|
20
|
+
}
|
21
|
+
h1 { font-size: 3.8em; color: #455024; margin-bottom: 3px; }
|
22
|
+
h1 .small { font-size: 0.4em; }
|
23
|
+
h1 a { text-decoration: none }
|
24
|
+
h2 { font-size: 1.5em; color: #455024; }
|
25
|
+
h3 { text-align: center; color: #455024; }
|
26
|
+
a { color: #455024; }
|
27
|
+
.description { font-size: 1.2em; margin-bottom: 30px; margin-top: 30px; font-style: italic;}
|
28
|
+
.download { float: right; }
|
29
|
+
pre { background: #000; color: #fff; padding: 15px;}
|
30
|
+
hr { border: 0; width: 80%; border-bottom: 1px solid #aaa}
|
31
|
+
.footer { text-align:center; padding-top:30px; font-style: italic; }
|
32
|
+
</style>
|
33
|
+
|
34
|
+
</head>
|
35
|
+
|
36
|
+
<body>
|
37
|
+
<a href="http://github.com/Empact/roxml"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
|
38
|
+
|
39
|
+
<div id="container">
|
40
|
+
|
41
|
+
<div class="download">
|
42
|
+
<a href="http://github.com/Empact/roxml/zipball/master">
|
43
|
+
<img border="0" width="90" src="http://github.com/images/modules/download/zip.png"></a>
|
44
|
+
<a href="http://github.com/Empact/roxml/tarball/master">
|
45
|
+
<img border="0" width="90" src="http://github.com/images/modules/download/tar.png"></a>
|
46
|
+
</div>
|
47
|
+
|
48
|
+
<h1><a href="http://github.com/Empact/roxml">roxml</a>
|
49
|
+
<span class="small">by <a href="http://github.com/Empact">Empact</a></small></h1>
|
50
|
+
|
51
|
+
<div class="description">
|
52
|
+
ROXML is a module for binding Ruby classes to XML. It supports custom mapping and bidirectional marshaling between Ruby and XML using annotation-style class methods. ROXML supports the Nokogiri and LibXML XML processors.
|
53
|
+
</div>
|
54
|
+
|
55
|
+
<p>We may not want to work with XML, but we don't always get to pick just how our data comes. If you do need to do serious work with XML, ROXML is here to make it nice.
|
56
|
+
|
57
|
+
Use xpath-based xml declarations to map an XML response into an extensible object, use that object, and then ouput it back to xml as it came.
|
58
|
+
|
59
|
+
Aside from the basics, ROXML has a lot of little goodies to make these definitions minimal and readable, which are worth digging in for. See the 'xml_convention' method for easily referencing xml which uses other naming conventions. See the handling of '?' in accessor names, the application of blocks and such for other manipulations.
|
60
|
+
|
61
|
+
And finally, if you use this library, feel free to push code back my way. I'll be looking forward to it.</p><h2>Dependencies</h2>
|
62
|
+
<p>activesupport >= 2.1.0</p>
|
63
|
+
<h2>Install</h2>
|
64
|
+
<p>'gem install roxml' will install the latest stable <a href="http://rubyforge.org/frs/?group_id=305">rubyforge version</a></p>
|
65
|
+
<h2>License</h2>
|
66
|
+
<p>MIT License</p>
|
67
|
+
<h2>Authors</h2>
|
68
|
+
<p>Ben Woosley (ben.woosley@gmail.com)
|
69
|
+
<br/>Anders Engström (anders.engstrom@gnejs.net)
|
70
|
+
<br/>James Thompson (james@plainprograms.com)
|
71
|
+
<br/>James Healy (jimmy@deefa.com)
|
72
|
+
<br/>Zak Mandhro (mandhro@yahoo.com)
|
73
|
+
<br/>Russ Olsen (russell.olsen@gmail.com)</p>
|
74
|
+
<h2>Contact</h2>
|
75
|
+
<p>Ben Woosley (Ben.Woosley@gmail.com)
|
76
|
+
<br/> </p>
|
77
|
+
|
78
|
+
|
79
|
+
<h2>Download</h2>
|
80
|
+
<p>
|
81
|
+
You can download this project in either
|
82
|
+
<a href="http://github.com/Empact/roxml/zipball/master">zip</a> or
|
83
|
+
<a href="http://github.com/Empact/roxml/tarball/master">tar</a> formats.
|
84
|
+
</p>
|
85
|
+
<p>You can also clone the project with <a href="http://git-scm.com">Git</a>
|
86
|
+
by running:
|
87
|
+
<pre>$ git clone git://github.com/Empact/roxml</pre>
|
88
|
+
</p>
|
89
|
+
|
90
|
+
<div class="footer">
|
91
|
+
get the source code on GitHub : <a href="http://github.com/Empact/roxml">Empact/roxml</a>
|
92
|
+
</div>
|
93
|
+
|
94
|
+
</div>
|
95
|
+
|
96
|
+
|
97
|
+
</body>
|
98
|
+
</html>
|