Class: Saxaphone::Element

Inherits:
Object
  • Object
show all
Defined in:
lib/saxaphone/element.rb

Defined Under Namespace

Classes: ElementHandler

Constant Summary collapse

@@base_class_name =
'Saxaphone::Element'

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name = '', content = '', attribute_array = []) ⇒ Element

Returns a new instance of Element.



199
200
201
202
203
204
205
206
207
208
# File 'lib/saxaphone/element.rb', line 199

def initialize(name = '', content = '', attribute_array = [])
  self.name = name
  self.content = content
  self.attributes = {}
  attribute_array.each do |key, value|
    assign_attribute_value(key, value) if self.class.stored_attributes.include?(key)
  end
  # self.attributes = Hash[attribute_array.select { |(key, value)| self.class.stored_attributes.include?(key) }]
  setup
end

Class Attribute Details

.attribute_aliasesObject

Returns the value of attribute attribute_aliases.



17
18
19
# File 'lib/saxaphone/element.rb', line 17

def attribute_aliases
  @attribute_aliases
end

.element_handlersObject

Returns the value of attribute element_handlers.



15
16
17
# File 'lib/saxaphone/element.rb', line 15

def element_handlers
  @element_handlers
end

.stored_attributesObject

Returns the value of attribute stored_attributes.



16
17
18
# File 'lib/saxaphone/element.rb', line 16

def stored_attributes
  @stored_attributes
end

Instance Attribute Details

#attributesObject

Returns the value of attribute attributes.



198
199
200
# File 'lib/saxaphone/element.rb', line 198

def attributes
  @attributes
end

#contentObject

Returns the value of attribute content.



198
199
200
# File 'lib/saxaphone/element.rb', line 198

def content
  @content
end

#nameObject

Returns the value of attribute name.



198
199
200
# File 'lib/saxaphone/element.rb', line 198

def name
  @name
end

Class Method Details

.element_attribute(element_name, options = {}) ⇒ Object

Define a single element that should be stored as an attribute.

WidgetElement < Saxaphone::Element
  element_attribute 'price'
end

element = WidgetElement.parse %{
  <widget>
    <price>4.33</price>
  </widget>
}

element.attributes # => {"price" => "4.33"}

The name of the stored attribute can optionally be changed with the :as option:

WidgetElement < Saxaphone::Element
  element_attribute 'price', as: 'dollars'
end

element = WidgetElement.parse %{
  <widget>
    <price>4.33</price>
  </widget>
}

element.attributes # => {"dollars" => "4.33"}


92
93
94
95
96
97
98
99
100
# File 'lib/saxaphone/element.rb', line 92

def element_attribute(element_name, options = {})
  if as = options.delete(:as)
    attribute_aliases[element_name] = as
  end

  has_element(element_name) do |element|
    assign_attribute_value(element.name, element.content)
  end
end

.element_attributes(element_names) ⇒ Object

Define elements that should be stored as attributes:

WidgetElement < Saxaphone::Element

element_attributes %w(color price)

end

element = WidgetElement.parse %{
  <widget>
    <color>red</color>
    <price>4.33</price>
  </widget>
}

element.attributes # => => “red”, “price” => “4.33”



58
59
60
61
62
# File 'lib/saxaphone/element.rb', line 58

def element_attributes(element_names)
  element_names.each do |element_name|
    element_attribute(element_name)
  end
end

.handler_for(element_name) ⇒ Object



189
190
191
# File 'lib/saxaphone/element.rb', line 189

def handler_for(element_name)
  element_handlers[element_name] || element_handlers['*']
end

.has_element(element_name, class_name = @@base_class_name, &block) ⇒ Object

Define what to do for a particular child element. After the element is parsed, it is passed to the block:

WidgetElement < Saxaphone::Element
  attr_accessor :cents

  has_element 'price' do |element|
    self.cents = element.content.to_f * 100
  end
end

element = WidgetElement.parse %{
  <widget>
    <price>4.33</price>
  </widget>
}

