representable 0.0.1.alpha1 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. data/README.rdoc +58 -153
  2. data/lib/representable.rb +18 -42
  3. data/lib/representable/bindings/json_bindings.rb +69 -0
  4. data/lib/representable/bindings/xml_bindings.rb +152 -0
  5. data/lib/representable/definition.rb +1 -12
  6. data/lib/representable/json.rb +66 -0
  7. data/lib/representable/version.rb +1 -1
  8. data/lib/representable/xml.rb +32 -38
  9. data/representable.gemspec +3 -2
  10. data/test/bindings_test.rb +110 -0
  11. data/test/json_test.rb +130 -0
  12. data/test/{roxml_test.rb → representable_test.rb} +28 -9
  13. data/test/test_helper.rb +2 -0
  14. data/test/xml_test.rb +192 -0
  15. metadata +32 -105
  16. data/History.txt +0 -354
  17. data/TODO +0 -37
  18. data/VERSION +0 -1
  19. data/examples/amazon.rb +0 -35
  20. data/examples/current_weather.rb +0 -27
  21. data/examples/dashed_elements.rb +0 -20
  22. data/examples/library.rb +0 -40
  23. data/examples/posts.rb +0 -27
  24. data/examples/rails.rb +0 -70
  25. data/examples/twitter.rb +0 -37
  26. data/examples/xml/active_record.xml +0 -70
  27. data/examples/xml/amazon.xml +0 -133
  28. data/examples/xml/current_weather.xml +0 -89
  29. data/examples/xml/dashed_elements.xml +0 -52
  30. data/examples/xml/posts.xml +0 -23
  31. data/examples/xml/twitter.xml +0 -422
  32. data/lib/representable/references.rb +0 -153
  33. data/spec/definition_spec.rb +0 -495
  34. data/spec/examples/active_record_spec.rb +0 -41
  35. data/spec/examples/amazon_spec.rb +0 -54
  36. data/spec/examples/current_weather_spec.rb +0 -37
  37. data/spec/examples/dashed_elements_spec.rb +0 -20
  38. data/spec/examples/library_spec.rb +0 -46
  39. data/spec/examples/post_spec.rb +0 -24
  40. data/spec/examples/twitter_spec.rb +0 -32
  41. data/spec/roxml_integration_test.rb +0 -289
  42. data/spec/roxml_spec.rb +0 -372
  43. data/spec/shared_specs.rb +0 -15
  44. data/spec/spec_helper.rb +0 -5
  45. data/spec/support/libxml.rb +0 -3
  46. data/spec/support/nokogiri.rb +0 -3
  47. data/spec/xml/array_spec.rb +0 -36
  48. data/spec/xml/attributes_spec.rb +0 -71
  49. data/spec/xml/encoding_spec.rb +0 -53
  50. data/spec/xml/namespace_spec.rb +0 -270
  51. data/spec/xml/namespaces_spec.rb +0 -67
  52. data/spec/xml/object_spec.rb +0 -82
  53. data/spec/xml/parser_spec.rb +0 -21
  54. data/spec/xml/text_spec.rb +0 -71
  55. data/test/fixtures/book_malformed.xml +0 -5
  56. data/test/fixtures/book_pair.xml +0 -8
  57. data/test/fixtures/book_text_with_attribute.xml +0 -5
  58. data/test/fixtures/book_valid.xml +0 -5
  59. data/test/fixtures/book_with_authors.xml +0 -7
  60. data/test/fixtures/book_with_contributions.xml +0 -9
  61. data/test/fixtures/book_with_contributors.xml +0 -7
  62. data/test/fixtures/book_with_contributors_attrs.xml +0 -7
  63. data/test/fixtures/book_with_default_namespace.xml +0 -9
  64. data/test/fixtures/book_with_depth.xml +0 -6
  65. data/test/fixtures/book_with_octal_pages.xml +0 -4
  66. data/test/fixtures/book_with_publisher.xml +0 -7
  67. data/test/fixtures/book_with_wrapped_attr.xml +0 -3
  68. data/test/fixtures/dictionary_of_attr_name_clashes.xml +0 -8
  69. data/test/fixtures/dictionary_of_attrs.xml +0 -6
  70. data/test/fixtures/dictionary_of_guarded_names.xml +0 -6
  71. data/test/fixtures/dictionary_of_mixeds.xml +0 -4
  72. data/test/fixtures/dictionary_of_name_clashes.xml +0 -10
  73. data/test/fixtures/dictionary_of_names.xml +0 -4
  74. data/test/fixtures/dictionary_of_texts.xml +0 -10
  75. data/test/fixtures/library.xml +0 -30
  76. data/test/fixtures/library_uppercase.xml +0 -30
  77. data/test/fixtures/muffins.xml +0 -3
  78. data/test/fixtures/nameless_ageless_youth.xml +0 -2
  79. data/test/fixtures/node_with_attr_name_conflicts.xml +0 -1
  80. data/test/fixtures/node_with_name_conflicts.xml +0 -4
  81. data/test/fixtures/numerology.xml +0 -4
  82. data/test/fixtures/person.xml +0 -1
  83. data/test/fixtures/person_with_guarded_mothers.xml +0 -13
  84. data/test/fixtures/person_with_mothers.xml +0 -10
  85. data/test/mocks/dictionaries.rb +0 -57
  86. data/test/mocks/mocks.rb +0 -279
  87. data/test/support/fixtures.rb +0 -11
  88. data/test/unit/definition_test.rb +0 -235
  89. data/test/unit/deprecations_test.rb +0 -24
  90. data/test/unit/to_xml_test.rb +0 -81
  91. data/test/unit/xml_attribute_test.rb +0 -39
  92. data/test/unit/xml_block_test.rb +0 -81
  93. data/test/unit/xml_bool_test.rb +0 -122
  94. data/test/unit/xml_convention_test.rb +0 -150
  95. data/test/unit/xml_hash_test.rb +0 -115
  96. data/test/unit/xml_initialize_test.rb +0 -49
  97. data/test/unit/xml_name_test.rb +0 -141
  98. data/test/unit/xml_namespace_test.rb +0 -31
  99. data/test/unit/xml_object_test.rb +0 -206
  100. data/test/unit/xml_required_test.rb +0 -94
  101. data/test/unit/xml_text_test.rb +0 -71
  102. data/website/index.html +0 -98
