class Atom::Element

Atom::Element

Base Element Object Class

You don't use this class directly. This is a base class of each element classes used in Atom Syndication Format.

Attributes

elem[R]

accessor for xml-element(REXML::Element) object.

Public Class Methods

element_attr_accessor(name) click to toggle source

Attribute accessor generator

# File lib/atomutil.rb, line 423
    def self.element_attr_accessor(name)
      name = name.to_s
      name.tr!('-', '_')
      class_eval(<<-EOS, __FILE__, __LINE__)
        def #{name}
          get_attr('#{name}')
        end
        def #{name}=(value)
          set_attr('#{name}', value)
        end
      EOS
    end
element_attr_accessors(*names) click to toggle source

You can generate attribute accessor at once.

# File lib/atomutil.rb, line 436
def self.element_attr_accessors(*names)
  names.each{ |n| element_attr_accessor(n) }
end
element_datetime_accessor(name) click to toggle source

Generate datetime element accessor for indicated name.

Example:

class Entry < BaseEntry
  element_datetime_accessor :updated
  element_datetime_accessor :published
end
entry = Entry.new
entry.updated = Time.now
puts entry.updated.year
puts entry.updated.month
# File lib/atomutil.rb, line 321
    def self.element_datetime_accessor(name)
      name = name.to_s
      name.tr!('-', '_')
      class_eval(<<-EOS, __FILE__, __LINE__)
        def #{name}
          dt = get(@ns, '#{name}')
          dt.nil? ? nil : Time.iso8601(dt.text)
        end
        def #{name}=(value, attributes=nil)
          case value
            when Time
              date = value.iso8601
            else
              date = value
          end
          set(@ns, '#{name}', date, attributes)
        end
      EOS
    end
element_datetime_accessors(*names) click to toggle source

You can set datetime accessor at once with this method

Example:

class Entry < BaseEntry
  element_datetime_accessor :updated, :published
end
entry = Entry.new
entry.updated = Time.now
puts entry.updated.year
puts entry.updated.month
# File lib/atomutil.rb, line 351
def self.element_datetime_accessors(*names)
  names.each{ |n| element_datetime_accessor(n) }
end
element_name(name=nil) click to toggle source
# File lib/atomutil.rb, line 248
def self.element_name(name=nil)
  unless name.nil?
    @element_name = name.to_s
  end
  @element_name
end
element_ns(ns=nil) click to toggle source
# File lib/atomutil.rb, line 255
def self.element_ns(ns=nil)
  unless ns.nil?
    @element_ns = ns.is_a?(Namespace) ? ns : Namespace.new(:uri => ns)
  end
  @element_ns
end
element_object_list_accessor(name, ext_class, moniker=nil) click to toggle source

Generate useful accessor for the multiple element

Example:

class Entry < Element
  element_object_list_accessors :author, Author, :authors
  element_object_list_accessors :contributor, Contributor, :contributors
