nokogiri-happymapper 0.8.1 → 0.9.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 +7 -0
- data/README.md +0 -3
- data/lib/happymapper/element.rb +2 -2
- data/lib/happymapper/supported_types.rb +3 -5
- data/lib/happymapper/version.rb +1 -1
- data/lib/happymapper.rb +44 -52
- metadata +98 -107
- data/spec/features/after_parse_callbacks_spec.rb +0 -32
- data/spec/features/attribute_default_value_spec.rb +0 -48
- data/spec/features/attributes_spec.rb +0 -35
- data/spec/features/has_many_empty_array_spec.rb +0 -44
- data/spec/features/ignay_spec.rb +0 -92
- data/spec/features/inheritance_spec.rb +0 -121
- data/spec/features/mixed_namespaces_spec.rb +0 -60
- data/spec/features/parse_with_object_to_update_spec.rb +0 -116
- data/spec/features/same_tag_different_meaning_spec.rb +0 -44
- data/spec/features/to_xml_spec.rb +0 -205
- data/spec/features/to_xml_with_namespaces_spec.rb +0 -237
- data/spec/features/wildcard_tag_name_spec.rb +0 -110
- data/spec/features/wrap_spec.rb +0 -87
- data/spec/features/xpath_spec.rb +0 -84
- data/spec/fixtures/address.xml +0 -9
- data/spec/fixtures/ambigous_items.xml +0 -22
- data/spec/fixtures/analytics.xml +0 -61
- data/spec/fixtures/analytics_profile.xml +0 -127
- data/spec/fixtures/atom.xml +0 -19
- data/spec/fixtures/commit.xml +0 -52
- data/spec/fixtures/current_weather.xml +0 -89
- data/spec/fixtures/current_weather_missing_elements.xml +0 -18
- data/spec/fixtures/default_namespace_combi.xml +0 -6
- data/spec/fixtures/dictionary.xml +0 -20
- data/spec/fixtures/family_tree.xml +0 -21
- data/spec/fixtures/inagy.xml +0 -85
- data/spec/fixtures/lastfm.xml +0 -355
- data/spec/fixtures/multiple_namespaces.xml +0 -170
- data/spec/fixtures/multiple_primitives.xml +0 -5
- data/spec/fixtures/optional_attributes.xml +0 -6
- data/spec/fixtures/pita.xml +0 -133
- data/spec/fixtures/posts.xml +0 -23
- data/spec/fixtures/product_default_namespace.xml +0 -18
- data/spec/fixtures/product_no_namespace.xml +0 -10
- data/spec/fixtures/product_single_namespace.xml +0 -10
- data/spec/fixtures/quarters.xml +0 -19
- data/spec/fixtures/radar.xml +0 -21
- data/spec/fixtures/set_config_options.xml +0 -3
- data/spec/fixtures/statuses.xml +0 -422
- data/spec/fixtures/subclass_namespace.xml +0 -50
- data/spec/fixtures/unformatted_address.xml +0 -1
- data/spec/fixtures/wrapper.xml +0 -11
- data/spec/happymapper/anonymous_mapper_spec.rb +0 -158
- data/spec/happymapper/attribute_spec.rb +0 -12
- data/spec/happymapper/item_spec.rb +0 -177
- data/spec/happymapper_spec.rb +0 -1208
- data/spec/spec_helper.rb +0 -25
@@ -1,237 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module ToXMLWithNamespaces
|
6
|
-
#
|
7
|
-
# Similar example as the to_xml but this time with namespacing
|
8
|
-
#
|
9
|
-
class Address
|
10
|
-
include HappyMapper
|
11
|
-
|
12
|
-
register_namespace 'address', 'http://www.company.com/address'
|
13
|
-
register_namespace 'country', 'http://www.company.com/country'
|
14
|
-
|
15
|
-
tag 'Address'
|
16
|
-
namespace 'address'
|
17
|
-
|
18
|
-
element :country, 'Country', tag: 'country', namespace: 'country'
|
19
|
-
|
20
|
-
attribute :location, String, on_save: :when_saving_location
|
21
|
-
|
22
|
-
element :street, String
|
23
|
-
element :postcode, String
|
24
|
-
element :city, String
|
25
|
-
|
26
|
-
element :housenumber, String
|
27
|
-
|
28
|
-
#
|
29
|
-
# to_xml will default to the attr_accessor method and not the attribute,
|
30
|
-
# allowing for that to be overwritten
|
31
|
-
#
|
32
|
-
undef :housenumber
|
33
|
-
def housenumber
|
34
|
-
"[#{@housenumber}]"
|
35
|
-
end
|
36
|
-
|
37
|
-
def when_saving_location(loc)
|
38
|
-
loc + '-live'
|
39
|
-
end
|
40
|
-
|
41
|
-
#
|
42
|
-
# Write a empty element even if this is not specified
|
43
|
-
#
|
44
|
-
element :description, String, state_when_nil: true
|
45
|
-
|
46
|
-
#
|
47
|
-
# Perform the on_save operation when saving
|
48
|
-
#
|
49
|
-
has_one :date_created, Time, on_save: ->(time) { Time.parse(time).strftime('%T %D') if time }
|
50
|
-
|
51
|
-
#
|
52
|
-
# Write multiple elements and call on_save when saving
|
53
|
-
#
|
54
|
-
has_many :dates_updated, Time, on_save: lambda { |times|
|
55
|
-
times.compact.map { |time| Time.parse(time).strftime('%T %D') } if times
|
56
|
-
}
|
57
|
-
|
58
|
-
#
|
59
|
-
# Class composition
|
60
|
-
#
|
61
|
-
|
62
|
-
def initialize(parameters)
|
63
|
-
parameters.each_pair do |property, value|
|
64
|
-
send("#{property}=", value) if respond_to?("#{property}=")
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
#
|
70
|
-
# Country is composed above the in Address class. Here is a demonstration
|
71
|
-
# of how to_xml will handle class composition as well as utilizing the tag
|
72
|
-
# value.
|
73
|
-
#
|
74
|
-
class Country
|
75
|
-
include HappyMapper
|
76
|
-
|
77
|
-
register_namespace 'countryName', 'http://www.company.com/countryName'
|
78
|
-
|
79
|
-
attribute :code, String, tag: 'countryCode'
|
80
|
-
has_one :name, String, tag: 'countryName', namespace: 'countryName'
|
81
|
-
|
82
|
-
def initialize(parameters)
|
83
|
-
parameters.each_pair do |property, value|
|
84
|
-
send("#{property}=", value) if respond_to?("#{property}=")
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
#
|
90
|
-
# This class is an example of a class that has a default namespace
|
91
|
-
# xmlns="urn:eventis:prodis:onlineapi:1.0"
|
92
|
-
# xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
93
|
-
# xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
94
|
-
#
|
95
|
-
class Recipe
|
96
|
-
include HappyMapper
|
97
|
-
|
98
|
-
# this is the default namespace of the document
|
99
|
-
register_namespace 'xmlns', 'urn:eventis:prodis:onlineapi:1.0'
|
100
|
-
register_namespace 'xsi', 'http://www.w3.org/2001/XMLSchema-instance'
|
101
|
-
register_namespace 'xsd', 'http://www.w3.org/2001/XMLSchema'
|
102
|
-
|
103
|
-
has_many :ingredients, String
|
104
|
-
|
105
|
-
def initialize(parameters)
|
106
|
-
parameters.each_pair { |property, value| send("#{property}=", value) if respond_to?("#{property}=") }
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
RSpec.describe 'Saving #to_xml with xml namespaces', type: :feature do
|
112
|
-
context 'with namespaces' do
|
113
|
-
let(:xml) do
|
114
|
-
country = ToXMLWithNamespaces::Country.new(name: 'USA', code: 'us')
|
115
|
-
address = ToXMLWithNamespaces::Address.new('street' => 'Mockingbird Lane',
|
116
|
-
'location' => 'Home',
|
117
|
-
'housenumber' => '1313',
|
118
|
-
'postcode' => '98103',
|
119
|
-
'city' => 'Seattle',
|
120
|
-
'country' => country,
|
121
|
-
'date_created' => '2011-01-01 15:00:00')
|
122
|
-
|
123
|
-
address.dates_updated = ['2011-01-01 16:01:00', '2011-01-02 11:30:01']
|
124
|
-
|
125
|
-
Nokogiri::XML(address.to_xml).root
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'sets the namespace specified in the class' do
|
129
|
-
expect(xml.xpath('/').children.first.namespace.prefix).to eq 'address'
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'saves elements' do
|
133
|
-
elements = { 'street' => 'Mockingbird Lane', 'postcode' => '98103', 'city' => 'Seattle' }
|
134
|
-
|
135
|
-
elements.each_pair do |property, value|
|
136
|
-
expect(xml.xpath("address:#{property}").text).to eq value
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
it 'saves attributes' do
|
141
|
-
expect(xml.xpath('@location').text).to eq 'Home-live'
|
142
|
-
end
|
143
|
-
|
144
|
-
context "when an element has a 'state_when_nil' parameter" do
|
145
|
-
it 'saves an empty element' do
|
146
|
-
expect(xml.xpath('address:description').text).to eq ''
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
context "when an element has a 'on_save' parameter" do
|
151
|
-
context 'with a symbol which represents a function' do
|
152
|
-
it 'saves the element with the result of a function call and not the value of the ivar' do
|
153
|
-
expect(xml.xpath('address:housenumber').text).to eq '[1313]'
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
context 'with a lambda' do
|
158
|
-
it 'saves the results' do
|
159
|
-
expect(xml.xpath('address:date_created').text).to eq '15:00:00 01/01/11'
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
context "when an attribute has a 'on_save' parameter" do
|
165
|
-
context 'with a lambda' do
|
166
|
-
it 'saves the result' do
|
167
|
-
expect(xml.xpath('@location').text).to eq 'Home-live'
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
context "when a has_many has a 'on_save' parameter" do
|
173
|
-
context 'with a lambda' do
|
174
|
-
it 'saves the result' do
|
175
|
-
dates_updated = xml.xpath('address:dates_updated')
|
176
|
-
|
177
|
-
aggregate_failures do
|
178
|
-
expect(dates_updated.length).to eq 2
|
179
|
-
expect(dates_updated.first.text).to eq '16:01:00 01/01/11'
|
180
|
-
expect(dates_updated.last.text).to eq '11:30:01 01/02/11'
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
context 'when an element type is a HappyMapper subclass' do
|
187
|
-
it 'saves attributes' do
|
188
|
-
expect(xml.xpath('country:country/@countryCode').text).to eq 'us'
|
189
|
-
end
|
190
|
-
|
191
|
-
it 'saves elements' do
|
192
|
-
expect(xml.xpath('country:country/countryName:countryName').text).to eq 'USA'
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
context 'with a default namespace' do
|
198
|
-
it 'writes the default namespace to xml without repeating xmlns' do
|
199
|
-
recipe = ToXMLWithNamespaces::Recipe.new(ingredients: ['One Cup Flour', 'Two Scoops of Lovin'])
|
200
|
-
expect(recipe.to_xml).to match(/xmlns=\"urn:eventis:prodis:onlineapi:1\.0\"/)
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
context 'namespace supplied by element declaration trumps namespace ' \
|
205
|
-
'specified by element class' do
|
206
|
-
|
207
|
-
let(:expected_xml) do
|
208
|
-
<<-XML.gsub(/^\s*\|/, '')
|
209
|
-
|<?xml version="1.0"?>
|
210
|
-
|<coffeemachine xmlns:beverage="http://beverages.org/Beverage/0.1" xmlns:coffee="http://coffee.org/Coffee/0.1">
|
211
|
-
| <beverage:beverage name="coffee"/>
|
212
|
-
|</coffeemachine>
|
213
|
-
XML
|
214
|
-
end
|
215
|
-
|
216
|
-
class Beverage
|
217
|
-
include HappyMapper
|
218
|
-
namespace 'coffee'
|
219
|
-
|
220
|
-
attribute :name, String
|
221
|
-
end
|
222
|
-
|
223
|
-
class CoffeeMachine
|
224
|
-
include HappyMapper
|
225
|
-
register_namespace 'coffee', 'http://coffee.org/Coffee/0.1'
|
226
|
-
register_namespace 'beverage', 'http://beverages.org/Beverage/0.1'
|
227
|
-
|
228
|
-
element :beverage, 'beverage', namespace: 'beverage'
|
229
|
-
end
|
230
|
-
|
231
|
-
it 'uses the element declaration namespace on the element' do
|
232
|
-
machine = CoffeeMachine.new
|
233
|
-
machine.beverage = Beverage.new.tap { |obj| obj.name = 'coffee' }
|
234
|
-
expect(machine.to_xml).to eq(expected_xml)
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|
@@ -1,110 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe 'Wildcard Root Tag', type: :feature do
|
6
|
-
generic_class_xml = %(
|
7
|
-
<root>
|
8
|
-
<description>some description</description>
|
9
|
-
<blarg name='blargname1' href='http://blarg.com'/>
|
10
|
-
<blarg name='blargname2' href='http://blarg.com'/>
|
11
|
-
<jello name='jelloname' href='http://jello.com'/>
|
12
|
-
<subelement>
|
13
|
-
<jello name='subjelloname' href='http://ohnojello.com' other='othertext'/>
|
14
|
-
</subelement>
|
15
|
-
</root>)
|
16
|
-
|
17
|
-
module GenericBase
|
18
|
-
class Base
|
19
|
-
include Comparable
|
20
|
-
include HappyMapper
|
21
|
-
|
22
|
-
def initialize(params = {})
|
23
|
-
@name = params[:name]
|
24
|
-
@href = params[:href]
|
25
|
-
@other = params[:other]
|
26
|
-
end
|
27
|
-
|
28
|
-
tag '*'
|
29
|
-
attribute :name, String
|
30
|
-
attribute :href, String
|
31
|
-
attribute :other, String
|
32
|
-
|
33
|
-
def <=>(other)
|
34
|
-
result = name <=> other.name
|
35
|
-
return result unless result == 0
|
36
|
-
|
37
|
-
result = href <=> other.href
|
38
|
-
return result unless result == 0
|
39
|
-
|
40
|
-
self.other <=> other.other
|
41
|
-
end
|
42
|
-
end
|
43
|
-
class Sub
|
44
|
-
include HappyMapper
|
45
|
-
tag 'subelement'
|
46
|
-
has_one :jello, Base, tag: 'jello'
|
47
|
-
end
|
48
|
-
class Root
|
49
|
-
include HappyMapper
|
50
|
-
tag 'root'
|
51
|
-
element :description, String
|
52
|
-
has_many :blargs, Base, tag: 'blarg', xpath: '.'
|
53
|
-
has_many :jellos, Base, tag: 'jello', xpath: '.'
|
54
|
-
has_many :subjellos, Base, tag: 'jello', xpath: 'subelement/.', read_only: true
|
55
|
-
has_one :sub_element, Sub
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe "can have generic classes using tag '*'" do
|
60
|
-
let(:root) { GenericBase::Root.parse(generic_class_xml) }
|
61
|
-
let(:xml) { Nokogiri::XML(root.to_xml) }
|
62
|
-
|
63
|
-
it 'maps different elements to same class' do
|
64
|
-
aggregate_failures do
|
65
|
-
expect(root.blargs).not_to be_nil
|
66
|
-
expect(root.jellos).not_to be_nil
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'filters on xpath appropriately' do
|
71
|
-
aggregate_failures do
|
72
|
-
expect(root.blargs.size).to eq(2)
|
73
|
-
expect(root.jellos.size).to eq(1)
|
74
|
-
expect(root.subjellos.size).to eq(1)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def base_with(name, href, other)
|
79
|
-
GenericBase::Base.new(name: name, href: href, other: other)
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'parses correct values onto generic class' do
|
83
|
-
aggregate_failures do
|
84
|
-
expect(root.blargs[0]).to eq base_with('blargname1', 'http://blarg.com', nil)
|
85
|
-
expect(root.blargs[1]).to eq base_with('blargname2', 'http://blarg.com', nil)
|
86
|
-
expect(root.jellos[0]).to eq base_with('jelloname', 'http://jello.com', nil)
|
87
|
-
expect(root.subjellos[0]).to eq base_with('subjelloname', 'http://ohnojello.com', 'othertext')
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def validate_xpath(xpath, name, href, other)
|
92
|
-
expect(xml.xpath("#{xpath}/@name").text).to eq name
|
93
|
-
expect(xml.xpath("#{xpath}/@href").text).to eq href
|
94
|
-
expect(xml.xpath("#{xpath}/@other").text).to eq other
|
95
|
-
end
|
96
|
-
|
97
|
-
it '#to_xmls using parent element tag name' do
|
98
|
-
aggregate_failures do
|
99
|
-
expect(xml.xpath('/root/description').text).to eq('some description')
|
100
|
-
validate_xpath('/root/blarg[1]', 'blargname1', 'http://blarg.com', '')
|
101
|
-
validate_xpath('/root/blarg[2]', 'blargname2', 'http://blarg.com', '')
|
102
|
-
validate_xpath('/root/jello[1]', 'jelloname', 'http://jello.com', '')
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
it "properlies respect child HappyMapper tags if tag isn't provided on the element defintion" do
|
107
|
-
expect(xml.xpath('root/subelement').size).to eq(1)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
data/spec/features/wrap_spec.rb
DELETED
@@ -1,87 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe 'wrap which allows you to specify a wrapper element', type: :feature do
|
6
|
-
module Wrap
|
7
|
-
class SubClass
|
8
|
-
include HappyMapper
|
9
|
-
tag 'subclass'
|
10
|
-
attribute :myattr, String
|
11
|
-
has_many :items, String, tag: 'item'
|
12
|
-
end
|
13
|
-
class Root
|
14
|
-
include HappyMapper
|
15
|
-
tag 'root'
|
16
|
-
attribute :attr1, String
|
17
|
-
element :name, String
|
18
|
-
wrap 'mywraptag' do
|
19
|
-
element :description, String
|
20
|
-
has_one :subclass, SubClass
|
21
|
-
end
|
22
|
-
element :number, Integer
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe '.parse' do
|
27
|
-
context 'when given valid XML' do
|
28
|
-
let(:root) { Wrap::Root.parse fixture_file('wrapper.xml') }
|
29
|
-
|
30
|
-
it 'sets the values correctly' do
|
31
|
-
aggregate_failures do
|
32
|
-
expect(root.attr1).to eq 'somevalue'
|
33
|
-
expect(root.name).to eq 'myname'
|
34
|
-
expect(root.description).to eq 'some description'
|
35
|
-
expect(root.subclass.myattr).to eq 'attrvalue'
|
36
|
-
expect(root.subclass.items.size).to eq(2)
|
37
|
-
expect(root.subclass.items[0]).to eq 'item1'
|
38
|
-
expect(root.subclass.items[1]).to eq 'item2'
|
39
|
-
expect(root.number).to eq 12_345
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
context 'when initialized without XML' do
|
45
|
-
let(:root) { Wrap::Root.new }
|
46
|
-
|
47
|
-
it 'creates anonymous classes so nil class values do not occur' do
|
48
|
-
expect { root.description = 'anything' }.not_to raise_error
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe '.to_xml' do
|
54
|
-
let(:root) do
|
55
|
-
root = Wrap::Root.new
|
56
|
-
root.attr1 = 'somevalue'
|
57
|
-
root.name = 'myname'
|
58
|
-
root.description = 'some description'
|
59
|
-
root.number = 12_345
|
60
|
-
|
61
|
-
subclass = Wrap::SubClass.new
|
62
|
-
subclass.myattr = 'attrvalue'
|
63
|
-
subclass.items = []
|
64
|
-
subclass.items << 'item1'
|
65
|
-
subclass.items << 'item2'
|
66
|
-
|
67
|
-
root.subclass = subclass
|
68
|
-
|
69
|
-
root
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'generates the correct xml' do
|
73
|
-
xml = Nokogiri::XML(root.to_xml)
|
74
|
-
|
75
|
-
aggregate_failures do
|
76
|
-
expect(xml.xpath('/root/@attr1').text).to eq 'somevalue'
|
77
|
-
expect(xml.xpath('/root/name').text).to eq 'myname'
|
78
|
-
expect(xml.xpath('/root/mywraptag/description').text).to eq 'some description'
|
79
|
-
expect(xml.xpath('/root/mywraptag/subclass/@myattr').text).to eq 'attrvalue'
|
80
|
-
expect(xml.xpath('/root/mywraptag/subclass/item').size).to eq(2)
|
81
|
-
expect(xml.xpath('/root/mywraptag/subclass/item[1]').text).to eq 'item1'
|
82
|
-
expect(xml.xpath('/root/mywraptag/subclass/item[2]').text).to eq 'item2'
|
83
|
-
expect(xml.xpath('/root/number').text).to eq '12345'
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
data/spec/features/xpath_spec.rb
DELETED
@@ -1,84 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe 'Specifying elements and attributes with an xpath', type: :feature do
|
6
|
-
class Item
|
7
|
-
include HappyMapper
|
8
|
-
|
9
|
-
tag 'item'
|
10
|
-
namespace 'amazing'
|
11
|
-
|
12
|
-
element :title, String
|
13
|
-
attribute :link, String, xpath: 'amazing:link/@href'
|
14
|
-
has_one :different_link, String, xpath: 'different:link/@href'
|
15
|
-
element :detail, String, xpath: 'amazing:subitem/amazing:detail'
|
16
|
-
has_many :more_details_text, String, xpath: 'amazing:subitem/amazing:more'
|
17
|
-
has_many :more_details, String,
|
18
|
-
xpath: 'amazing:subitem/amazing:more/@first|amazing:subitem/amazing:more/@alternative'
|
19
|
-
has_many :more_details_alternative, String, xpath: 'amazing:subitem/amazing:more/@*'
|
20
|
-
|
21
|
-
has_one :baby, 'Baby', name: 'baby', namespace: 'amazing'
|
22
|
-
end
|
23
|
-
|
24
|
-
class Baby
|
25
|
-
include HappyMapper
|
26
|
-
|
27
|
-
has_one :name, String
|
28
|
-
end
|
29
|
-
|
30
|
-
let(:parsed_result) { Item.parse(xml_string, single: true) }
|
31
|
-
|
32
|
-
let(:xml_string) do
|
33
|
-
%(
|
34
|
-
<rss>
|
35
|
-
<amazing:item xmlns:amazing="http://www.amazing.com/amazing"
|
36
|
-
xmlns:different="http://www.different.com/different">
|
37
|
-
<amazing:title>Test XML</amazing:title>
|
38
|
-
<different:link href="different_link" />
|
39
|
-
<amazing:link href="link_to_resources" />
|
40
|
-
<amazing:subitem>
|
41
|
-
<amazing:detail>I want to parse this</amazing:detail>
|
42
|
-
<amazing:more first="this one">more 1</amazing:more>
|
43
|
-
<amazing:more alternative="another one">more 2</amazing:more>
|
44
|
-
</amazing:subitem>
|
45
|
-
<amazing:baby>
|
46
|
-
<amazing:name>Jumbo</amazing:name>
|
47
|
-
</amazing:baby>
|
48
|
-
</amazing:item>
|
49
|
-
</rss>
|
50
|
-
)
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'has a title' do
|
54
|
-
expect(parsed_result.title).to eq 'Test XML'
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'finds the link href value' do
|
58
|
-
expect(parsed_result.link).to eq 'link_to_resources'
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'finds the other link href value' do
|
62
|
-
expect(parsed_result.different_link).to eq 'different_link'
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'finds this subitem based on the xpath' do
|
66
|
-
expect(parsed_result.detail).to eq 'I want to parse this'
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'finds the subitem texts based on the xpath' do
|
70
|
-
expect(parsed_result.more_details_text).to eq ['more 1', 'more 2']
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'finds the subitem attributes based on the xpath' do
|
74
|
-
expect(parsed_result.more_details).to eq ['this one', 'another one']
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'finds the subitem attributes based on the xpath with a wildcard' do
|
78
|
-
expect(parsed_result.more_details_alternative).to eq ['this one', 'another one']
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'has a baby name' do
|
82
|
-
expect(parsed_result.baby.name).to eq 'Jumbo'
|
83
|
-
end
|
84
|
-
end
|
data/spec/fixtures/address.xml
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<ambigous>
|
3
|
-
<my-items>
|
4
|
-
<item>
|
5
|
-
<name>My first item</name>
|
6
|
-
<item><name>My first internal item</name></item>
|
7
|
-
</item>
|
8
|
-
<item>
|
9
|
-
<name>My second item</name>
|
10
|
-
<item><name>My second internal item</name></item>
|
11
|
-
</item>
|
12
|
-
<item>
|
13
|
-
<name>My third item</name>
|
14
|
-
<item><name>My third internal item</name></item>
|
15
|
-
</item>
|
16
|
-
</my-items>
|
17
|
-
<others-items>
|
18
|
-
<item>
|
19
|
-
<name>Other item</name>
|
20
|
-
</item>
|
21
|
-
</others-items>
|
22
|
-
</ambigous>
|
data/spec/fixtures/analytics.xml
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<feed xmlns="http://www.w3.org/2005/Atom"
|
3
|
-
xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
|
4
|
-
xmlns:dxp="http://schemas.google.com/analytics/2009">
|
5
|
-
<id>http://www.google.com/analytics/feeds/accounts/nunemaker@gmail.com</id>
|
6
|
-
<updated>2009-04-22T23:21:23.000-07:00</updated>
|
7
|
-
<title type="text">Profile list for nunemaker@gmail.com</title>
|
8
|
-
<link rel="self" type="application/atom+xml"
|
9
|
-
href="http://www.google.com/analytics/feeds/accounts/default"/>
|
10
|
-
<author>
|
11
|
-
<name>Google Analytics</name>
|
12
|
-
</author>
|
13
|
-
<generator version="1.0">Google Analytics</generator>
|
14
|
-
<openSearch:totalResults>4</openSearch:totalResults>
|
15
|
-
<openSearch:startIndex>1</openSearch:startIndex>
|
16
|
-
<openSearch:itemsPerPage>4</openSearch:itemsPerPage>
|
17
|
-
<entry>
|
18
|
-
<id>http://www.google.com/analytics/feeds/accounts/ga:47912</id>
|
19
|
-
<updated>2008-11-24T12:11:32.000-08:00</updated>
|
20
|
-
<title type="text">addictedtonew.com</title>
|
21
|
-
<link rel="alternate" type="text/html" href="http://www.google.com/analytics"/>
|
22
|
-
<dxp:tableId>ga:47912</dxp:tableId>
|
23
|
-
<dxp:property name="ga:accountId" value="85301"/>
|
24
|
-
<dxp:property name="ga:accountName" value="addictedtonew.com"/>
|
25
|
-
<dxp:property name="ga:profileId" value="47912"/>
|
26
|
-
<dxp:property name="ga:webPropertyId" value="UA-85301-1"/>
|
27
|
-
</entry>
|
28
|
-
<entry>
|
29
|
-
<id>http://www.google.com/analytics/feeds/accounts/ga:1897579</id>
|
30
|
-
<updated>2008-11-24T12:11:32.000-08:00</updated>
|
31
|
-
<title type="text">railstips.org</title>
|
32
|
-
<link rel="alternate" type="text/html" href="http://www.google.com/analytics"/>
|
33
|
-
<dxp:tableId>ga:1897579</dxp:tableId>
|
34
|
-
<dxp:property name="ga:accountId" value="85301"/>
|
35
|
-
<dxp:property name="ga:accountName" value="addictedtonew.com"/>
|
36
|
-
<dxp:property name="ga:profileId" value="1897579"/>
|
37
|
-
<dxp:property name="ga:webPropertyId" value="UA-85301-7"/>
|
38
|
-
</entry>
|
39
|
-
<entry>
|
40
|
-
<id>http://www.google.com/analytics/feeds/accounts/ga:17132454</id>
|
41
|
-
<updated>2009-04-22T23:21:23.000-07:00</updated>
|
42
|
-
<title type="text">johnnunemaker.com</title>
|
43
|
-
<link rel="alternate" type="text/html" href="http://www.google.com/analytics"/>
|
44
|
-
<dxp:tableId>ga:17132454</dxp:tableId>
|
45
|
-
<dxp:property name="ga:accountId" value="85301"/>
|
46
|
-
<dxp:property name="ga:accountName" value="addictedtonew.com"/>
|
47
|
-
<dxp:property name="ga:profileId" value="17132454"/>
|
48
|
-
<dxp:property name="ga:webPropertyId" value="UA-85301-25"/>
|
49
|
-
</entry>
|
50
|
-
<entry>
|
51
|
-
<id>http://www.google.com/analytics/feeds/accounts/ga:17132478</id>
|
52
|
-
<updated>2009-04-22T23:21:23.000-07:00</updated>
|
53
|
-
<title type="text">harmonyapp.com</title>
|
54
|
-
<link rel="alternate" type="text/html" href="http://www.google.com/analytics"/>
|
55
|
-
<dxp:tableId>ga:17132478</dxp:tableId>
|
56
|
-
<dxp:property name="ga:accountId" value="85301"/>
|
57
|
-
<dxp:property name="ga:accountName" value="addictedtonew.com"/>
|
58
|
-
<dxp:property name="ga:profileId" value="17132478"/>
|
59
|
-
<dxp:property name="ga:webPropertyId" value="UA-85301-26"/>
|
60
|
-
</entry>
|
61
|
-
</feed>
|