nokogiri-happymapper 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -5
  3. data/README.md +85 -69
  4. data/lib/happymapper.rb +27 -22
  5. data/lib/happymapper/anonymous_mapper.rb +35 -30
  6. data/lib/happymapper/item.rb +1 -1
  7. data/lib/happymapper/supported_types.rb +2 -7
  8. data/lib/happymapper/version.rb +1 -1
  9. data/spec/features/after_parse_callbacks_spec.rb +29 -0
  10. data/spec/{attribute_default_value_spec.rb → features/attribute_default_value_spec.rb} +3 -3
  11. data/spec/{attributes_spec.rb → features/attributes_spec.rb} +6 -6
  12. data/spec/{has_many_empty_array_spec.rb → features/has_many_empty_array_spec.rb} +1 -1
  13. data/spec/{ignay_spec.rb → features/ignay_spec.rb} +10 -19
  14. data/spec/{inheritance_spec.rb → features/inheritance_spec.rb} +1 -1
  15. data/spec/{mixed_namespaces_spec.rb → features/mixed_namespaces_spec.rb} +17 -17
  16. data/spec/{parse_with_object_to_update_spec.rb → features/parse_with_object_to_update_spec.rb} +0 -0
  17. data/spec/features/same_tag_different_meaning_spec.rb +44 -0
  18. data/spec/{to_xml_spec.rb → features/to_xml_spec.rb} +2 -2
  19. data/spec/{to_xml_with_namespaces_spec.rb → features/to_xml_with_namespaces_spec.rb} +0 -0
  20. data/spec/{wilcard_tag_name_spec.rb → features/wildcard_tag_name_spec.rb} +5 -5
  21. data/spec/{wrap_spec.rb → features/wrap_spec.rb} +4 -4
  22. data/spec/{xpath_spec.rb → features/xpath_spec.rb} +17 -23
  23. data/spec/happymapper/anonymous_mapper_spec.rb +158 -0
  24. data/spec/happymapper/element_spec.rb +1 -1
  25. data/spec/happymapper/item_spec.rb +75 -45
  26. data/spec/happymapper_spec.rb +120 -125
  27. metadata +32 -28
  28. data/spec/happymapper_parse_spec.rb +0 -131
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 75fd5c49ca6f39f746d0570dcf4b5cbcc53c983aeeb1d5198a4bb8108701fc46
4
- data.tar.gz: 5e9106990b90654f2e93977381b3cd4a3901f79cdda533c2f2d6b452e67e95c8
3
+ metadata.gz: 20c74c3600aeae595d9851fdc864364df4af72d3b5ea1257cb7323a5f4032439
4
+ data.tar.gz: b1fe72afe90bebc42fe52130fe1d4fb6681815f9c9e79a9f8dccabf93f5e9003
5
5
  SHA512:
