saxaphone 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,36 +8,149 @@ module Saxaphone
8
8
  end
9
9
 
10
10
  class << self
11
+ # A block can be passed to <tt>setup</tt>,
12
+ # which is called after the element is initialized.
13
+ #
14
+ # WidgetElement < Saxaphone::Element
15
+ # attr_accessor :foo
16
+ #
17
+ # setup do
18
+ # self.foo = 'bar'
19
+ # end
20
+ # end
21
+ #
22
+ # It is recommended to use setup rather than
23
+ # overriding initialize.
24
+ #
11
25
  def setup(&block)
12
26
  define_method(:setup, &block)
13
27
  end
14
28
 
29
+ # Define elements that should be stored as attributes:
30
+ #
31
+ # WidgetElement < Saxaphone::Element
32
+ # element_attributes %w(color price)
33
+ # end
34
+ #
35
+ # element = WidgetElement.parse %{
36
+ # <widget>
37
+ # <color>red</color>
38
+ # <price>4.33</price>
39
+ # </widget>
40
+ # }
41
+ #
42
+ # element.attributes # => {"color" => "red", "price" => "4.33"}
43
+ #
15
44
  def element_attributes(element_names)
16
45
  element_names.each do |element_name|
17
46
  element_attribute(element_name)
18
47
  end
19
48
  end
20
49
 
50
+ # Define a single element that should be stored as an attribute.
51
+ #
52
+ # WidgetElement < Saxaphone::Element
53
+ # element_attribute 'price'
54
+ # end
55
+ #
56
+ # element = WidgetElement.parse %{
57
+ # <widget>
58
+ # <price>4.33</price>
59
+ # </widget>
60
+ # }
61
+ #
62
+ # element.attributes # => {"price" => "4.33"}
63
+ #
64
+ # The name of the stored attribute can optionally be changed
65
+ # with the <tt>:as</tt> option:
66
+ #
67
+ # WidgetElement < Saxaphone::Element
68
+ # element_attribute 'price', as: 'dollars'
69
+ # end
70
+ #
71
+ # element = WidgetElement.parse %{
72
+ # <widget>
73
+ # <price>4.33</price>
74
+ # </widget>
75
+ # }
76
+ #
77
+ # element.attributes # => {"dollars" => "4.33"}
21
78
  def element_attribute(element_name, options = {})
22
- converted_name = options.delete(:as) || element_name
23
- logic = proc { |element| attributes[converted_name] = element.content }
24
- element_handler = ElementHandler.new(@@base_class_name, logic)
79
+ converted_name = options.delete(:as)
25
80
 
26
- element_handlers[element_name] = element_handler
81
+ has_element(element_name) do |element|
82
+ attributes[converted_name || element.name] = element.content
83
+ end
27
84
  end
28
85
 
86
+ # Define what to do for a particular child element.
87
+ # After the element is parsed, it is passed to the block:
88
+ #
89
+ # WidgetElement < Saxaphone::Element
90
+ # attr_accessor :cents
91
+ #
92
+ # has_element 'price' do |element|
93
+ # self.cents = element.content.to_f * 100
94
+ # end
95
+ # end
96
+ #
97
+ # element = WidgetElement.parse %{
98
+ # <widget>
99
+ # <price>4.33</price>
100
+ # </widget>
101
+ # }
102
+ #
103
+ # element.cents # => 433.0
104
+ #
105
+ # It is possible to define the class name that is used
106
+ # to parse the child element:
107
+ #
108
+ # PriceElement < Saxaphone::Element
109
+ # def cents
110
+ # content.to_f * 100
111
+ # end
112
+ # end
113
+ #
114
+ # WidgetElement < Saxaphone::Element
115
+ # attr_accessor :cents
116
+ #
117
+ # has_element 'price', 'PriceElement' do |element|
118
+ # self.cents = element.cents
119
+ # end
120
+ # end
121
+ #
122
+ # The children elements can have children of their own,
123
+ # and each uses has_element to define what to do.
124
+ #
29
125
  def has_element(element_name, class_name = @@base_class_name, &block)
30
126
  element_handlers[element_name] = ElementHandler.new(class_name, block)
31
127
  end
32
128
 
129
+ # Define a white list of the attributes that are extracted
130
+ # from the XML element and stored in the attribute hash:
131
+ #
132
+ # WidgetElement < Saxaphone::Element
133
+ # store_attributes 'name', 'color'
134
+ # end
135
+ #
136
+ # element = WidgetElement.parse %{
137
+ # <widget name="Acme" color="red" price="3.21">
138
+ # ...
139
+ # </widget>
140
+ # }
141
+ #
142
+ # element.attributes # => {"name" => "Acme", "color" => "red"}
143
+ #
144
+ # Notice that the "price" attribute is not stored.
145
+ #
33
146
  def store_attributes(*attribute_names)
34
147
  @stored_attributes = attribute_names.flatten.to_set
35
148
  end
36
149
 
37
- def element_handlers
38
- @element_handlers ||= {}
150
+ def handler_for(element_name)
151
+ element_handlers[element_name] || element_handlers['*']
39
152
  end
40
-
153
+
41
154
  def stored_attributes
42
155
  @stored_attributes ||= Set.new
43
156
  end
@@ -45,6 +158,11 @@ module Saxaphone
45
158
  def parse(xml)