@@ -1,186 +1,91 @@
1
- ROXML Ruby Object to XML mapping library.
1
+ = Representable
2
2
 
3
- For more information visit:
3
+ <em>Maps representation documents from and to Ruby objects.</em>
4
4
 
5
- http://rdoc.info/projects/Empact/roxml
6
- http://empact.github.com/roxml/
7
- http://rubyforge.org/projects/roxml/
8
5
 
9
- Please submit bugs here:
6
+ == Introduction
10
7
 
11
- http://github.com/Empact/roxml/issues
8
+ _Representable_ maps fragments in documents to attributes in Ruby objects and back. It allows parsing representations and gives an object-oriented interface to the document. But that's only half of it! Representable can also render documents from an object instance.
12
9
 
13
- =Quick Start Guide
10
+ This is especially helpful when implementing REST services and clients and keeps your representation knowledge in one place.
14
11
 
15
- This is a short usage example. See ROXML::ClassMethods::Declarations and packaged test cases for more information.
12
+ == Example
16
13
 
17
- ==Basic Mapping
14
+ When writing a REST service you'd have to parse and extract data from an incoming representation document manually. Given the following XML document which represents an order.
18
15
 
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:
16
+ <order>
17
+ <id>1</id>
18
+ <item>
19
+ <name>Chocolate Cookie</name>
20
+ </item>
21
+ <item>
22
+ <name>Vanilla Muffin</name>
23
+ </item>
24
+ </order>
22
25
 
23
- class Book
24
- include ROXML
26
+ Now, parsing manually starts simple but gets complex soon. In the end, you have a nested hash data structure. Try this with Representable.
25
27
 
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
28
+ class Order
29
+ include Representable::XML
30
+
31
+ representable_property :id
32
+ representable_collection :items, :tag => :item, :as => Item
30
33
  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
34
+
35
+ class Item
36
+ include Representable::XML
37
+
38
+ representable_property :name
88
39
  end
40
+
41
+ == Consuming Representations
89
42
 
90
- class BookWithPublisher
91
- include ROXML
43
+ Representable gives you easy access for consuming incoming representation documents. It maps the appropriate content to objects' attributes.
92
44
 
