class Ox::Element

An Element represents a element of an XML document. It has a name, attributes, and sub-nodes.

To access the child elements or attributes there are several options. One is to walk the nodes and attributes. Another is to use the locate() method. The easiest for simple regularly formatted XML is to reference the sub elements or attributes simply by name. Repeating elements with the same name can be referenced with an element count as well. A few examples should explain the 'easy' API more clearly.


doc = Ox.parse(%{
  <Person age="58">

=> "Peter"
=> "Makie"
=> "58"

Public Class Methods

new(name) click to toggle source

Creates a new Element with the specified name.

  • name [String] name of the Element

Calls superclass method
# File lib/ox/element.rb, line 41
def initialize(name)
  @attributes = {}
  @nodes = []

Public Instance Methods

<<(node) click to toggle source

Appends a Node to the Element's nodes array. Returns the element itself so multiple appends can be chained together.

  • node [Node] Node to append to the nodes array

# File lib/ox/element.rb, line 59
def <<(node)
  raise "argument to << must be a String or Ox::Node." unless node.is_a?(String) or node.is_a?(Node)
  @nodes = [] if !instance_variable_defined?(:@nodes) or @nodes.nil?
  @nodes << node
Alias for: eql?
alocate(path, found) click to toggle source
  • path [Array] array of steps in a path

  • found [Array] matching nodes

# File lib/ox/element.rb, line 191
def alocate(path, found)
  step = path[0]
  if step.start_with?('@') # attribute
    raise unless 1 == path.size
    if instance_variable_defined?(:@attributes)
      step = step[1..-1]
      sym_step = step.to_sym
      @attributes.each do |k,v|
        found << v if ('?' == step or k == step or k == sym_step)
  else # element name
    if (i = step.index('[')).nil? # just name
      name = step
      qual = nil
      name = step[0..i-1]
      raise unless step.end_with?(']')
      i += 1
      qual = step[i..i] # step[i] would be better but some rubies (jruby, ree, rbx) take that as a Fixnum.
      if '0' <= qual and qual <= '9'
        qual = '+'
        i += 1
      index = step[i..-2].to_i
    if '?' == name or '*' == name
      match = nodes
    elsif '^' == name[0..0] # 1.8.7 thinks name[0] is a fixnum
      case name[1..-1]
       when 'Element'
        match = { |e| e.is_a?(Element) }
       when 'String', 'Text'
        match = { |e| e.is_a?(String) }
      when 'Comment'
        match = { |e| e.is_a?(Comment) }
      when 'CData'
        match = { |e| e.is_a?(CData) }
      when 'DocType'
        match = { |e| e.is_a?(DocType) }
        #puts "*** no match on #{name}"
        match = []
      match = { |e| e.is_a?(Element) and name == }
    unless qual.nil? or match.empty?
      case qual
      when '+'
        match = index < match.size ? [match[index]] : []
      when '-'
        match = index <= match.size ? [match[-index]] : []
      when '<'
        match = 0 < index ? match[0..index - 1] : []
      when '>'
        match = index <= match.size ? match[index + 1..-1] : []
    if (1 == path.size)
      match.each { |n| found << n }
    elsif '*' == name
      match.each { |n| n.alocate(path, found) if n.is_a?(Element) }
      match.each { |n| n.alocate(path[1..-1], found) if n.is_a?(Element) }
      match.each { |n| n.alocate(path[1..-1], found) if n.is_a?(Element) }
eql?(other) click to toggle source

Returns true if this Object and other are of the same type and have the equivalent value and the equivalent elements otherwise false is returned.

  • other [Object] Object compare self to.

return [Boolean] true if both Objects are equivalent, otherwise false.

Calls superclass method
# File lib/ox/element.rb, line 70
def eql?(other)
  return false if (other.nil? or self.class != other.class)
  return false unless super(other)
  return false unless self.attributes == other.attributes
  return false unless self.nodes == other.nodes
Also aliased as: ==
locate(path) click to toggle source

Returns an array of Nodes or Strings that correspond to the locations specified by the path parameter. The path parameter describes the path to the return values which can be either nodes in the XML or attributes. The path is a relative description. There are similarities between the locate() method and XPath but locate does not follow the same rules as XPath. The syntax is meant to be simpler and more Ruby like.

Like XPath the path delimiters are the slash (/) character. The path is split on the delimiter and each element of the path then describes the child of the current Element to traverse.

Attributes are specified with an @ prefix.

Each element name in the path can be followed by a bracket expression that narrows the paths to traverse. Supported expressions are numbers with a preceeding qualifier. Qualifiers are -, +, <, and >. The + qualifier is the default. A - qualifier indicates the index begins at the end of the children just like for Ruby Arrays. The < and > qualifiers indicates all elements either less than or greater than should be matched. Note that unlike XPath, the element index starts at 0 similar to Ruby be contrary to XPath.

Element names can also be wildcard characters. A * indicates any decendent should be followed. A ? indicates any single Element can match the wildcard. A ^ character followed by the name of a Class will match any node of the specified class. Valid class names are Element, Comment, String (or Text), CData, DocType.

Examples are:

  • element.locate("Family/Pete ") returns all children of the Pete Element.

  • element.locate("Family/?[1]") returns the first element in the Family Element.

  • element.locate("Family/?[<3]") returns the first 3 elements in the Family Element.

  • element.locate("Family/?/@age") returns the arg attribute for each child in the Family Element.

  • element.locate("Family/ @type") returns the type attribute value for decendents of the Family.

  • element.locate("Family/^Comment") returns any comments that are a child of Family.

  • path [String] path to the Nodes to locate

# File lib/ox/element.rb, line 131
def locate(path)
  return [self] if path.nil?
  found = []
  pa = path.split('/')
  if '*' == path[0]
    # a bit of a hack but it allows self to be checked as well
    e ='')
    e << self
    e.alocate(pa, found)
    alocate(pa, found)
method_missing(id, *args, &block) click to toggle source

Handles the 'easy' API that allows navigating a simple XML by referencing elements and attributes by name.

  • id [Symbol] element or attribute name

return [Element|Node|String|nil] the element, attribute value, or Node identifed by the name

raise [NoMethodError] if no match is found

# File lib/ox/element.rb, line 152
def method_missing(id, *args, &block)
  has_some = false
  ids = id.to_s
  i = args[0].to_i # will be 0 if no arg or parsing fails
  nodes.each do |n|
    if (n.is_a?(Element) || n.is_a?(Instruct)) && (n.value == id || n.value == ids)
      return n if 0 == i
      has_some = true
      i -= 1
  if instance_variable_defined?(:@attributes)
    return @attributes[id] if @attributes.has_key?(id)
    return @attributes[ids] if @attributes.has_key?(ids)
  return nil if has_some
  raise"#{ids} not found", name)