6
- metadata.gz: 5bceafdb34f883e0980e914ff30bea0774436e9e105c1d89a25128f0e4bb7a1ddb17278bc971ee94578a83a399af4061ddc73813fc0edf46b5d5b35c8e6e48a0
7
- data.tar.gz: 956560556fa3dbf7f111f61b4997645cc168f05ac8659c4f68fca2e30db8ab7e2a400ea18c6e13a35aeed81f4626d37e467e8fab116490945dd77269cfc1b4b0
6
+ metadata.gz: ab001b07e41193a760a37d87600f2020310aa4f753b1bdcca2fad7251a5ac50346267c61cce18a5d5fc20f3ec683a3f8b67a305de2183a5fb8b3187731f8eab8
7
+ data.tar.gz: db0cb626e8d21eaf4b388bdb414165dbcb6b63ab3d6c6c3f61077255983fa3ec833e10e223ad429a9162d669d0ede349010c9b8c123ad231e34b4949ee2c4288
@@ -1,16 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.0 / 2018-08-28
4
+
5
+ ### Breaking Changes
6
+
7
+ * Ensure child elements only parse direct child nodes when parsing anonymously
8
+ ([#100](https://github.com/mvz/happymapper/pull/100))
9
+
10
+ ### Improvements
11
+
12
+ * Improve documentation
13
+ ([#99](https://github.com/mvz/happymapper/pull/99))
14
+
15
+ ### Bug fixes
16
+
17
+ * Handle repeated camel-cased elements as `has_many` when parsing anonymously
18
+ ([#101](https://github.com/mvz/happymapper/pull/101))
19
+ * Avoid creating extra elements named `text` when parsing anonymously
20
+ ([#98](https://github.com/mvz/happymapper/pull/98))
21
+
3
22
  ## 0.7.0 / 2018-08-27
4
23
 
5
24
  ### Breaking Changes
6
25
 
7
- * Remove constant HappyMapper::DEFAULT_NS
26
+ * Remove constant `HappyMapper::DEFAULT_NS`
27
+ ([#78](https://github.com/mvz/happymapper/pull/78))
8
28
  * Drop support for Ruby 2.2 and below
29
+ ([#80](https://github.com/mvz/happymapper/pull/80))
9
30
 
10
31
  ### Improvements
11
32
 
12
33
  * Support Ruby 2.5
13
34
  * Always sort namespaces. This adds support for JRuby.
35
+ ([#84](https://github.com/mvz/happymapper/pull/84))
14
36
 
15
37
  ### Bug fixes
16
38
 
@@ -28,7 +50,7 @@
28
50
  * Prevent parsing of empty string for Date, DateTime (wushugene)
29
51
  * Rescue nil dates (sarsena)
30
52
  * Preserve XML value (benoist)
31
- * Restore after_parse callback support (codekitchen)
53
+ * Restore `after_parse` callback support (codekitchen)
32
54
  * Parse specific types before general types (Ivo Wever)
33
55
  * Higher priority for namespace on element declarations (Ivo Wever)
34
56
 
@@ -39,7 +61,7 @@
39
61
  ## 0.5.8 / 2013-10-12
40
62
 
41
63
  * Allow child elements to remove their parent's namespacing (dcarneiro)
42
- * has_many elements were returning nil because the tag name was being ignored (haarts)
64
+ * `has_many` elements were returning nil because the tag name was being ignored (haarts)
43
65
  * Subclassed happymapper classes are allowed to override elements (benoist)
44
66
  * Attributes on elements with dashes will properly created methods (alex-klepa)
45
67
  * 'Embedded' attributes break parsing when parent element is not present (geoffwa)
@@ -56,8 +78,8 @@
56
78
 
57
79
  ## 0.5.4/ 2012-09-25
58
80
 
59
- * the #wrap method allows you to better model xml content that is buried deep
60
- within the xml. This implementation addresses issues with calling #to_xml
81
+ * the `#wrap` method allows you to better model xml content that is buried deep
82
+ within the xml. This implementation addresses issues with calling `#to_xml`
61
83
  with content that was parsed from an xpath. (zrob)
62
84
 
63
85
  * Parent HappyMapper classes may dictate the name of the tag for the child
data/README.md CHANGED
@@ -41,13 +41,15 @@ Run Bundler to install the gem:
41
41
  Let's start with a simple example to get our feet wet. Here we have a simple
42
42
  example of XML that defines some address information:
43
43
 
44
- <address>
45
- <street>Milchstrasse</street>
46
- <housenumber>23</housenumber>
47
- <postcode>26131</postcode>
48
- <city>Oldenburg</city>
49
- <country code="de">Germany</country>
50
- </address>
44
+ ```xml
45
+ <address>
46
+ <street>Milchstrasse</street>
47
+ <housenumber>23</housenumber>
48
+ <postcode>26131</postcode>
49
+ <city>Oldenburg</city>
50
+ <country code="de">Germany</country>
51
+ </address>
52
+ ```
51
53
 
52
54
  Happymapper provides support for simple, zero configuration parsing as well as
53
55
  the ability to model the XML content in classes.
@@ -168,14 +170,16 @@ will do that work for us inside of parse.
168
170
  What if our address XML was a little different, perhaps we allowed multiple
169
171
  streets:
170
172
 
171
- <address>
172
- <street>Milchstrasse</street>
173
- <street>Another Street</street>
174
- <housenumber>23</housenumber>
175
- <postcode>26131</postcode>
176
- <city>Oldenburg</city>
177
- <country code="de">Germany</country>
178
- </address>
173
+ ```xml
174
+ <address>
175
+ <street>Milchstrasse</street>
176
+ <street>Another Street</street>
177
+ <housenumber>23</housenumber>
178
+ <postcode>26131</postcode>
179
+ <city>Oldenburg</city>
180
+ <country code="de">Germany</country>
181
+ </address>
182
+ ```
179
183
 
180
184
  Similar to `element` or `has_one`, the declaration for when you have multiple
181
185
  elements you simply use:
@@ -222,14 +226,16 @@ the instance variable `@streets` if we ever need to the values as an array.
222
226
 
223
227
  ### Attribute Mapping
224
228
 
225
- <address location='home'>
226
- <street>Milchstrasse</street>
227
- <street>Another Street</street>
228
- <housenumber>23</housenumber>
229
- <postcode>26131</postcode>
230
- <city>Oldenburg</city>
231
- <country code="de">Germany</country>
232
- </address>
229
+ ```xml
230
+ <address location='home'>
231
+ <street>Milchstrasse</street>
232
+ <street>Another Street</street>
233
+ <housenumber>23</housenumber>
234
+ <postcode>26131</postcode>
235
+ <city>Oldenburg</city>
236
+ <country code="de">Germany</country>
237
+ </address>
238
+ ```
233
239
 
234
240
  Attributes are absolutely the same as `element` or `has_many`
235
241
 
@@ -242,13 +248,16 @@ of the attribute.
242
248
 
243
249
  #### Attributes On Empty Child Elements
244
250
 
245
- <feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
246
- <id>tag:all-the-episodes.heroku.com,2005:/tv_shows</id>
247
- <link rel="alternate" type="text/html" href="http://all-the-episodes.heroku.com"/>
248
- <link rel="self" type="application/atom+xml" href="http://all-the-episodes.heroku.com/tv_shows.atom"/>
249
- <title>TV Shows</title>
250
- <updated>2011-07-10T06:52:27Z</updated>
251
- </feed>
251
+ ```xml
252
+ <feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
253
+ <id>tag:all-the-episodes.heroku.com,2005:/tv_shows</id>
254
+ <link rel="alternate" type="text/html" href="http://all-the-episodes.heroku.com"/>
255
+ <link rel="self" type="application/atom+xml"
256
+ href="http://all-the-episodes.heroku.com/tv_shows.atom"/>
257
+ <title>TV Shows</title>
258
+ <updated>2011-07-10T06:52:27Z</updated>
259
+ </feed>
260
+ ```
252
261
 
253
262
  In this case you would need to map an element to a new `Link` class just to
254
263
  access `<link>`s attributes, except that there is an alternate syntax. Instead
@@ -301,7 +310,8 @@ point we neglected it as we declared a `country` as being a `String`.
301
310
  <country code="de">Germany</country>
302
311
  </address>
303
312
 
304
- Well if we only going to parse country, on it's own, we would likely create a class mapping for it.
313
+ Well if we only going to parse country, on it's own, we would likely create a
314
+ class mapping for it.
305
315
 
306
316
  ```ruby
307
317
  class Country
@@ -318,7 +328,8 @@ We are utilizing an `attribute` declaration and a new declaration called `conten
318
328
 
319
329
  * `content` is used when you want the text contained within the element
320
330
 
321
- Awesome, now if we were to redeclare our `Address` class we would use our new `Country` class.
331
+ Awesome, now if we were to redeclare our `Address` class we would use our new
332
+ `Country` class.
322
333
 
323
334
  ```ruby
324
335
  class Address
@@ -361,19 +372,21 @@ are available when it comes time to parse you are golden.
361
372
  Getting to elements deep down within your XML can be a little more work if you
362
373
  did not have xpath support. Consider the following example:
363
374
 
364
- <media>
365
- <gallery>
366
- <title href="htttp://fishlovers.org/friends">Friends Who Like Fish</title>
367
- <picture>
368
- <name>Burtie Sanchez</name>
369
- <img>burtie01.png</img>
370
- </picture>
371
- </gallery>
372
- <picture>
373
- <name>Unsorted Photo</name>
374
- <img>bestfriends.png</img>
375
- </picture>
376
- </media>
375
+ ```xml
376
+ <media>
377
+ <gallery>
378
+ <title href="htttp://fishlovers.org/friends">Friends Who Like Fish</title>
379
+ <picture>
380
+ <name>Burtie Sanchez</name>
381
+ <img>burtie01.png</img>
382
+ </picture>
383
+ </gallery>
384
+ <picture>
385
+ <name>Unsorted Photo</name>
386
+ <img>bestfriends.png</img>
387
+ </picture>
388
+ </media>
389
+ ```
377
390
 
378
391
  You may want to map the sub-elements contained buried in the 'gallery' as top
379
392
  level items in the media. Traditionally you could use class composition to
@@ -484,24 +497,25 @@ opportunity to do some surgery and define our happymapper elements as well as
484
497
  any other methods that may rely on those instance variables that come along in
485
498
  the package.
486
499
 
487
-
488
500
  ### Filtering with XPATH (non-greedy)
489
501
 
490
502
  I ran into a case where I wanted to capture all the pictures that were directly
491
503
  under media, but not the ones contained within a gallery.
492
504
 
493
- <media>
494
- <gallery>
495
- <picture>
496
- <name>Burtie Sanchez</name>
497
- <img>burtie01.png</img>
498
- </picture>
499
- </gallery>
500
- <picture>
501
- <name>Unsorted Photo</name>
502
- <img>bestfriends.png</img>
503
- </picture>
504
- </media>
505
+ ```xml
506
+ <media>
507
+ <gallery>
508
+ <picture>
509
+ <name>Burtie Sanchez</name>
510
+ <img>burtie01.png</img>
511
+ </picture>
512
+ </gallery>
513
+ <picture>
514
+ <name>Unsorted Photo</name>
515
+ <img>bestfriends.png</img>
516
+ </picture>
517
+ </media>
518
+ ```
505
519
 
506
520
  The following `Media` class is where I started:
507
521
 
@@ -538,7 +552,6 @@ has_many :pictures, Picture, tag: 'picture', xpath: '.'
538
552
  `.` states that we are only interested in pictures that can be found directly
539
553
  under the current node. So when we parse again we will have only our one element.
540
554
 
541
-
542
555
  ### Namespaces
543
556
 
544
557
  Obviously your XML and these trivial examples are easy to map and parse because
@@ -588,15 +601,18 @@ declaration is important and that is when it has a different namespace than
588
601
 
589
602
  Imagine that our `country` actually belonged to a completely different namespace.
590
603
 
591
- <prefix:address location='home' xmlns:prefix="http://www.unicornland.com/prefix"
592
- xmlns:different="http://www.trollcountry.com/different">
593
- <prefix:street>Milchstrasse</prefix:street>
594
- <prefix:street>Another Street</prefix:street>
595
- <prefix:housenumber>23</prefix:housenumber>
596
- <prefix:postcode>26131</prefix:postcode>
597
- <prefix:city>Oldenburg</prefix:city>
598
- <different:country code="de">Germany</different:country>
599
- </prefix:address>
604
+ ```xml
605
+ <prefix:address location='home'
606
+ xmlns:prefix="http://www.unicornland.com/prefix"
607
+ xmlns:different="http://www.trollcountry.com/different">
608
+ <prefix:street>Milchstrasse</prefix:street>
609
+ <prefix:street>Another Street</prefix:street>
610
+ <prefix:housenumber>23</prefix:housenumber>
611
+ <prefix:postcode>26131</prefix:postcode>
612
+ <prefix:city>Oldenburg</prefix:city>
613
+ <different:country code="de">Germany</different:country>
614
+ </prefix:address>
615
+ ```
600
616
 
601
617
  Well we would need to specify that namespace:
602
618
 
@@ -606,7 +622,7 @@ element :country, Country, tag: 'country', namespace: 'different'
606
622
 
607
623
  With that we should be able to parse as we once did.
608
624
 
609
- ### Large Datasets (in_groups_of)
625
+ ### Large Datasets (`:in_groups_of`)
610
626
 
611
627
  When dealing with large sets of XML that simply cannot or should not be placed
612
628
  into memory the objects can be handled in groups through the `:in_groups_of`
@@ -10,7 +10,9 @@ module HappyMapper
10
10
  class Boolean; end
11
11
  class XmlContent; end
12
12
 
13
- extend AnonymousMapper
13
+ def self.parse(xml_content)
14
+ AnonymousMapper.new.parse(xml_content)
15
+ end
14
16
 
15
17
  def self.included(base)
16
18
  if base.superclass <= HappyMapper
@@ -282,15 +284,13 @@ module HappyMapper
282
284
  #
283
285
  # @param [Nokogiri::XML::Node,Nokogiri:XML::Document,String] xml the XML
284
286
  # contents to convert into Object.
285
- # @param [Hash] options additional information for parsing. :single => true
286
- # if requesting a single object, otherwise it defaults to retuning an
287
- # array of multiple items. :xpath information where to start the parsing
287
+ # @param [Hash] options additional information for parsing.
288
+ # :single => true if requesting a single object, otherwise it defaults
289
+ # to retuning an array of multiple items.
290
+ # :xpath information where to start the parsing
288
291
  # :namespace is the namespace to use for additional information.
289
292
  #
290
293
  def parse(xml, options = {})
291
- # create a local copy of the objects namespace value for this parse execution
292
- namespace = (@namespace if defined? @namespace)
293
-
294
294
  # Capture any provided namespaces and merge in any namespaces that have
295
295
  # been registered on the object.
296
296
  namespaces = options[:namespaces] || {}
@@ -323,15 +323,15 @@ module HappyMapper
323
323
  root = node.name == tag_name
324
324
  end
325
325
 
326
+ # If the :single option has been specified or we are at the root element
327
+ # then we are going to return a single element or nil if no nodes are found
328
+ single = root || options[:single]
329
+
326
330
  # if a namespace has been provided then set the current namespace to it
327
- # or set the default namespace to the one defined under 'xmlns'
328
- # or set the default namespace to the namespace that matches 'happymapper's
331
+ # or use the namespace provided by the class
332
+ # or use the 'xmlns' namespace if defined
329
333
 
330
- if options[:namespace]
331
- namespace = options[:namespace]
332
- elsif namespaces.has_key?('xmlns')
333
- namespace ||= 'xmlns'
334
- end
334
+ namespace = options[:namespace] || self.namespace || namespaces.key?('xmlns') && 'xmlns'
335
335
 
336
336
  # from the options grab any nodes present and if none are present then
337
337
  # perform the following to find the nodes for the given class
@@ -341,7 +341,7 @@ module HappyMapper
341
341
  end
342
342
 
343
343
  # Nothing matching found, we can go ahead and return
344
- return (options[:single] || root ? nil : []) if nodes.size == 0
344
+ return (single ? nil : []) if nodes.empty?
345
345
 
346
346
  # If the :limit option has been specified then we are going to slice
347
347
  # our node results by that amount to allow us the ability to deal with
@@ -372,11 +372,11 @@ module HappyMapper
372
372
  end
373
373
  end
374
374
 
375
- # If the :single option has been specified or we are at the root element
376
- # then we are going to return the first item in the collection. Otherwise
377
- # the return response is going to be an entire array of items.
375
+ # If we're parsing a single element then we are going to return the first
376
+ # item in the collection. Otherwise the return response is going to be an
377
+ # entire array of items.
378
378
 
379
- if options[:single] || root
379
+ if single
380
380
  collection.first
381
381
  else
382
382
  collection
@@ -396,8 +396,13 @@ module HappyMapper
396
396
  # and finally attach the current namespace if one has been defined
397
397
  #
398
398
 
399
- xpath = (root ? '/' : './/')
400
- xpath = options[:xpath].to_s.sub(/([^\/])$/, '\1/') if options[:xpath]
399
+ xpath = if options[:xpath]
400
+ options[:xpath].to_s.sub(%r{([^/])$}, '\1/')
401
+ elsif root
402
+ '/'
403
+ else
404
+ './/'
405
+ end
401
406
  if namespace
402
407
  return [] unless namespaces.find { |name, _url| ["xmlns:#{namespace}", namespace].include? name }
403
408
  xpath += "#{namespace}:"
@@ -646,7 +651,7 @@ module HappyMapper
646
651
  # Attributes that have a nil value should be ignored unless they explicitly
647
652
  # state that they should be expressed in the output.
648
653
  #
649
- if not value.nil? || attribute.options[:state_when_nil]
654
+ if !(value.nil? || attribute.options[:state_when_nil])
650
655
  attribute_namespace = attribute.options[:namespace]
651
656
  ["#{attribute_namespace ? "#{attribute_namespace}:" : ''}#{attribute.tag}", value]
652
657
  else
@@ -1,19 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HappyMapper
4
- module AnonymousMapper
4
+ class AnonymousMapper
5
5
  def parse(xml_content)
6
6
  # TODO: this should be able to handle all the types of functionality that parse is able
7
7
  # to handle which includes the text, xml document, node, fragment, etc.
8
8
  xml = Nokogiri::XML(xml_content)
9
9
 
10
- happymapper_class = create_happymapper_class_with_element(xml.root)
10
+ klass = create_happymapper_class_from_node(xml.root)
11
11
 
12
12
  # With all the elements and attributes defined on the class it is time
13
13
  # for the class to actually use the normal HappyMapper powers to parse
14
14
  # the content. At this point this code is utilizing all of the existing
15
15
  # code implemented for parsing.
16
- happymapper_class.parse(xml_content, single: true)
16
+ klass.parse(xml_content, single: true)
17
17
  end
18
18
 
19
19
  private
@@ -38,75 +38,80 @@ module HappyMapper
38
38
  # value is set to the one provided.
39
39
  #
40
40
  def create_happymapper_class_with_tag(tag_name)
41
- happymapper_class = Class.new
42
- happymapper_class.class_eval do
41
+ klass = Class.new
42
+ klass.class_eval do
43
43
  include HappyMapper
44
44
  tag tag_name
45
45
  end
46
- happymapper_class
46
+ klass
47
47
  end
48
48
 
49
49
  #
50
50
  # Used internally to create and define the necessary happymapper
51
51
  # elements.
52
52
  #
53
- def create_happymapper_class_with_element(element)
54
- happymapper_class = create_happymapper_class_with_tag(element.name)
53
+ def create_happymapper_class_from_node(node)
54
+ klass = create_happymapper_class_with_tag(node.name)
55
55
 
56
- happymapper_class.namespace element.namespace.prefix if element.namespace
56
+ klass.namespace node.namespace.prefix if node.namespace
57
57
 
58
- element.namespaces.each do |prefix, namespace|
59
- happymapper_class.register_namespace prefix, namespace
58
+ node.namespaces.each do |prefix, namespace|
59
+ klass.register_namespace prefix, namespace
60
60
  end
61
61
 
62
- element.attributes.each_value do |attribute|
63
- define_attribute_on_class(happymapper_class, attribute)
62
+ node.attributes.each_value do |attribute|
63
+ define_attribute_on_class(klass, attribute)
64
64
  end
65
65
 
66
- element.children.each do |child|
67
- define_element_on_class(happymapper_class, child)
66
+ node.children.each do |child|
67
+ define_element_on_class(klass, child)
68
68
  end
69
69
 
70
- happymapper_class
70
+ klass
71
71
  end
72
72
 
73
73
  #
74
74
  # Define a HappyMapper element on the provided class based on
75
- # the element provided.
75
+ # the node provided.
76
76
  #
77
- def define_element_on_class(class_instance, element)
78
- # When a text element has been provided create the necessary
77
+ def define_element_on_class(klass, node)
78
+ # When a text node has been provided create the necessary
79
79
  # HappyMapper content attribute if the text happens to contain
80
80
  # some content.
81
81
 
82
- class_instance.content :content, String if element.text? && (element.content.strip != '')
82
+ if node.text?
83
+ klass.content :content, String if node.content.strip != ''
84
+ return
85
+ end
83
86
 
84
- # When the element has children elements, that are not text
85
- # elements, then we want to recursively define a new HappyMapper
87
+ # When the node has child elements, that are not text
88
+ # nodes, then we want to recursively define a new HappyMapper
86
89
  # class that will have elements and attributes.
87
90
 
88
- element_type = if !element.elements.reject(&:text?).empty? || !element.attributes.empty?
89
- create_happymapper_class_with_element(element)
91
+ element_type = if node.elements.any? || node.attributes.any?
92
+ create_happymapper_class_from_node(node)
90
93
  else
91
94
  String
92
95
  end
93
96
 
94
- method = class_instance.elements.find { |e| e.name == element.name } ? :has_many : :has_one
97
+ element_name = underscore(node.name)
98
+ method = klass.elements.find { |e| e.name == element_name } ? :has_many : :has_one
95
99
 
96
100
  options = {}
97
- options[:tag] = element.name
98
- namespace = element.namespace
101
+ options[:tag] = node.name
102
+ namespace = node.namespace
99
103
  options[:namespace] = namespace.prefix if namespace
104
+ options[:xpath] = './' unless element_type == String
100
105
 
101
- class_instance.send(method, underscore(element.name), element_type, options)
106
+ klass.send(method, element_name, element_type, options)
102
107
  end
103
108
 
104
109
  #
105
110
  # Define a HappyMapper attribute on the provided class based on
106
111
  # the attribute provided.
107
112
  #
108
- def define_attribute_on_class(class_instance, attribute)
109
- class_instance.attribute underscore(attribute.name), String, tag: attribute.name
113
+ def define_attribute_on_class(klass, attribute)
114
+ klass.attribute underscore(attribute.name), String, tag: attribute.name
110
115
  end
111
116
  end
112
117
  end