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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -5
- data/README.md +85 -69
- data/lib/happymapper.rb +27 -22
- data/lib/happymapper/anonymous_mapper.rb +35 -30
- data/lib/happymapper/item.rb +1 -1
- data/lib/happymapper/supported_types.rb +2 -7
- data/lib/happymapper/version.rb +1 -1
- data/spec/features/after_parse_callbacks_spec.rb +29 -0
- data/spec/{attribute_default_value_spec.rb → features/attribute_default_value_spec.rb} +3 -3
- data/spec/{attributes_spec.rb → features/attributes_spec.rb} +6 -6
- data/spec/{has_many_empty_array_spec.rb → features/has_many_empty_array_spec.rb} +1 -1
- data/spec/{ignay_spec.rb → features/ignay_spec.rb} +10 -19
- data/spec/{inheritance_spec.rb → features/inheritance_spec.rb} +1 -1
- data/spec/{mixed_namespaces_spec.rb → features/mixed_namespaces_spec.rb} +17 -17
- data/spec/{parse_with_object_to_update_spec.rb → features/parse_with_object_to_update_spec.rb} +0 -0
- data/spec/features/same_tag_different_meaning_spec.rb +44 -0
- data/spec/{to_xml_spec.rb → features/to_xml_spec.rb} +2 -2
- data/spec/{to_xml_with_namespaces_spec.rb → features/to_xml_with_namespaces_spec.rb} +0 -0
- data/spec/{wilcard_tag_name_spec.rb → features/wildcard_tag_name_spec.rb} +5 -5
- data/spec/{wrap_spec.rb → features/wrap_spec.rb} +4 -4
- data/spec/{xpath_spec.rb → features/xpath_spec.rb} +17 -23
- data/spec/happymapper/anonymous_mapper_spec.rb +158 -0
- data/spec/happymapper/element_spec.rb +1 -1
- data/spec/happymapper/item_spec.rb +75 -45
- data/spec/happymapper_spec.rb +120 -125
- metadata +32 -28
- data/spec/happymapper_parse_spec.rb +0 -131
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20c74c3600aeae595d9851fdc864364df4af72d3b5ea1257cb7323a5f4032439
|
4
|
+
data.tar.gz: b1fe72afe90bebc42fe52130fe1d4fb6681815f9c9e79a9f8dccabf93f5e9003
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab001b07e41193a760a37d87600f2020310aa4f753b1bdcca2fad7251a5ac50346267c61cce18a5d5fc20f3ec683a3f8b67a305de2183a5fb8b3187731f8eab8
|
7
|
+
data.tar.gz: db0cb626e8d21eaf4b388bdb414165dbcb6b63ab3d6c6c3f61077255983fa3ec833e10e223ad429a9162d669d0ede349010c9b8c123ad231e34b4949ee2c4288
|
data/CHANGELOG.md
CHANGED
@@ -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
|
60
|
-
within the xml. This implementation addresses issues with calling
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
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
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
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
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
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
|
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
|
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
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
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
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
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
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
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`
|
data/lib/happymapper.rb
CHANGED
@@ -10,7 +10,9 @@ module HappyMapper
|
|
10
10
|
class Boolean; end
|
11
11
|
class XmlContent; end
|
12
12
|
|
13
|
-
|
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.
|
286
|
-
# if requesting a single object, otherwise it defaults
|
287
|
-
# array of multiple items.
|
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
|
328
|
-
# or
|
331
|
+
# or use the namespace provided by the class
|
332
|
+
# or use the 'xmlns' namespace if defined
|
329
333
|
|
330
|
-
|
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 (
|
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
|
376
|
-
#
|
377
|
-
#
|
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
|
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
|
400
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
42
|
-
|
41
|
+
klass = Class.new
|
42
|
+
klass.class_eval do
|
43
43
|
include HappyMapper
|
44
44
|
tag tag_name
|
45
45
|
end
|
46
|
-
|
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
|
54
|
-
|
53
|
+
def create_happymapper_class_from_node(node)
|
54
|
+
klass = create_happymapper_class_with_tag(node.name)
|
55
55
|
|
56
|
-
|
56
|
+
klass.namespace node.namespace.prefix if node.namespace
|
57
57
|
|
58
|
-
|
59
|
-
|
58
|
+
node.namespaces.each do |prefix, namespace|
|
59
|
+
klass.register_namespace prefix, namespace
|
60
60
|
end
|
61
61
|
|
62
|
-
|
63
|
-
define_attribute_on_class(
|
62
|
+
node.attributes.each_value do |attribute|
|
63
|
+
define_attribute_on_class(klass, attribute)
|
64
64
|
end
|
65
65
|
|
66
|
-
|
67
|
-
define_element_on_class(
|
66
|
+
node.children.each do |child|
|
67
|
+
define_element_on_class(klass, child)
|
68
68
|
end
|
69
69
|
|
70
|
-
|
70
|
+
klass
|
71
71
|
end
|
72
72
|
|
73
73
|
#
|
74
74
|
# Define a HappyMapper element on the provided class based on
|
75
|
-
# the
|
75
|
+
# the node provided.
|
76
76
|
#
|
77
|
-
def define_element_on_class(
|
78
|
-
# When a text
|
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
|
-
|
82
|
+
if node.text?
|
83
|
+
klass.content :content, String if node.content.strip != ''
|
84
|
+
return
|
85
|
+
end
|
83
86
|
|
84
|
-
# When the
|
85
|
-
#
|
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
|
89
|
-
|
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
|
-
|
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] =
|
98
|
-
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
|
-
|
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(
|
109
|
-
|
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
|