element.cents # => 433.0

It is possible to define the class name that is used to parse the child element:

PriceElement < Saxaphone::Element
  def cents
    content.to_f * 100
  end
end

WidgetElement < Saxaphone::Element
  attr_accessor :cents

  has_element 'price', 'PriceElement' do |element|
    self.cents = element.cents
  end
end

The children elements can have children of their own,
and each uses has_element to define what to do.


141
142
143
# File 'lib/saxaphone/element.rb', line 141

def has_element(element_name, class_name = @@base_class_name, &block)
  element_handlers[element_name] = ElementHandler.new(class_name, block)
end

.inherited(base) ⇒ Object



19
20
21
22
23
# File 'lib/saxaphone/element.rb', line 19

def inherited(base)
  base.element_handlers   = element_handlers.dup
  base.stored_attributes  = stored_attributes.dup
  base.attribute_aliases  = attribute_aliases.dup
end

.parse(xml) ⇒ Object



193
194
195
# File 'lib/saxaphone/element.rb', line 193

def parse(xml)
  Saxaphone::Document.parse(xml, self)
end

.setup(&block) ⇒ Object

A block can be passed to setup, which is called after the element is initialized.

 WidgetElement < Saxaphone::Element
   attr_accessor :foo

   setup do
     self.foo = 'bar'
   end
 end

It is recommended to use setup rather than
overriding initialize.


39
40
41
# File 'lib/saxaphone/element.rb', line 39

def setup(&block)
  define_method(:setup, &block)
end

.store_attribute(attribute_name, options = {}) ⇒ Object

Define a white listed attribute that is extracted from the XML element and stored in the attribute hash:

WidgetElement < Saxaphone::Element
  store_attribute 'href', as: 'uri'
end

element = WidgetElement.parse %{
  <widget href="http://www.example.com" color="red" price="3.21">
    ...
  </widget>
}

element.attributes # => {"uri" => "http://www.example.com"}


181
182
183
184
185
186
187
# File 'lib/saxaphone/element.rb', line 181

def store_attribute(attribute_name, options = {})
  if as = options.delete(:as)
    attribute_aliases[attribute_name] = as
  end

  self.stored_attributes << attribute_name
end

.store_attributes(*attribute_names) ⇒ Object

Define a white list of the attributes that are extracted from the XML element and stored in the attribute hash:

WidgetElement < Saxaphone::Element
  store_attributes 'name', 'color'
end

element = WidgetElement.parse %{
  <widget name="Acme" color="red" price="3.21">
    ...
  </widget>
}

element.attributes # => {"name" => "Acme", "color" => "red"}

Notice that the “price” attribute is not stored.



162
163
164
# File 'lib/saxaphone/element.rb', line 162

def store_attributes(*attribute_names)
  self.stored_attributes += attribute_names.flatten.to_set
end

Instance Method Details

#add_element(element) ⇒ Object



213
214
215
216
217
# File 'lib/saxaphone/element.rb', line 213

def add_element(element)
  if element_handler = self.class.handler_for(element.name)
    instance_exec(element, &element_handler.proc) if element_handler.proc
  end
end

#append_content(string) ⇒ Object



232
233
234
# File 'lib/saxaphone/element.rb', line 232

def append_content(string)
  content << string
end

#assign_attribute_value(key, value) ⇒ Object



228
229
230
# File 'lib/saxaphone/element.rb', line 228

def assign_attribute_value(key, value)
  attributes[self.class.attribute_aliases[key] || key] = value
end

#element_for(element_name) ⇒ Object



219
220
221
222
223
224
225
226
# File 'lib/saxaphone/element.rb', line 219

def element_for(element_name)
  if element_handler = self.class.handler_for(element_name)
    Saxaphone::Util.constantize(element_handler.class_name)
  else
    Saxaphone::Element
  end
  
end

#setupObject



210
211
# File 'lib/saxaphone/element.rb', line 210

def setup
end