end
# File lib/atomutil.rb, line 394
    def self.element_object_list_accessor(name, ext_class, moniker=nil)
      name = name.to_s
      name.tr!('-', '_')
      unless moniker.nil?
        moniker = moniker.to_s
        moniker.tr!('-', '_')
      end
      elem_ns = ext_class.element_ns || ns
      class_eval(<<-EOS, __FILE__, __LINE__)
        def #{name}
          get_object('#{elem_ns}', '#{name}', #{ext_class})
        end
        def #{name}=(stuff)
          set('#{elem_ns}', '#{name}', stuff)
        end
        def add_#{name}(stuff)
          add('#{elem_ns}', '#{name}', stuff)
        end
      EOS
      class_eval(<<-EOS, __FILE__, __LINE__) unless moniker.nil?
        def #{moniker}
          get_objects('#{elem_ns}', '#{name}', #{ext_class})
        end
        def #{moniker}=(stuff)
          #{name} = stuff
        end
      EOS
    end
element_text_accessor(name) click to toggle source

Generate element accessor for indicated name The generated accessors can deal with elements which has only simple text-node, such as title, summary, rights, and etc. Of course, these elements should handle more complex data. In such a case, you can control them directly with 'set' and 'get' method.

Example:

class Entry < Element
  element_text_accessor 'title'
  element_text_accessor 'summary'
end

elem = MyElement.new
elem.title   = "foo"
elem.summary = "bar"
puts elem.title #foo
puts elem.summary #bar

div = REXML::Element.new("<div><p>hoge</p></div>")
elem.set('http://www.w3.org/2005/Atom', 'title', div, { :type => 'xhtml' })
# File lib/atomutil.rb, line 283
    def self.element_text_accessor(name)
      name = name.to_s
      name.tr!('-', '_')
      class_eval(<<-EOS, __FILE__, __LINE__)
        def #{name}
          value = get(@ns, '#{name}')
          value.nil? ? nil : value.text
        end
        def #{name}=(value, attributes=nil)
          set(@ns, '#{name}', value, attributes)
        end
      EOS
    end
element_text_accessors(*names) click to toggle source

You can set text_accessor at once with this method

Example:

class Entry < BaseEntry
  element_text_accessors :title, :summary
end
entry = Entry.new
entry.title = "hoge"
puts entry.title #hoge
# File lib/atomutil.rb, line 306
def self.element_text_accessors(*names)
  names.each{ |n| element_text_accessor(n) }
end
element_text_list_accessor(name, moniker=nil) click to toggle source

Generates text accessor for multiple value.

Example:

# File lib/atomutil.rb, line 357
    def self.element_text_list_accessor(name, moniker=nil)
      name = name.to_s
      name.tr!('-', '_')
      unless moniker.nil?
        moniker = moniker.to_s
        moniker.tr!('-', '_')
      end
      elem_ns = element_ns || ns
      class_eval(<<-EOS, __FILE__, __LINE__)
        def #{name}
          value = getlist('#{elem_ns}', '#{name}')
          value.empty?? nil : value.first
        end
        def #{name}=(stuff)
          set('#{elem_ns}', '#{name}', stuff)
        end
        def add_#{name}(stuff)
          add('#{elem_ns}', '#{name}', stuff)
        end
      EOS
      class_eval(<<-EOS, __FILE__, __LINE__) unless moniker.nil?
        def #{moniker}
          getlist('#{elem_ns}', '#{name}')
        end
        def #{moniker}=(stuff)
          #{name} = stuff
        end
      EOS
    end
new(params={}) { |obj| ... } click to toggle source
Calls superclass method
# File lib/atomutil.rb, line 235
def self.new(params={})
  obj = super(params)
  yield(obj) if block_given?
  obj
end
new(params={}) click to toggle source

Setup element.

# File lib/atomutil.rb, line 441
def initialize(params={})
  @ns = params.has_key?(:namespace) ? params[:namespace] \
      : self.class.element_ns       ? self.class.element_ns \
      :                               self.class.ns
  @elem = params.has_key?(:elem) ? params[:elem] : REXML::Element.new(self.class.element_name)
  if @ns.is_a?(Namespace)
    unless @ns.prefix.nil?
      @elem.add_namespace @ns.prefix, @ns.uri
    else
      @elem.add_namespace @ns.uri
    end
  else
    @elem.add_namespace @ns
  end
  params.keys.each do |key|
    setter = "#{key}=";
    send(setter.to_sym, params[key]) if respond_to?(setter.to_sym)
  end
end
ns(ns=nil) click to toggle source
# File lib/atomutil.rb, line 241
def self.ns(ns=nil)
  unless ns.nil?
    @@ns = ns.is_a?(Namespace) ? ns : Namespace.new(:uri => ns)
  end
  @@ns
end

Public Instance Methods

add(ns, element_name, value, attributes={}) click to toggle source

Same as 'set', but when a element-name confliction occurs, append new element without overriding.

# File lib/atomutil.rb, line 505
def add(ns, element_name, value, attributes={})
  element = REXML::Element.new(element_name)
  if ns.is_a?(Namespace)
    unless ns.prefix.nil? || ns.prefix.empty?
      element.name = "#{ns.prefix}:#{element_name}"
      element.add_namespace ns.prefix, ns.uri unless @ns == ns || @ns == ns.uri
    else
      element.add_namespace ns.uri unless @ns == ns || @ns == ns.uri
    end
  else
    element.add_namespace ns unless @ns == ns || @ns.to_s == ns
  end
  if value.is_a?(Element)
    value.elem.each_element do |e|
      element.add e.deep_clone
    end
    value.elem.attributes.each_attribute do |a|
      unless a.name =~ /^xmlns(?:\:)?/
        element.add_attribute a
      end
    end
    #element.text = value.elem.text unless value.elem.text.nil?
    text = value.elem.get_text
    unless text.nil?
      element.text = REXML::Text.new(text.to_s, true, nil, true)
    end
  else
    if value.is_a?(REXML::Element)
      element.add_element value.deep_clone
    else
      element.add_text value.to_s
    end
  end
  element.add_attributes attributes unless attributes.nil?
  @elem.add_element element
end
get(ns, element_name) click to toggle source

Get indicated element. If it matches multiple, returns first one.

elem = entry.get('http://example/2007/mynamespace', 'foo')

ns = Atom::Namespace.new(:prefix => 'dc', :uri => 'http://purl.org/dc/elements/1.1/')
elem = entry.get(ns, 'subject')
# File lib/atomutil.rb, line 549
def get(ns, element_name)
  getlist(ns, element_name).first
end
get_attr(name) click to toggle source

Get attribute value for indicated key

# File lib/atomutil.rb, line 587
def get_attr(name)
  @elem.attributes[name.to_s]
end
get_object(ns, element_name, ext_class) click to toggle source

Get indicated elements as an object of the class you passed as thrid argument.

ns = Atom::Namespace.new(:uri => 'http://example.com/ns#')
obj = entry.get_object(ns, 'mytag', MyClass)
puts obj.class #MyClass

MyClass should inherit Atom::Element

# File lib/atomutil.rb, line 568
def get_object(ns, element_name, ext_class)
  elements = getlist(ns, element_name)
  return nil if elements.empty?
  ext_class.new(:namespace => ns, :elem => elements.first)
end
get_objects(ns, element_name, ext_class) click to toggle source

Get all indicated elements as an object of the class you passed as thrid argument.

entry.get_objects(ns, 'mytag', MyClass).each{ |obj|
  p obj.class #MyClass
}
# File lib/atomutil.rb, line 579
def get_objects(ns, element_name, ext_class)
  elements = getlist(ns, element_name)
  return [] if elements.empty?
  elements.collect do |e|
    ext_class.new(:namespace => ns, :elem => e)
  end
end
getlist(ns, element_name) click to toggle source

Get indicated elements as array

ns = Atom::Namespace.new(:prefix => 'dc', :uri => 'http://purl.org/dc/elements/1.1/')
elems = entry.getlist(ns, 'subject')
# File lib/atomutil.rb, line 557
def getlist(ns, element_name)
  @elem.get_elements(child_xpath(ns, element_name))
end
set_attr(name, value) click to toggle source

Set attribute value for indicated key

# File lib/atomutil.rb, line 591
def set_attr(name, value)
  @elem.attributes[name.to_s] = value
end
to_s(*) click to toggle source

Convert to XML-Document and return it as string

# File lib/atomutil.rb, line 595
def to_s(*)
  doc = REXML::Document.new
  decl = REXML::XMLDecl.new("1.0", "utf-8")
  doc.add decl
  doc.add_element @elem
  doc.to_s
end

Private Instance Methods

child_xpath(ns, element_name, attributes=nil) click to toggle source

Get a xpath string to traverse child elements with namespace and name.

# File lib/atomutil.rb, line 604
def child_xpath(ns, element_name, attributes=nil)
  ns_uri = ns.is_a?(Namespace) ? ns.uri : ns
  unless !attributes.nil? && attributes.is_a?(Hash)
    "child::*[local-name()='#{element_name}' and namespace-uri()='#{ns_uri}']"
  else
    attr_str = attributes.collect{|key, val| "@#{key.to_s}='#{val}'"}.join(' and ')
    "child::*[local-name()='#{element_name}' and namespace-uri()='#{ns_uri}' and #{attr_str}]"
  end
end