xml_mapper 0.4.1 → 0.4.2

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.
data/README.rdoc CHANGED
@@ -22,6 +22,7 @@ Declarative mapping of XML files to ruby attributes
22
22
  <tracks>
23
23
  <track code="1234">
24
24
  <title>Fear Not of Man</title>
25
+ <version_title></version_title>
25
26
  <number>1</number>
26
27
  <disk>1</number>
27
28
  <explicit_lyrics />
@@ -31,8 +32,11 @@ Declarative mapping of XML files to ruby attributes
31
32
  </track>
32
33
  <track code="2345">
33
34
  <title>Hip Hop</title>
35
+ <version_title>Album Version</version_title>
34
36
  <number>2</number>
35
37
  <disk>1</number>
38
+ <performer>Mos Def</performer>
39
+ <producer>DJ Premier</producer>
36
40
  <not_streamable_in>
37
41
  <country>at</country>
38
42
  </not_streamable_in>
@@ -46,32 +50,36 @@ Declarative mapping of XML files to ruby attributes
46
50
  require "date"
47
51
 
48
52
  class MyMapper < XmlMapper
49
- text :title, :version_title # 1:1 - maps xpaths title and version_title to attribute keys
50
- integer :released_in # converts value to an integer
51
- text :country, :after_map => :upcase # calls after_map method on extracted value if value responds to the method
52
- text :released_on, :after_map => :parse_date # calls after_map method defined in Mapper class when value does not respond
53
- boolean :allows_streaming # maps Y, y, yes, true => true, N, n, no, false => false
53
+ text :title, :version_title # 1:1 - maps xpaths title and version_title to attribute keys
54
+ integer :released_in # converts value to an integer
55
+ text :country, :after_map => :upcase # calls after_map method on extracted value if value responds to the method
56
+ text :released_on, :after_map => :parse_date # calls after_map method defined in Mapper class when value does not respond
57
+ boolean :allows_streaming # maps 1, Y, y, yes, true => true, 0, N, n, no, false => false
54
58
 
55
59
  within :artist do
56
- text :name => :artist_name # adds mapping for xpath "artist/name"
60
+ text :name => :artist_name # adds mapping for xpath "artist/name"
57
61
  integer :id => :artist_id
58
62
  end
59
63
 
60
- many "contributions/*" => :contributions do # use the name of xml nodes for mappings
61
- node_name :role # map name of xml node to :role
62
- inner_text :name # map inner_text of xml node to :name
64
+ many "contributions/*" => :contributions do # use the name of xml nodes for mappings
65
+ node_name :role # map name of xml node to :role
66
+ inner_text :name # map inner_text of xml node to :name
63
67
  end
64
68
 
65
- many "tracks/track" => :tracks do # maps xpath "tracks/track" to array with key :tracks
66
- attribute :code => :isrc # map xml attribute "code" to :isrc
69
+ many "tracks/track" => :tracks do # maps xpath "tracks/track" to array with key :tracks
70
+ attribute :code => :isrc # map xml attribute "code" to :isrc
67
71
  text :title => :track_title
72
+ text :version_title
68
73
  integer :number => :track_number
69
74
  integer :disk => :disk_number
70
- exists :explicit_lyrics # checks if a node with the xpath exists
75
+ exists :explicit_lyrics # checks if a node with the xpath exists
71
76
  not_exists "not_streamable_in/country[text()='de']" => :allows_streaming
77
+
78
+ text :performer => { :contributions => :performer } # assigns to content at xpath :performer to attributes[:contributions][:performer]
79
+ text :producer => { :contributions => :producer } # assigns to content at xpath :performer to attributes[:contributions][:producer]
72
80
  end
73
81
 
74
- after_map do # is called after attributes are extracted, self references the extracted attributes
82
+ after_map do # is called after attributes are extracted, self references the extracted attributes
75
83
  self[:tracks_count] = self[:tracks].length
76
84
  end
77
85
 
@@ -87,21 +95,20 @@ Declarative mapping of XML files to ruby attributes
87
95
  * MyMapper.attributes_from_xml_path(xml) (also sets :xml_path)
88
96
 
89
97
  == Output
