representable 0.0.1.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/.gitignore +7 -0
  2. data/.gitmodules +3 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +3 -0
  5. data/History.txt +354 -0
  6. data/LICENSE +20 -0
  7. data/README.rdoc +186 -0
  8. data/Rakefile +10 -0
  9. data/TODO +37 -0
  10. data/VERSION +1 -0
  11. data/examples/amazon.rb +35 -0
  12. data/examples/current_weather.rb +27 -0
  13. data/examples/dashed_elements.rb +20 -0
  14. data/examples/library.rb +40 -0
  15. data/examples/posts.rb +27 -0
  16. data/examples/rails.rb +70 -0
  17. data/examples/twitter.rb +37 -0
  18. data/examples/xml/active_record.xml +70 -0
  19. data/examples/xml/amazon.xml +133 -0
  20. data/examples/xml/current_weather.xml +89 -0
  21. data/examples/xml/dashed_elements.xml +52 -0
  22. data/examples/xml/posts.xml +23 -0
  23. data/examples/xml/twitter.xml +422 -0
  24. data/lib/representable.rb +257 -0
  25. data/lib/representable/definition.rb +109 -0
  26. data/lib/representable/nokogiri_extensions.rb +19 -0
  27. data/lib/representable/references.rb +153 -0
  28. data/lib/representable/version.rb +3 -0
  29. data/lib/representable/xml.rb +79 -0
  30. data/representable.gemspec +29 -0
  31. data/spec/definition_spec.rb +495 -0
  32. data/spec/examples/active_record_spec.rb +41 -0
  33. data/spec/examples/amazon_spec.rb +54 -0
  34. data/spec/examples/current_weather_spec.rb +37 -0
  35. data/spec/examples/dashed_elements_spec.rb +20 -0
  36. data/spec/examples/library_spec.rb +46 -0
  37. data/spec/examples/post_spec.rb +24 -0
  38. data/spec/examples/twitter_spec.rb +32 -0
  39. data/spec/roxml_integration_test.rb +289 -0
  40. data/spec/roxml_spec.rb +372 -0
  41. data/spec/shared_specs.rb +15 -0
  42. data/spec/spec_helper.rb +5 -0
  43. data/spec/support/libxml.rb +3 -0
  44. data/spec/support/nokogiri.rb +3 -0
  45. data/spec/xml/array_spec.rb +36 -0
  46. data/spec/xml/attributes_spec.rb +71 -0
  47. data/spec/xml/encoding_spec.rb +53 -0
  48. data/spec/xml/namespace_spec.rb +270 -0
  49. data/spec/xml/namespaces_spec.rb +67 -0
  50. data/spec/xml/object_spec.rb +82 -0
  51. data/spec/xml/parser_spec.rb +21 -0
  52. data/spec/xml/text_spec.rb +71 -0
  53. data/test/fixtures/book_malformed.xml +5 -0
  54. data/test/fixtures/book_pair.xml +8 -0
  55. data/test/fixtures/book_text_with_attribute.xml +5 -0
  56. data/test/fixtures/book_valid.xml +5 -0
  57. data/test/fixtures/book_with_authors.xml +7 -0
  58. data/test/fixtures/book_with_contributions.xml +9 -0
  59. data/test/fixtures/book_with_contributors.xml +7 -0
  60. data/test/fixtures/book_with_contributors_attrs.xml +7 -0
  61. data/test/fixtures/book_with_default_namespace.xml +9 -0
  62. data/test/fixtures/book_with_depth.xml +6 -0
  63. data/test/fixtures/book_with_octal_pages.xml +4 -0
  64. data/test/fixtures/book_with_publisher.xml +7 -0
  65. data/test/fixtures/book_with_wrapped_attr.xml +3 -0
  66. data/test/fixtures/dictionary_of_attr_name_clashes.xml +8 -0
  67. data/test/fixtures/dictionary_of_attrs.xml +6 -0
  68. data/test/fixtures/dictionary_of_guarded_names.xml +6 -0
  69. data/test/fixtures/dictionary_of_mixeds.xml +4 -0
  70. data/test/fixtures/dictionary_of_name_clashes.xml +10 -0
  71. data/test/fixtures/dictionary_of_names.xml +4 -0
  72. data/test/fixtures/dictionary_of_texts.xml +10 -0
  73. data/test/fixtures/library.xml +30 -0
  74. data/test/fixtures/library_uppercase.xml +30 -0
  75. data/test/fixtures/muffins.xml +3 -0
  76. data/test/fixtures/nameless_ageless_youth.xml +2 -0
  77. data/test/fixtures/node_with_attr_name_conflicts.xml +1 -0
  78. data/test/fixtures/node_with_name_conflicts.xml +4 -0
  79. data/test/fixtures/numerology.xml +4 -0
  80. data/test/fixtures/person.xml +1 -0
  81. data/test/fixtures/person_with_guarded_mothers.xml +13 -0
  82. data/test/fixtures/person_with_mothers.xml +10 -0
  83. data/test/mocks/dictionaries.rb +57 -0
  84. data/test/mocks/mocks.rb +279 -0
  85. data/test/roxml_test.rb +58 -0
  86. data/test/support/fixtures.rb +11 -0
  87. data/test/test_helper.rb +6 -0
  88. data/test/unit/definition_test.rb +235 -0
  89. data/test/unit/deprecations_test.rb +24 -0
  90. data/test/unit/to_xml_test.rb +81 -0
  91. data/test/unit/xml_attribute_test.rb +39 -0
  92. data/test/unit/xml_block_test.rb +81 -0
  93. data/test/unit/xml_bool_test.rb +122 -0
  94. data/test/unit/xml_convention_test.rb +150 -0
  95. data/test/unit/xml_hash_test.rb +115 -0
  96. data/test/unit/xml_initialize_test.rb +49 -0
  97. data/test/unit/xml_name_test.rb +141 -0
  98. data/test/unit/xml_namespace_test.rb +31 -0
  99. data/test/unit/xml_object_test.rb +206 -0
  100. data/test/unit/xml_required_test.rb +94 -0
  101. data/test/unit/xml_text_test.rb +71 -0
  102. data/website/index.html +98 -0
  103. metadata +248 -0
