Class: ROXO

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/roxo.rb

Overview

Ruby Objects as XML Objects

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(xml) ⇒ ROXO

Returns a new instance of ROXO.



20
21
22
23
24
25
26
# File 'lib/roxo.rb', line 20

def initialize(xml)
  xml = ::LibXML::XML::Parser.string(xml).parse.root unless xml.kind_of?(LibXML::XML::Node)

  @raw, @name, @attributes = xml, xml.name, xml.attributes.to_h
  @children = xml.children.select(&:element?).group_by{|c|c.name.to_sym}
  @value = xml.children.select{|e|e.text? or e.cdata?}.map{|e|e.to_s.chomp(']]>').sub('<![CDATA[','')}.join
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/roxo.rb', line 50

def method_missing(sym, *args)
  if terminal? # Proxy all method calls to the wrapped object.
    return @value.send(sym, *args)
  elsif sym.to_s =~ /\?$/ # re-dispatch without question mark, interpret result as a boolean.
    node = send(sym.to_s[0..-2].to_sym, *args)
    return node ? %w{yes true t y}.include?(node.downcase) : nil
  elsif @children[sym]
    x = self.class.new(@children[sym].first)
    return x.terminal? ? x.value : x
  elsif @attributes[sym.to_s]
    return @attributes[sym.to_s]
  elsif @children[sing = sym.to_s.singularize.to_sym]
    return @children[sing].map{|e|self.class.new(e)}
  end 
end

Instance Attribute Details

#childrenObject (readonly)

Returns the value of attribute children.



10
11
12
# File 'lib/roxo.rb', line 10

def children
  @children
end

#nameObject (readonly)

Returns the value of attribute name.



10
11
12
# File 'lib/roxo.rb', line 10

def name
  @name
end

#rawObject (readonly)

Returns the value of attribute raw.



10
11
12
# File 'lib/roxo.rb', line 10

def raw
  @raw
end

#valueObject (readonly)

Returns the value of attribute value.



10
11
12
# File 'lib/roxo.rb', line 10

def value
  @value
end

Instance Method Details

#<=>(other) ⇒ Object

A node is terminal if we can’t descend any further



36
37
38
39
40
41
42
43
44
# File 'lib/roxo.rb', line 36

def <=>(other)
  return -1 unless (self.class == other.class)
  return z unless (z = self.__attributes <=> other.__attributes).zero?
  return z unless (z = self.value.strip <=> other.value.strip).zero?
  return z unless (z = self.name <=> other.name).zero?

  nodes = lambda{|obj|obj.children.values.flatten.map{|n|self.class.new(n)}}
  nodes[self] <=> nodes[other]
end

#==(o) ⇒ Object



46
47
48
# File 'lib/roxo.rb', line 46

def ==(o)
  self.<=>(o) == 0
end

#[](o) ⇒ Object

Only lookup attributes



13
# File 'lib/roxo.rb', line 13

def        [](o); @attributes[o.to_s];    end

#__attributesObject



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

def __attributes
  @attributes.sort.reject{|k,v|k.to_s =~ /^xmlns/}
end

#attributesObject



11
# File 'lib/roxo.rb', line 11

def   attributes; @attributes.keys;       end

#has?(o) ⇒ Boolean

Boolean. Does this exist?

Returns:

  • (Boolean)


12
# File 'lib/roxo.rb', line 12

def      has?(o); !! send(o);             end

#inspectObject



28
29
30
# File 'lib/roxo.rb', line 28

def inspect
  terminal? ? value.inspect : "#<ROXO:0x#{object_id.to_s(16)} @name=\"#{@name}\", ...>"
end

#terminal?Boolean

Returns:

  • (Boolean)


32
33
34
# File 'lib/roxo.rb', line 32

def terminal? 
  @children.size.zero? and @attributes.blank?
end

#to_sObject



14
# File 'lib/roxo.rb', line 14

def         to_s; @value;                 end