nokogiri-happymapper 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|