@@ -0,0 +1,7 @@
1
+ spec/**/*.xml
2
+ rdoc
3
+ build
4
+ doc
5
+ Rake.config
6
+ pkg
7
+ .project
@@ -0,0 +1,3 @@
1
+ [submodule "vendor/override_rake_task"]
2
+ path = vendor/override_rake_task
3
+ url = git://github.com/Empact/override_rake_task.git
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -0,0 +1,354 @@
1
+ == 3.1.6 (September 9, 2010)
2
+
3
+ * bug fix
4
+
5
+ * load active_support in a way that is compatible with 2.x and 3.x
6
+ (fixes gh issue #27)
7
+ * change the way we monkey patch Nokogiri to leave the original
8
+ behaviour of the search() method unchanged (fixes gh issue #16)
9
+ * Unofficial release by James Healy, empact has stepped back from maintaining
10
+ roxml
11
+
12
+ == 3.1.5 (December 18, 2009)
13
+
14
+ * bug fix
15
+
16
+ * don't use tasks/ because those rake files are picked up by those vendoring roxml
17
+
18
+ == 3.1.4 (December 18, 2009)
19
+
20
+ * bug fix
21
+
22
+ * require the necessary version of active support (#tap wasn't introduced until 2.3)
23
+
24
+ == 3.1.3 (October 30, 2009)
25
+
26
+ * minor enhancements
27
+
28
+ * Add support for local-name() reference reading via :namespace => '*'
29
+ (ala http://techrageo.us/2008/11/01/wildcard-namespaces-in-xpath/)
30
+
31
+ * bug fixes
32
+
33
+ * attributes collected :as => [] were previously output improperly,
34
+ as a single attribute on a single node
35
+ * don't output crazy, context-less namespaces and local-name xpaths
36
+ when trying to output namespaced attributes
37
+
38
+ == 3.1.2 (October 18, 2009)
39
+
40
+ * minor enhancements
41
+
42
+ * Retain whitespace in element contents, but still default on blank (rather than entirely empty) elements
43
+
44
+ * bug fixes
45
+
46
+ * Include namespaces in xml output
47
+ * Fix that auto-wrapped collections weren't output with their wrappers
48
+ (which requires introducing the roxml_references accessor on the instance)
49
+
50
+ == 3.1.1 (October 17, 2009)
51
+
52
+ * bug fix
53
+
54
+ * Fix bad load paths
55
+
56
+ == 3.1 (October 16, 2009)
57
+
58
+ * major enhancements
59
+
60
+ * Add support for registering XML namespace prefixes via the xml_namespaces method
61
+
62
+ * bug fix
63
+
64
+ * References to arrays of attributes were only returning the first. No more.
65
+
66
+ == 3.0 (October 14, 2009)
67
+
68
+ * major enhancements
69
+
70
+ * Add Nokogiri support
71
+ * Remove previously deprecated functionality
72
+ * Remove REXML support
73
+ * Error on any unrecognized options
74
+ * Normalize hash declaration syntax:
75
+ * for :key => '@string', string is taken to be the :from argument
76
+ * for :key => {:from => '@string', :as => Type}, the arguments are just the same as a regular declaration
77
+
78
+ * minor enhancements
79
+
80
+ * Include 't' and 'f' in the list of possible boolean values, since rails uses them
81
+ * Remove :attrs hash syntax. Not particularly helpful & somewhat obfuscatory. Use :key, :value instead.
82
+ * Default attrs ending in '_at' to DateTime. This can be overriden via :as
83
+ * Default attrs ending in '_on' to Date. This can be overriden via :as
84
+ * Don't require rubygems within the library
85
+ * Don't mess with the load path
86
+
87
+ == 2.5.4 (October 4, 2009)
88
+
89
+ * bug fix
90
+
91
+ * Rely on REXML's #add_child and LibXML's <<, rather than #child_add which had been removed from REXML and deprecated from LibXML
92
+
93
+ == 2.5.3 (March 22, 2009)
94
+
95
+ * minor enhancement
96
+
97
+ * Work around apparently unintentional breaking change in libxml-ruby 1.1.3
98
+
99
+ == 2.5.2 (March 12, 2009)
100
+
101
+ * minor enhancements
102
+
103
+ * Remove dependency on an Object#try which conflicted with ActiveSupport 2.3's version
104
+ * Document the :to_xml option for attr references
105
+ * Require active_support directly, as it's less brittle and plays nicer with other libraries
106
+
107
+ == 2.5.1 (March 2, 2009)
108
+
109
+ * minor enhancements
110
+
111
+ * Add Document#save to REXML support, complete with XMLDecl output
112
+
113
+ * bug fixes
114
+
115
+ * rexml support has been fixed
116
+ * the first example in the readme was broken and has been fixed
117
+
118
+ == 2.5.0 (February 24, 2009)
119
+
120
+ * major enhancements
121
+
122
+ * support for mapping ActiveRecord classes. See examples/rails.rb.
123
+ * .from_xml will now use the setter for the declared variable, if one is available,
124
+ rather than directly setting the instance variable
125
+ * All declaration type arguments are now supported via the :as parameter, e.g. :as => [MyType]. Other uses are deprecated.
126
+ * All xml source path arguments are now supported via the :from and :in parameters, e.g. :from => :attr or :from => '@MyAttr'. Other uses are deprecated.
127
+ * All other options are presented separately, e.g. :cdata => true rather than :as => :cdata. Other uses are deprecated.
128
+
129
+ * minor enhancements
130
+
131
+ * .xml_attr declaration declares neither a reader nor a writer. With it you're left to your own devices.
132
+ * You can use literal [] for the [:text] object type declaration,
133
+ though they should be used in the :as parameter: :as => []
134
+ * You can use [] with your :as declarations. e.g. :as => [Float] is
135
+ equivalent to the old :as => [Float, :array]
136
+ * Show the actual call point of a deprecation, rather than some internal path
137
+ * Add support for BigDecimal and Fixnum as block shorthands [James Healy]
138
+ * Update libxml support to 0.9.6, and add it as a dependency, to ensure correct versioning, and
139
+ as it's an order of magnitude faster than rexml
140
+
141
+ * breaking changes
142
+
143
+ * :else option only applies to instances created via .from_xml
144
+ * On .from_xml, #initialize is now called with the *initialization_args before extracting attributes from the xml.
145
+ * #xml_initialize has been replaced with the #after_parse callback, which takes no arguments.
146
+ * .xml_accessor will overwrite the setter for this variable if it has already been defined. Use .xml_reader or .xml_attr,
147
+ or define your writer later, if this is not the behavior you want.
148
+
149
+ * deprecations
150
+
151
+ * Use :cdata => true rather than :as => :cdata
152
+ * Use literal [] around your regular object type, rather than :as => :array
153
+ * Use :from => :content rather than the :content object declaration type
154
+ * Specifying an unknown symbol or Class for :as will raise in 3.0
155
+ * Specifying :as with anything other than a type argument e.g. :bool, Float, [Date],
156
+ will not be supported in 3.0
157
+ * Use :from => :attr or :from => '@attribute_name' rather than the :attr
158
+ object declaration type
159
+ * Passing any type declaration outside the :as parameter is deprecated
160
+ * In 3.0, attributes ending in _on and _at will default to :as => Date and DateTime, respectively,
161
+ rather than :text
162
+ * Deprecated hash :attrs declaration syntax in favor of {:key => '@attr1', :value => '@attr2'}
163
+ * Deprecated hash {Type => 'name'} declaration syntax in favor of {:as => Type, :from => 'name}
164
+ * Deprecated String#to_utf and #to_latin.
165
+
166
+ * bug fixes
167
+
168
+ * xml_accessor now properly handles punctuation, such that the writer appears without '?' for boolean attributes
169
+ * text node contents are no longer truncated when '&' are present in the contents
170
+ * When using :as => Integer or Float, don't raise on missing element [James Healy]
171
+
172
+ == 2.4.3 (February 1, 2009)
173
+
174
+ * 1 bug fix
175
+
176
+ * Fix roxml to work in ruby 1.8.6, which has been broken since the removal of
177
+ extensions in version 2.4.1. Thanks Pat! [Pat Nakajima]
178
+
179
+ == 2.4.2 (January 31, 2009)
180
+
181
+ * 1 major enhancement
182
+
183
+ * xml_namespace for declaring Class-level, inheritable default namespaces.
184
+
185
+ * 4 minor enhancements
186
+
187
+ * add :as => Time, DateTime, and Date support
188
+ * support Pathname, IO and URI objects as #from_xml arguments
189
+ * :as => :bool now supports all capitalizations of 'true', 'false', 'yes', 'no', as well as '1' and '0'
190
+ * For basic types (:as => Integer, Float, Date, &c.), interpret empty strings just
191
+ as missing elements (by returning nil), rather than raising. Raise behavior can be
192
+ accessed by supplying your own block or using the :required option.
193
+
194
+ * 3 bug fixes
195
+
196
+ * Arrays of attrs or elements :as => :bool weren't previously supported. An oversight.
197
+ * Don't apply xml_convention if name is explicitly set
198
+ * Protect xpath operators : and / from modification via String#camelcase & such
199
+
200
+ == 2.4.1 (January 28, 2009)
201
+
202
+ * 3 minor enhancements
203
+
204
+ * remove dependency on 'extensions' gem, as we weren't using it much and it
205
+ was causing problems for some
206
+ * deprecate the 'xml' declaration in favor of the more explicit 'xml_reference'
207
+ declaration. Reorder params to make for cleaner 3.0 transition.
208
+ * deprecate '#tag_name' in favor of 'self.class.tag_name', as it's a class-specific value
209
+
210
+ == 2.4.0 (January 15, 2009)
211
+
212
+ * 1 major enhancement
213
+
214
+ * Add xml_convention to enable easy defaulting to common naming formats, such as camel-case and
215
+ underscored [Ben Woosley]
216
+
217
+ * 6 minor enhancements
218
+
219
+ * Add :frozen option for freezing values on parse [Ben Woosley]
220
+ * Attempt to minimize node creation by better matching wrappers [Ben Woosley]
221
+ * Preserve hash values where a single key maps to multiple values, return them as an array rather
222
+ any single one of them at random (as in group_by rather than index_by) [Ben Woosley]
223
+ * Deprecate #xml_name? as it's only used for triggering the xml_name warning [Ben Woosley]
224
+ * REXML parser ignores whitespace, which doesn't matter to us anyway [Ben Woosley]
225
+ * xml_name is inherited by default [Ben Woosley]
226
+
227
+ * 2 bug fixes
228
+
229
+ * Don't detect objects which define their own empty? as being absent for the purposes
230
+ of :default and :required [Ben Woosley]
231
+ * Sub-objects pick up their parent's attributes, even if they're added after
232
+ the child's use [Ben Woosley]
233
+
234
+ == 2.3.2 (December 11, 2008)
235
+
236
+ * Fix that both false and nil values were excluded from to_xml output, when only nil values should be [Ben Woosley]
237
+
238
+ == 2.3.1 (December 9, 2008)
239
+
240
+ * Add missing dependencies to extensions/enumerable and Symbol.to_proc,
241
+ which are as-yet inexplicably pre-included on my system... [Ben Woosley, Per Melin]
242
+
243
+ == 2.3 (December 7, 2008)
244
+
245
+ * Fix a bug in the application of blocks to array types [Ben Woosley]
246
+
247
+ * Objects now inherit xml attributes from their parents, as they should [Ben Woosley, Per Melin]
248
+
249
+ * Add #xml_initialize, which is called at the end of #from_xml, after the xml attributes
250
+ are set. Deprecate the half-baked xml_construct in it's favor. [Ben Woosley]
251
+
252
+ * Fix a bug in the handling of empty Hash types [Ben Woosley]
253
+
254
+ * Implement automatic bool-ification when the accessor name ends with ?. [Ben Woosley]
255
+
256
+ * Add missing dependency ActiveSupport [Ben Woosley]
257
+
258
+ * Remove support for installing as a rails plugin [Ben Woosley]
259
+
260
+ * Fix a bug where xml_construct was using the refs' names rather than their accessor names for comparison [Ben Woosley]
261
+
262
+ * Significantly reduce our footprint by selectively including smaller parts of ActiveSupport and Extensions.
263
+ This avoids problems such as the conflict between ActiveSupport's #to_json and the JSON gem's #to_json.
264
+ Thanks to Per Melin for reporting this problem. [Ben Woosley]
265
+
266
+ * Rationalize sub-element xml naming by enforcing the following precedence for the containing xml of an object:
267
+ :from of parent, xml_name of child, parent's accessor name. The previous fallback did not include xml_name.
268
+ This new behavior is more consistent, explicit, predictable, and DRY, but it is a breaking change, so a warning
269
+ is printed to alert others of this behavior change. ROXML::SILENCE_XML_NAME_WARNING may be used to deactivate this
270
+ warning. [Ben Woosley, James W. Thompson, Delynn Berry]
271
+
272
+ == 2.2 (November 2, 2008)
273
+
274
+ * fix gem dependencies [James Healy]
275
+
276
+ * Add block shorthands for Float and Integer, which precede the block argume if present [Ben Woosley]
277
+
278
+ * Add :required option to throw on absence [Ben Woosley]
279
+
280
+ * Deprecate the non-specific #parse in favor of #from_xml [Ben Woosley]
281
+
282
+ * Fix a bug whereby the default value was carrying over information from one object to another [James Healy, Ben Woosley]
283
+
284
+ * Fix support for :in on :attr elements [Ben Woosley]
285
+
286
+ * Deprecate Array#to_h in favor of Array#to_hash [Ben Woosley]
287
+
288
+ * Deprecate Object#to_latin and Object#to_utf in favor of the same methods on String [Ben Woosley]
289
+
290
+ == 2.1 (October 3, 2008)
291
+
292
+ * rake test now uses the default parser selection [Ben Woosley]
293
+
294
+ * Added rcov code coverage for tests [Anders Engström]
295
+
296
+ * Accommodate that libxml requires you to name the default namespace when available [Ben Woosley]
297
+
298
+ * Enable optional selection of a parser through the early definition of ROXML::XML_PARSER
299
+ [Ben Woosley]
300
+
301
+ * Enable fallback to the REXML parser if LibXML is unavailable [Ben Woosley]
302
+
303
+ == 2.0 (September 20, 2008)
304
+
305
+ * :text_content becomes simply :content, and is joined by :name [Ben Woosley]
306
+
307
+ * Allow hash mapping from node names and contents: [Ben Woosley]
308
+
309
+ xml_reader :name, {:key => :name,
310
+ :value => :content}, :in => 'container'
311
+
312
+ * Allow supplying a default via the :else option [Ben Woosley]
313
+
314
+ * Allow hash mapping of text and attr elements: [Ben Woosley]
315
+
316
+ xml_reader :name, {:key => {:text => 'key_name'},
317
+ :value => {:attr => 'attr_name'}}, :in => 'container'
318
+
319
+ * Allow 'xml_reader :name, [Type]' as an alternative to 'xml_reader :name, Type, :as => :array'
320
+ [Ben Woosley]
321
+
322
+ * Allow attaching a block for manipulating a value on fetch: [Ben Woosley]
323
+
324
+ xml_accessor :count, :attr => 'my_int' do |val|
325
+ Integer(val)
326
+ end
327
+
328
+ * Collapse xml_attr, xml_text and xml_object into a single api: xml, patterned after the standard
329
+ attr, and offer xml_reader and xml_accessor as well. Remove the :readonly arg in the process
330
+ [Ben Woosley]
331
+
332
+ * Attach string extensions (#to_latin, #to_utf) to Object rather than String, so we don't have to
333
+ call #to_s first every time [Ben Woosley]
334
+
335
+ * Allow a ROXML object to call its constructor on initialization with the xml_construct function
336
+ [Ben Woosley]
337
+
338
+ * Use symbols (e.g. :text_content) rather than TAG_CONSTANTS (e.g. TEXT_CONTENT) for readability
339
+ [Ben Woosley]
340
+
341
+ * Use named arguments (e.g. :as, :in) rather than positional for clarity,
342
+ position-independence, and invisible exclusion [Ben Woosley]
343
+
344
+ * Split out rails_plugin_package_task_gem [Ben Woosley]
345
+
346
+ * Increase testing significantly, particularly on new functionality & to_xml [Ben Woosley]
347
+
348
+ == 1.2 (October 10, 2007)
349
+
350
+ * Fix a bug such that the TEXT_CONTENT tag is no longer also READ_ONLY [Russ Olsen]
351
+
352
+ == 1.1 (September 24, 2006)
353
+
354
+ * Initial design & development [Zak Mandhro & Anders Engstrom]
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2004-2009 Ben Woosley, Zak Mandhro and Anders Engstrom
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,186 @@
1
+ ROXML Ruby Object to XML mapping library.
2
+
3
+ For more information visit:
4
+
5
+ http://rdoc.info/projects/Empact/roxml
6
+ http://empact.github.com/roxml/
7
+ http://rubyforge.org/projects/roxml/
8
+
9
+ Please submit bugs here:
10
+
11
+ http://github.com/Empact/roxml/issues
12
+
13
+ =Quick Start Guide
14
+
15
+ This is a short usage example. See ROXML::ClassMethods::Declarations and packaged test cases for more information.
16
+
17
+ ==Basic Mapping
18
+
19
+ Consider an XML document representing a Library containing a number of Books. You
20
+ can map this structure to Ruby classes that provide addition useful behavior. With
21
+ ROXML, you can annotate the Ruby classes as follows:
22
+
23
+ class Book
24
+ include ROXML
25
+
26
+ xml_accessor :isbn, :from => "@ISBN" # attribute with name 'ISBN'
27
+ xml_accessor :title
28
+ xml_accessor :description, :cdata => true # text node with cdata protection
29
+ xml_accessor :author
30
+ end
31
+
32
+ class Library
33
+ include ROXML
34
+
35
+ xml_accessor :name, :from => "NAME", :cdata => true
36
+ xml_accessor :books, :as => [Book] # by default roxml searches for books for in <book> child nodes, then, if none are present, in ./books/book children
37
+ end
38
+
39
+ To create a library and put a number of books in it we could run the following code:
40
+
41
+ book = Book.new
42
+ book.isbn = "0201710897"
43
+ book.title = "The PickAxe"
44
+ book.description = "Best Ruby book out there!"
45
+ book.author = "David Thomas, Andrew Hunt, Dave Thomas"
46
+
47
+ lib = Library.new
48
+ lib.name = "Favorite Books"
49
+ lib.books = [book]
50
+
51
+ To save this information to an XML file:
52
+
53
+ doc = Nokogiri::XML::Document.new
54
+ doc.root = lib.to_xml
55
+ open("library.xml", 'w') do |file|
56
+ file << doc.serialize
57
+ end
58
+
59
+ or
60
+
61
+ doc = LibXML::XML::Document.new
62
+ doc.root = lib.to_xml
63
+ doc.save("library.xml")
64
+
65
+ To later populate the library object from the XML file:
66
+
67
+ lib = Library.from_xml(File.read("library.xml"))
68
+
69
+ Similarly, to do a one-to-one mapping between XML objects, such as book and publisher,
70
+ you would add a reference to another ROXML class. For example:
71
+
72
+ <book isbn="0974514055">
73
+ <title>Programming Ruby - 2nd Edition</title>
74
+ <description>Second edition of the great book.</description>
75
+ <publisher>
76
+ <name>Pragmatic Bookshelf</name>
77
+ </publisher>
78
+ </book>
79
+
80
+ can be mapped using the following code:
81
+
82
+ class Publisher
83
+ include ROXML
84
+
85
+ xml_accessor :name
86
+
87
+ # other important functionality
88
+ end
89
+
90
+ class BookWithPublisher
91
+ include ROXML
92
+
93
+ xml_name 'book'
94
+ xml_reader :publisher, :as => Publisher
95
+
96
+ # or, alternatively, if no class is needed to hang functionality on:
97
+ # xml_reader :publisher, :from => 'name', :in => 'publisher'
98
+ end
99
+
100
+ Note: In the above example, _xml_name_ annotation tells ROXML to set the element
101
+ name to "book" for mapping to XML. The default is XML element name is the class name in lowercase; "bookwithpublisher"
102
+ in this case.
103
+
104
+ === Namespace Support
105
+
106
+ Namespaced nodes are supported via the xml_namespace and xml_namespaces declarations and the :from and :namespace attr options. See spec/xml/namespace_spec.rb for usage.
107
+
108
+ Note that ROXML does not currently support outputting namespaced nodes. This is planned for a future version.
109
+
110
+ == Manipulation
111
+
112
+ Extending the above examples, say you want to parse a book's page count and have it available as an Integer.
113
+ In such a case, you can extend any object with a block to manipulate it's value at parse time. For example:
114
+
115
+ class Dog
116
+ include ROXML
117
+
118
+ xml_reader(:age, :from => '@human_years', :as => Integer) {|years| years * 7 }
119
+ end
120
+
121
+ The result of the block above is stored, rather than the actual value parsed from the document.
122
+
123
+ == Construction
124
+
125
+ Object life-cycle is as follows: .from_xml is called with a first argument representing the xml
126
+ in file, string, or path form, and with optional initialization_args following.
127
+
128
+ Firt .new and thus #initialize, is called with those same initialization_args, or no args if none
129
+ are present. Then the object is populated with the attribute values from xml. Then the
130
+ #after_parse callback is called, with no arguments.
131
+
132
+ In #after_parse you can ensure that your object initialization is complete, including initialization which
133
+ requires more than one variable in concert.
134
+
135
+ E.g.:
136
+
137
+ class Measurement
138
+ include ROXML
139
+
140
+ xml_reader :units, :from => :attr
141
+ xml_reader :value, :from => :content
142
+
143
+ def initialize(value = 0, units = 'meters')
144
+ to_metric
145
+ end
146
+
147
+ private
148
+ def after_parse
149
+ # xml attributes of self are already valid
150
+ to_metric
151
+ end
152
+
153
+ def to_metric
154
+ # translate units & value into metric, for example
155
+ end
156
+ end
157
+
158
+ One important use of this approach is to make ROXML object which may or may not include an xml backing,
159
+ which may be used via _new_ construction as well as _from_xml_ construction.
160
+
161
+ == Selecting a parser
162
+
163
+ By default, ROXML will use Nokogiri if it is available, followed by LibXML. If you'd like to
164
+ explicitly require one or the other, you may do the following:
165
+
166
+ module ROXML
167
+ XML_PARSER = 'nokogiri' # or 'libxml'
168
+ end
169
+ require 'roxml'
170
+
171
+ For more information on available annotations, see ROXML::ClassMethods::Declarations
172
+
173
+ == Note on Patches/Pull Requests
174
+
175
+ * Fork the project.
176
+ * Make your feature addition or bug fix.
177
+ * Add specs for it. This is important so I don't break it in a
178
+ future version unintentionally.
179
+ * Commit, do not mess with rakefile, version, or history.
180
+ (if you want to have your own version, that is fine but
181
+ bump version in a commit by itself I can ignore when I pull)
182
+ * Send me a pull request. Bonus points for topic branches.
183
+
184
+ == Copyright
185
+
186
+ Copyright (c) 2004-2009 Ben Woosley, Zak Mandhro and Anders Engstrom. See LICENSE for details.