Module: Duxml::ElementGuts

Includes:
Duxml, LazyOx, Enumerable, Reportable
Included in:
Doc, Element
Defined in:
lib/duxml/doc/element.rb,
lib/duxml/doc/element.rb

Overview

contains actual methods of XML Element

Instance Attribute Summary

Attributes included from Reportable

#observer_peers

Attributes included from Duxml

#doc

Attributes included from Saxer

#io

Instance Method Summary collapse

Methods included from LazyOx

#method_missing

Methods included from Reportable

#add_observer

Methods included from Duxml

#load, #log, #save, #validate

Methods included from Saxer

#sax

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Duxml::LazyOx

Instance Method Details

#<<(obj) ⇒ Element

this override reports changes to history; NewText for Strings, Add for elements

Parameters:

  • obj (Element, Array)

    element or string to add to this Element; can insert arrays which are always inserted in order

Returns:

See Also:

  • Ox::Element#<<


56
57
58
# File 'lib/duxml/doc/element.rb', line 56

def <<(obj)
  add(obj)
end

#[](index_or_attr) ⇒ Element, String

Returns string if attribute value or text node; Element if XML node.

Parameters:

  • index_or_attr (String, Symbol, Fixnum)

    string or symbol of attribute or index of child node

Returns:

  • (Element, String)

    string if attribute value or text node; Element if XML node



92
93
94
# File 'lib/duxml/doc/element.rb', line 92

def [](index_or_attr)
  index_or_attr.is_a?(Fixnum) ? nodes[index_or_attr] : super(index_or_attr)
end

#[]=(attr_sym, val) ⇒ Element

Returns self.

Parameters:

  • attr_sym (String, Symbol, Fixnum)

    name of attribute or index of child to replace

  • val (String)

    new attribute value or replacement child node

Returns:



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/duxml/doc/element.rb', line 99

def []=(attr_sym, val)
  if attr_sym.is_a?(Fixnum)
    remove nodes[attr_sym]
    add(val, attr_sym)
    return self
  end
  attr = attr_sym.to_s
  raise "argument to [] must be a Symbol or a String." unless attr.is_a?(Symbol) or attr.is_a?(String)
  args = [attr]
  args << attributes[attr] if attributes[attr]
  super(attr, val)
  type = args.size == 1 ? :NewAttr : :ChangeAttr
  report(type, *args)
  self
end

#abstract?Boolean

Returns whether or not this has been written to file.

Returns:

  • (Boolean)

    whether or not this has been written to file



47
48
49
# File 'lib/duxml/doc/element.rb', line 47

def abstract?
  line < 0 || column < 0
end

#add(obj, index = -1)) ⇒ Element

this version of the method allows insertions between existing elements

Parameters:

  • obj (Element, Array)

    element or string to add to this Element; can insert arrays which are always inserted in order

  • index (Fixnum) (defaults to: -1))

    index at which to insert new node; inserts at end of element by default; when inserting arrays, index is incremented for each item to avoid reversing array order

Returns:

See Also:



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/duxml/doc/element.rb', line 66

def add(obj, index=-1)
  case
    when obj.is_a?(Array), obj.is_a?(NodeSet)
      obj.each_with_index do |e, i|
        add(e, index == -1 ? index : index+i)
      end
    when obj.is_a?(String)
      if obj[0] == '<' and obj[-1] == '>' and (s = Ox.parse(obj))
        add dclone s
      else
        type = :NewText
        nodes.insert(index, obj)
      end
    else
      type = :Add
      nodes.insert(index, obj)
      if obj.count_observers < 1 && @observer_peers
        obj.add_observer(@observer_peers.first.first)
      end
  end
  report(type, obj, index)
  self
end

#dclone(source = self) ⇒ Element

Returns deep clone of source, including its attributes and recursively cloned children.

Parameters:

  • source (Element) (defaults to: self)

    if not explicitly provided, creates deep clone of this element; source can be any XML element (not only Duxml) that responds to traverse with pre-order traversal

Returns:

  • (Element)

    deep clone of source, including its attributes and recursively cloned children



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/duxml/doc/element.rb', line 187