93
- xml_name 'book'
94
- xml_reader :publisher, :as => Publisher
45
+ @order = Order.from_xml(xml)
46
+ @order.id # => "1"
47
+ @order.items # => [<item>, <item>]
48
+ @order.items.first.name # => "Chocolate Cookie"
95
49
 
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
50
 
110
- == Manipulation
51
+ == Extendability
111
52
 
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:
53
+ The cool thing with object-oriented representations is: you can treat them just like any other object in Ruby and extend them dynamically - which is impossible with plain hashes.
114
54
 
115
- class Dog
116
- include ROXML
117
-
118
- xml_reader(:age, :from => '@human_years', :as => Integer) {|years| years * 7 }
55
+ class Order
56
+ # ...
57
+
58
+ def sort_items
59
+ items.sort! do |a,b|
60
+ a.name <=> b.name
61
+ end
62
+ end
119
63
  end
120
64
 
121
- The result of the block above is stored, rather than the actual value parsed from the document.
122
65
 
123
- == Construction
66
+ == Generating Representations
124
67
 
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.
68
+ Usually you have two places that share knowledge about a representation and its syntax and semantics: the parser <em>and</em> the renderer. With Representable, this is kept in one place.
127
69
 
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.
70
+ @order.to_xml # => "<order><id>1</id>...</order>"
71
+
72
+ You can also render a representation from a newly created object.
131
73
 
132
- In #after_parse you can ensure that your object initialization is complete, including initialization which
133
- requires more than one variable in concert.
74
+ Order.new(:id => 2, :items => [candy]).to_xml
134
75
 
135
- E.g.:
136
76
 
137
- class Measurement
138
- include ROXML
77
+ Representable makes working with representations extremely easy and testable.
139
78
 
140
- xml_reader :units, :from => :attr
141
- xml_reader :value, :from => :content
79
+ == More
142
80
 