nodes() click to toggle source

Returns the Element's nodes array. These are the sub-elements of this Element. return [Array] all child Nodes.

# File lib/ox/element.rb, line 51
def nodes
  @nodes = [] if !instance_variable_defined?(:@nodes) or @nodes.nil?
replace_text(txt) click to toggle source

Clears any child nodes of an element and replaces those with a single Text (String) node. Note the existing nodes array is modified and not replaced.

  • txt [String] to become the only element of the nodes array

# File lib/ox/element.rb, line 89
def replace_text(txt)
  raise "the argument to replace_text() must be a String" unless txt.is_a?(String)
  @nodes << txt
respond_to?(id, inc_all=false) click to toggle source
  • id [String|Symbol] identifer of the attribute or method

  • ignored inc_all [Boolean]

return true if the element has a member that matches the provided name.

Calls superclass method
# File lib/ox/element.rb, line 174
def respond_to?(id, inc_all=false)
  return true if super
  id_str = id.to_s
  id_sym = id.to_sym
  nodes.each do |n|
    next if n.is_a?(String)
    return true if n.value == id_str || n.value == id_sym
  if instance_variable_defined?(:@attributes) && !@attributes.nil?
    return true if @attributes.has_key?(id_str)
    return true if @attributes.has_key?(id_sym)
text() click to toggle source

Returns the first String in the elements nodes array or nil if there is no String node.

# File lib/ox/element.rb, line 81
def text()
  nodes.each { |n| return n if n.is_a?(String) }