def dclone(source = self)
  input_stack = []
  output_stack = []
  traverse(source) do |node|
    if node.is_a?(String)
      output_stack.last << node
      next
    end
    copy = Element.new(node.name, node.attributes)
    if output_stack.empty?
      output_stack << copy
      input_stack << node
    else

      if input_stack.last.nodes.none? do |n| n === node end
        input_stack.pop
        output_stack.pop
      end

      output_stack.last << copy
      if node.nodes.any?
        output_stack << copy
        input_stack << node
      end

    end
  end
  output_stack.pop
end

#delete(obj) ⇒ Element Also known as: remove

TODO do we need this method to take Fixnum node index as well?

Parameters:

  • obj (Element)

    element child to delete

Returns:



146
147
148
149
# File 'lib/duxml/doc/element.rb', line 146

def delete(obj)
  report(:Remove, @nodes.delete(obj))
  obj
end

#descriptionString

Returns self description.

Returns:

  • (String)

    self description



116
117
118
# File 'lib/duxml/doc/element.rb', line 116

def description
  "<#{name}>"
end

#each(&block) ⇒ Object

traverse through just the children of this node

Parameters:

  • &block (block)

    code to execute for each child node



174
175
176
# File 'lib/duxml/doc/element.rb', line 174

def each(&block)
  @nodes.each(&block)
end

#historyHistoryClass

Returns history that is observing this element for changes.

Returns:

  • (HistoryClass)

    history that is observing this element for changes



126
127
128
# File 'lib/duxml/doc/element.rb', line 126

def history
  @observer_peers.first.first if @observer_peers.respond_to?(:any?) and @observer_peers.any? and @observer_peers.first.any?
end

#inspectObject

Returns #to_s.

Returns:

  • #to_s



139
140
141
# File 'lib/duxml/doc/element.rb', line 139

def inspect
  to_s
end

#name_spaceString

Returns namespace of element, derived from name e.g. ‘<duxml:element>’ => ‘duxml’.

Returns:

  • (String)

    namespace of element, derived from name e.g. ‘<duxml:element>’ => ‘duxml’



179
180
181
182
# File 'lib/duxml/doc/element.rb', line 179

def name_space
  return nil unless (i = name.index(':'))
  name[0..i-1]
end

#scloneElement

Returns shallow clone of this element, with all attributes and children only if none are Elements.

Returns:

  • (Element)

    shallow clone of this element, with all attributes and children only if none are Elements



218
219
220
221
222
# File 'lib/duxml/doc/element.rb', line 218

def sclone
  stub = Element.new(name, attributes)
  stub << nodes if text?
  stub
end

#stubElement

Returns copy of this Element but with no children.

Returns:

  • (Element)

    copy of this Element but with no children



121
122
123
# File 'lib/duxml/doc/element.rb', line 121

def stub
  Element.new(name, attributes)
end

#text?true, false

Returns true if all child nodes are text only; false if any child nodes are XML.

Returns:

  • (true, false)

    true if all child nodes are text only; false if any child nodes are XML



225
226
227
# File 'lib/duxml/doc/element.rb', line 225

def text?
  nodes.all? do |node| node.is_a?(String) end
end

#to_sString

Returns XML string (overrides Ox’s to_s which just prints the object pointer).

Returns:

  • (String)

    XML string (overrides Ox’s to_s which just prints the object pointer)



131
132
133
134
135
136
# File 'lib/duxml/doc/element.rb', line 131

def to_s
  s = %(<#{name})
  attributes.each do |k,v| s << %( #{k.to_s}="#{v}") end
  return s+'/>' if nodes.empty?
  s << ">#{nodes.collect do |n| n.to_s end.join}</#{name}>"
end

#traverse(node = nil, &block) ⇒ Object

pre-order traverse through this node and all of its descendants

Parameters:

  • &block (block)

    code to execute for each yielded node



156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/duxml/doc/element.rb', line 156

def traverse(node=nil, &block)
  return self.to_enum unless block_given?
  node_stack = [node || self]

  until node_stack.empty?
    current = node_stack.shift
    if current
      yield current
      node_stack = node_stack.insert(0, *current.nodes) if current.respond_to?(:nodes)
    end
  end

  node || self if block_given?
end