143
- def initialize(value = 0, units = 'meters')
144
- to_metric
145
- end
81
+ Representable was written with REST representations in mind. However, it is a generic module for working with documents. If you do consider using it for a REST project, check out the {Roar framework}[http://github.com/apotonick/roar], which comes with representers, built-in hypermedia support and more. It internally uses Representable and streamlines the process for building hypermedia-driven REST applications.
146
82
 
147
- private
148
- def after_parse
149
- # xml attributes of self are already valid
150
- to_metric
151
- end
83
+ Representable comes with parser and renderer for XML and JSON and can easily be extended (Warning: internal API still changing).
152
84
 
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
85
 
184
86
  == Copyright
185
87
 
186
- Copyright (c) 2004-2009 Ben Woosley, Zak Mandhro and Anders Engstrom. See LICENSE for details.
88
+ Representable is a simplified fork of the ROXML gem. Big thanks to Ben Woosley for his work.
89
+
90
+ Copyright (c) 2011 Nick Sutterer <apotonick@gmail.com>
91
+ Copyright (c) 2004-2009 Ben Woosley, Zak Mandhro and Anders Engstrom.
@@ -1,7 +1,5 @@
1
1
  require 'active_support'
2
2
  require 'active_support/core_ext/module/delegation'
3
- require 'active_support/core_ext/array/extract_options'
4
- require 'active_support/core_ext/string/starts_ends_with'
5
3
  require 'active_support/core_ext/string/inflections.rb'
6
4
  require 'active_support/core_ext/hash/reverse_merge.rb'
7
5
 
@@ -10,32 +8,19 @@ require 'hooks/inheritable_attribute'
10
8
 
11
9
  require 'representable/definition'
12
10
  require 'representable/nokogiri_extensions'
13
- require 'representable/references'
14
11
 
15
- require 'representable/xml' # TODO: do that dynamically.
12
+ #require 'representable/xml' # TODO: do that dynamically.
16
13
 
17
14
  module Representable
18
- VERSION = '3.1.5'
19
-
20
-
21
15
  def self.included(base)
22
16
  base.class_eval do
23
17
  extend ClassMethods::Accessors, ClassMethods::Declarations
24
-
25
-
26
-
27
- attr_accessor :roxml_references
28
18
 
29
19
  extend Hooks::InheritableAttribute
30
20
  inheritable_attr :representable_attrs
31
21
  self.representable_attrs = []
32
22
 
33
23
  inheritable_attr :explicit_representation_name # FIXME: move to Accessors.
34
-
35
-
36
- extend Xml::Declarations # DISCUSS: do that dynamically?
37
- extend Xml::ClassMethods # DISCUSS: do that dynamically?
38
- include Xml::InstanceMethods # DISCUSS: do that dynamically?
39
24
  end
40
25
  end
41
26
 
@@ -204,39 +189,30 @@ module Representable
204
189
  # [:cdata] true for values which should be input from or output as cdata elements
205
190
  # [:to_xml] this proc is applied to the attributes value outputting the instance via #to_xml
206
191
  #
207
- def representable_attr(*syms, &block)
208
- opts = syms.extract_options!
209
- syms.map do |sym|
210
- definition_class.new(sym, opts, &block).tap do |attr|
211
- representable_attrs << attr
212
- end
213
- end
192
+ def representable_property(*args) # TODO: make it accept 1-n props.
193
+ attr = representable_attr(*args)
194
+ add_reader(attr)
195
+ attr_writer(attr.accessor)
214
196
  end
215
-
216
- # Declares a read-only xml reference. See xml_attr for details.
217
- #
218
- # Note that while xml_reader does not create a setter for this attribute,
219
- # its value can be modified indirectly via methods. For more complete
220
- # protection, consider the :frozen option.
221
- def representable_reader(*syms, &block)
222
- representable_attr(*syms, &block).each do |attr|
223
- add_reader(attr)
197
+
198
+ def representable_collection(name, options={})
199
+ options[:as] = [options[:as]].compact
200
+ representable_property(name, options)
201
+ end
202
+
203
+ private
204
+ def representable_attr(name, options={})
205
+ definition_class.new(name, options).tap do |attr|
206
+ representable_attrs << attr
224
207
  end
225
208
  end
226
-
227
- # Declares a writable xml reference. See xml_attr for details.
228
- #
229
- # Note that while xml_accessor does create a setter for this attribute,
230
- # you can use the :frozen option to prevent its value from being
231
- # modified indirectly via methods.
232
- def representable_accessor(*syms, &block)
209
+
210
+ def representable_reader(*syms, &block)
233
211
  representable_attr(*syms, &block).each do |attr|
234
212
  add_reader(attr)
235
- attr_writer(attr.accessor)
236
213
  end
237
214
  end
238
-
239
- private
215
+
240
216
  def add_reader(attr)
241
217
  define_method(attr.accessor) do
242
218
  instance_variable_get(attr.instance_variable_name)
@@ -0,0 +1,69 @@
1
+ module Representable
2
+ module JSON
3
+ class Binding
4
+ attr_reader :definition
5
+ delegate :required?, :array?, :accessor, :wrapper, :name, :to => :definition
6
+
7
+ def initialize(definition)
8
+ @definition = definition
9
+ end
10
+
11
+ def value_in(hash)
12
+ value_from_hash(hash) or default
13
+ end
14
+
15
+ private
16
+ def default
17
+ ""
18
+ end
19
+
20
+ def collect_for(hash)
21
+ nodes = hash[name.to_s] or return
22
+ nodes = [nodes] unless nodes.is_a?(Array)
23
+
24
+ vals = nodes.collect { |node| yield node }
25
+
26
+ array? ? vals : vals.first
27
+ end
28
+ end
29
+
30
+ # Represents plain key-value.
31
+ class TextBinding < Binding
32
+ def update_json(hash, value)
33
+ hash[name] = value
34
+ end
35
+
36
+ private
37
+ def value_from_hash(hash)
38
+ collect_for(hash) do |value|
39
+ value
40
+ end
41
+ end
42
+ end
43
+
44
+ # Represents a tag with object binding.
45
+ class ObjectBinding < Binding
46
+ delegate :sought_type, :to => :definition
47
+
48
+ def update_json(hash, value)
49
+ if array?
50
+ hash.merge! ({accessor => value.collect {|v| v.to_json(:wrap => false)}}) # hier name=> wech.
51
+ else
52
+ hash.merge! value.to_json
53
+ end
54
+ end
55
+
56
+ private
57
+ def default
58
+ []
59
+ end
60
+
61
+ def value_from_hash(xml)
62
+ collect_for(xml) do |node|
63
+ sought_type.from_json(node, :wrap => false) # hier name=> wech.
64
+ end
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,152 @@
1
+ module Representable
2
+ module XML
3
+ class Binding
4
+ attr_reader :definition
5
+ delegate :required?, :array?, :accessor, :wrapper, :name, :to => :definition
6
+
7
+ def initialize(definition)
8
+ @definition = definition
9
+ end
10
+
11
+ def value_in(xml)
12
+ xml = Nokogiri::XML::Node.from(xml) or return default
13
+
14
+ value_from_node(xml) or default
15
+ end
16
+
17
+ private
18
+ def default
19
+ ""
20
+ end
21
+
22
+ def xpath
23
+ name
24
+ end
25
+
26
+ def wrap(xml, opts = {:always_create => false})
27
+ wrap_with = @auto_vals ? auto_wrapper : wrapper
28
+
29
+ return xml if !wrap_with || xml.name == wrap_with
30
+ if !opts[:always_create] && (child = xml.children.find {|c| c.name == wrap_with })
31
+ return child
32
+ end
33
+ xml.add_node(wrap_with.to_s)
34
+ end
35
+
36
+ def collect_for(xml)
37
+ nodes = xml.search("./#{xpath}")
38
+ vals = nodes.collect { |node| yield node }
39
+
40
+ array? ? vals : vals.first
41
+ end
42
+ end
43
+
44
+
45
+ # Represents a tag attribute.
46
+ class AttributeBinding < Binding
47
+ def update_xml(xml, values)
48
+ wrap(xml).tap do |xml|
49
+ xml[name] = values.to_s
50
+ end
51
+ end
52
+
53
+ private
54
+ def value_from_node(xml)
55
+ xml[name]
56
+ end
57
+ end
58
+
59
+
60
+ # Represents text content in a tag. # FIXME: is this tested???
61
+ class TextBinding < Binding
62
+ delegate :cdata?, :content?, :name?, :to => :definition
63
+
64
+ # Updates the text in the given _xml_ block to
65
+ # the _value_ provided.
66
+ def update_xml(xml, value)
67
+ wrap(xml).tap do |xml|
68
+ if content?
69
+ add(xml, value)
70
+ elsif name?
71
+ xml.name = value
72
+ elsif array?
73
+ value.each do |v|
74
+ add(xml.add_node(name), v)
75
+ end
76
+ else
77
+ add(xml.add_node(name), value)
78
+ end
79
+ end
80
+ end
81
+
82
+ private
83
+ def value_from_node(xml)
84
+ collect_for(xml) do |node|
85
+ node.content
86
+ end
87
+ end
88
+
89
+ def add(dest, value)
90
+ if cdata?
91
+ dest.add_child(Nokogiri::XML::CDATA.new(dest.document, content))
92
+ else
93
+ dest.content = value.to_s
94
+ end
95
+ end
96
+ end
97
+
98
+
99
+ class NamespaceBinding < Binding
100
+ private
101
+ def value_from_node(xml)
102
+ xml.namespace.prefix
103
+ end
104
+ end
105
+
106
+ # Represents a tag with object binding.
107
+ class ObjectBinding < Binding
108
+ delegate :sought_type, :to => :definition
109
+
110
+ # Adds the ref's markup to +xml+.
111
+ def update_xml(xml, value)
112
+ wrap(xml).tap do |xml|
113
+ if array?
114
+ update_xml_for_collection(xml, value)
115
+ else
116
+ update_xml_for_entity(xml, value)
117
+ end
118
+ end
119
+ end
120
+
121
+ private
122
+ def default
123
+ []
124
+ end
125
+
126
+ def serialize(object)
127
+ object.to_xml
128
+ end
129
+
130
+ def deserialize(node_class, xml)
131
+ node_class.from_xml(xml)
132
+ end
133
+
134
+ # Deserializes the ref's element from +xml+.
135
+ def value_from_node(xml)
136
+ collect_for(xml) do |node|
137
+ deserialize(sought_type, node)
138
+ end
139
+ end
140
+
141
+ def update_xml_for_collection(xml, collection)
142
+ collection.each do |item|
143
+ update_xml_for_entity(xml, item)
144
+ end
145
+ end
146
+
147
+ def update_xml_for_entity(xml, entity)
148
+ xml.add_child(serialize(entity))
149
+ end
150
+ end
151
+ end
152
+ end