ROXML 3.0.0

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