46
159
  Saxaphone::Document.parse(xml, self)
47
160
  end
161
+
162
+ private
163
+ def element_handlers
164
+ @element_handlers ||= {}
165
+ end
48
166
  end
49
167
 
50
168
  attr_accessor :name, :content, :attributes
@@ -59,13 +177,13 @@ module Saxaphone
59
177
  end
60
178
 
61
179
  def add_element(element)
62
- if element_handler = self.class.element_handlers[element.name]
180
+ if element_handler = self.class.handler_for(element.name)
63
181
  instance_exec(element, &element_handler.proc) if element_handler.proc
64
182
  end
65
183
  end
66
184
 
67
185
  def element_for(element_name)
68
- if element_handler = self.class.element_handlers[element_name]
186
+ if element_handler = self.class.handler_for(element_name)
69
187
  Saxaphone::Util.constantize(element_handler.class_name)
70
188
  else
71
189
  Saxaphone::Element
data/test/element_test.rb CHANGED
@@ -43,12 +43,42 @@ class Saxaphone::ElementTest < MiniTest::Spec
43
43
  element_attribute 'faz', as: 'baz'
44
44
  end
45
45
 
46
- element.add_element(Saxaphone::Element.new('faz', 'value'))
46
+ element.add_element(Saxaphone::Element.new('faz', 'value1'))
47
+ element.add_element(Saxaphone::Element.new('foo', 'value2'))
47
48
 
48
- assert_equal({'baz' => 'value'}, element.attributes)
49
+ assert_equal({'baz' => 'value1'}, element.attributes)
50
+ end
51
+
52
+ def test_element_attribute_with_any
53
+ element = define_element do
54
+ element_attribute 'faz', as: 'baz'
55
+ element_attribute '*'
56
+ end
57
+
58
+ element.add_element(Saxaphone::Element.new('faz', 'value1'))
59
+ element.add_element(Saxaphone::Element.new('foo', 'value2'))
60
+
61
+ assert_equal({'baz' => 'value1', 'foo' => 'value2'}, element.attributes)
49
62
  end
50
63
 
51
64
  def test_has_element_with_block
65
+ element = define_element do
66
+ attr_accessor :child_content
67
+
68
+ has_element 'omg' do |element|
69
+ self.child_content = element.content
70
+ end
71
+ end
72
+
73
+ child_element = element.element_for('omg').new('omg')
74
+ child_element.content = 'weee'
75
+ element.add_element(child_element)
76
+
77
+ assert_kind_of Saxaphone::Element, child_element
78
+ assert_equal 'weee', element.child_content
79
+ end
80
+
81
+ def test_has_element_with_block_and_custom_element
52
82
  element = define_element do
53
83
  attr_accessor :child_special
54
84
 
@@ -58,14 +88,28 @@ class Saxaphone::ElementTest < MiniTest::Spec
58
88
  end
59
89
 
60
90
  child_element = element.element_for('omg').new('omg')
91
+ child_element.special = 'weee'
92
+ element.add_element(child_element)
61
93
 
62
94
  assert_kind_of TestChildElement, child_element
63
- child_element.special = 'weee'
95
+ assert_equal 'weee', element.child_special
96
+ end
97
+
98
+ def test_has_element_with_any
99
+ element = define_element do
100
+ has_element '*' do |element|
101
+ self.attributes[element.name.upcase] = element.content
102
+ end
103
+ end
104
+
105
+ child_element = element.element_for('faz').new('faz')
106
+ child_element.content = 'weee'
64
107
  element.add_element(child_element)
65
108
 
66
- assert_equal 'weee', element.child_special
109
+ assert_kind_of Saxaphone::Element, child_element
110
+ assert_equal({'FAZ' => 'weee'}, element.attributes)
67
111
  end
68
-
112
+
69
113
  def test_has_element_without_block
70
114
  element = define_element do
71
115
  has_element 'wtf', 'Saxaphone::ElementTest::TestChildElement'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saxaphone
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-07-18 00:00:00.000000000 -07:00
13
- default_executable:
12
+ date: 2011-11-08 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: nokogiri
17
- requirement: &2162445820 !ruby/object:Gem::Requirement
16
+ requirement: &70201937138840 !ruby/object:Gem::Requirement
18
17
  none: false
19
18
  requirements:
20
19
  - - ! '>='
@@ -22,7 +21,7 @@ dependencies:
22
21
  version: '0'
23
22
  type: :runtime
24
23
  prerelease: false
25
- version_requirements: *2162445820
24
+ version_requirements: *70201937138840
26
25
  description: Use objects
27
26
  email: developer@matthewhiggins.com
28
27
  executables: []
@@ -40,7 +39,6 @@ files:
40
39
  - test/document_test.rb
41
40
  - test/element_test.rb
42
41
  - test/test_helper.rb
43
- has_rdoc: true
44
42
  homepage: http://github.com/matthuhiggins/saxaphone
45
43
  licenses: []
46
44
  post_install_message:
@@ -61,7 +59,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
61
59
  version: 1.3.5
62
60
  requirements: []
63
61
  rubyforge_project:
64
- rubygems_version: 1.6.2
62
+ rubygems_version: 1.8.10
65
63
  signing_key:
66
64
  specification_version: 3
67
65
  summary: Object Oriented SAX Parsing