90
- { :title=>"Black on Both Sides", :allows_streaming=>true, :version_title=>"Extended Edition",
91
- :xml_path=>"/Users/tobias/Projects/xml_mapper/spec/fixtures/base.xml", :tracks_count=>2, :released_in=>1999,
92
- :released_on=>#<Date: 4902927/2,0,2299161>, :artist_name=>"Mos Def",
93
- :contributions=>[
94
- {:name=>"Mos Def", :role=>"artist"}, {:name=>"DJ Premier", :role=>"producer"}
95
- ],
96
- :artist_id=>1212, :country=>"DE",
98
+ {
99
+ :title=>"Black on Both Sides", :allows_streaming=>true, :version_title=>"Extended Edition",
97
100
  :tracks=>[
98
- { :track_title=>"Fear Not of Man", :allows_streaming=>false, :track_number=>1, :disk_number=>1,
99
- :explicit_lyrics=>true, :isrc=>"1234"
101
+ { :track_title=>"Fear Not of Man", :allows_streaming=>false, :track_number=>1, :version_title=>nil, :disk_number=>1,
102
+ :explicit_lyrics=>true, :contributions=>{:performer=>nil, :producer=>nil}, :isrc=>"1234"
100
103
  },
101
- { :track_title=>"Hip Hop", :allows_streaming=>true, :track_number=>2, :disk_number=>1,
102
- :explicit_lyrics=>false, :isrc=>"2345"
104
+ { :track_title=>"Hip Hop", :allows_streaming=>true, :track_number=>2, :version_title=>"Album Version", :disk_number=>1,
105
+ :explicit_lyrics=>false, :contributions=>{:performer=>"Mos Def", :producer=>"DJ Premier"}, :isrc=>"2345"
103
106
  }
104
- ]
107
+ ],
108
+ :tracks_count=>2, :released_in=>1999, :xml_path=>"/Users/tobias/Projects/xml_mapper/spec/fixtures/base.xml",
109
+ :released_on=>#<Date: 4902927/2,0,2299161>, :artist_name=>"Mos Def",
110
+ :contributions=>[ {:name=>"Mos Def", :role=>"artist"}, {:name=>"DJ Premier", :role=>"producer"} ]
111
+ :artist_id=>1212, :country=>"DE"
105
112
  }
106
113
 
107
114
  == Contributing to xml_mapper
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 0.4.2
data/lib/xml_mapper.rb CHANGED
@@ -123,13 +123,25 @@ class XmlMapper
123
123
  doc = xml_or_doc.is_a?(Nokogiri::XML::Node) ? xml_or_doc : Nokogiri::XML(xml_or_doc)
124
124
  doc = doc.root if doc.respond_to?(:root)
125
125
  atts = self.mappings.inject(xml_path.nil? ? {} : { :xml_path => xml_path }) do |hash, mapping|
126
- hash.merge(mapping[:key] => value_from_doc_and_mapping(doc, mapping))
126
+ if (value = value_from_doc_and_mapping(doc, mapping)) != :not_found
127
+ add_value_to_hash(hash, mapping[:key], value)
128
+ end
127
129
  end
128
130
  atts.instance_eval(&self.after_map_block) if self.after_map_block
129
131
  atts
130
132
  end
131
133
  end
132
134
 
135
+ def add_value_to_hash(hash, key_or_hash, value)
136
+ if key_or_hash.is_a?(Hash)
137
+ hash[key_or_hash.keys.first] ||= Hash.new
138
+ add_value_to_hash(hash[key_or_hash.keys.first], key_or_hash.values.first, value)
139
+ else
140
+ hash.merge!(key_or_hash => value)
141
+ end
142
+ hash
143
+ end
144
+
133
145
  def value_from_doc_and_mapping(doc, mapping)
134
146
  if mapping[:type] == :many
135
147
  mapping[:options][:mapper].attributes_from_xml(doc.search(mapping[:xpath]).to_a)
@@ -170,7 +182,9 @@ class XmlMapper
170
182
  end
171
183
 
172
184
  def inner_text_for_node(node)
173
- node.inner_text if node
185
+ if node
186
+ node.inner_text.length == 0 ? nil : node.inner_text
187
+ end
174
188
  end
175
189
 
176
190
  MAPPINGS = {
data/spec/example_spec.rb CHANGED
@@ -22,8 +22,16 @@ describe "ExampleSpec" do
22
22
  end
23
23
 
24
24
  [
25
- { :track_title => "Fear Not of Man", :track_number => 1, :disk_number => 1, :explicit_lyrics => true, :isrc => "1234" },
26
- { :track_title => "Hip Hop", :track_number => 2, :disk_number => 1, :explicit_lyrics => false, :isrc => "2345" },
25
+ {
26
+ :track_title => "Fear Not of Man", :track_number => 1, :disk_number => 1, :explicit_lyrics => true, :isrc => "1234",
27
+ :version_title => nil
28
+ },
29
+ {
30
+ :track_title => "Hip Hop", :track_number => 2, :disk_number => 1, :explicit_lyrics => false, :isrc => "2345",
31
+ :version_title => "Album Version", :contributions => {
32
+ :producer => "DJ Premier", :performer => "Mos Def"
33
+ }
34
+ },
27
35
  ].each_with_index do |hash, offset|
28
36
  hash.each do |key, value|
29
37
  it "extracts #{value.inspect} for #{key} for track with offset #{offset}" do
@@ -16,6 +16,7 @@
16
16
  <tracks>
17
17
  <track code="1234">
18
18
  <title>Fear Not of Man</title>
19
+ <version_title></version_title>
19
20
  <number>1</number>
20
21
  <disk>1</number>
21
22
  <explicit_lyrics />
@@ -25,8 +26,11 @@
25
26
  </track>
26
27
  <track code="2345">
27
28
  <title>Hip Hop</title>
29
+ <version_title>Album Version</version_title>
28
30
  <number>2</number>
29
31
  <disk>1</number>
32
+ <performer>Mos Def</performer>
33
+ <producer>DJ Premier</producer>
30
34
  <not_streamable_in>
31
35
  <country>at</country>
32
36
  </not_streamable_in>
data/spec/my_mapper.rb CHANGED
@@ -6,7 +6,7 @@ class MyMapper < XmlMapper
6
6
  integer :released_in # converts value to an integer
7
7
  text :country, :after_map => :upcase # calls after_map method on extracted value if value responds to the method
8
8
  text :released_on, :after_map => :parse_date # calls after_map method defined in Mapper class when value does not respond
9
- boolean :allows_streaming # maps Y, y, yes, true => true, N, n, no, false => false
9
+ boolean :allows_streaming # maps 1, Y, y, yes, true => true, 0, N, n, no, false => false
10
10
 
11
11
  within :artist do
12
12
  text :name => :artist_name # adds mapping for xpath "artist/name"
@@ -21,10 +21,14 @@ class MyMapper < XmlMapper
21
21
  many "tracks/track" => :tracks do # maps xpath "tracks/track" to array with key :tracks
22
22
  attribute :code => :isrc # map xml attribute "code" to :isrc
23
23
  text :title => :track_title
24
+ text :version_title
24
25
  integer :number => :track_number
25
26
  integer :disk => :disk_number
26
27
  exists :explicit_lyrics # checks if a node with the xpath exists
27
28
  not_exists "not_streamable_in/country[text()='de']" => :allows_streaming
29
+
30
+ text :performer => { :contributions => :performer }
31
+ text :producer => { :contributions => :producer }
28
32
  end
29
33
 
30
34
  after_map do # is called after attributes are extracted, self references the extracted attributes
@@ -72,6 +72,22 @@ describe "XmlMapper" do
72
72
  @mapper.attributes_from_xml(@xml).should == { :title => "Black on Both Sides", :artist_name => "Mos Def" }
73
73
  end
74
74
 
75
+ it "sets value to nil when value was empty string" do
76
+ @mapper.add_mapping(:text, :artist_name)
77
+ @mapper.attributes_from_xml("<album><artist_name></artist_name></album>").should == { :artist_name => nil }
78
+ end
79
+
80
+ it "assigns found keys to nested attributes" do
81
+ @mapper.add_mapping(:text, :artist_name => { :meta => :artist_name })
82
+ @mapper.add_mapping(:text, :title => { :meta => :title })
83
+ @mapper.attributes_from_xml(@xml).should == {
84
+ :meta => {
85
+ :artist_name => "Mos Def",
86
+ :title => "Black on Both Sides"
87
+ }
88
+ }
89
+ end
90
+
75
91
  describe "#exists" do
76
92
  it "returns true when node exists" do
77
93
  xml = %(<album><title>Black on Both Sides</title><rights><country>DE</country></rights></album>)
data/xml_mapper.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{xml_mapper}
8
- s.version = "0.4.1"
8
+ s.version = "0.4.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tobias Schwab"]
12
- s.date = %q{2010-12-01}
12
+ s.date = %q{2010-12-02}
13
13
  s.description = %q{Declarative XML to Ruby mapping}
14
14
  s.email = %q{tobias.schwab@dynport.de}
15
15
  s.extra_rdoc_files = [
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xml_mapper
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 11
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 4
9
- - 1
10
- version: 0.4.1
9
+ - 2
10
+ version: 0.4.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tobias Schwab
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-01 00:00:00 +01:00
18
+ date: 2010-12-02 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency