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#<<


77
78
79
# File 'lib/duxml/doc/element.rb', line 77

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



114
115
116
# File 'lib/duxml/doc/element.rb', line 114

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:



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/duxml/doc/element.rb', line 121

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



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

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:



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/duxml/doc/element.rb', line 87

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
      obj.set_doc! @doc
  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



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/duxml/doc/element.rb', line 209

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:



168
169
170
171
# File 'lib/duxml/doc/element.rb', line 168

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

#descriptionString

Returns self description.

Returns:

  • (String)

    self description



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

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



196
197
198
# File 'lib/duxml/doc/element.rb', line 196

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



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

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



161
162
163
# File 'lib/duxml/doc/element.rb', line 161

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’



201
202
203
204
# File 'lib/duxml/doc/element.rb', line 201

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



240
241
242
243
244
# File 'lib/duxml/doc/element.rb', line 240

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

#set_doc!(_doc) ⇒ Element

Returns self.

Parameters:

  • _doc (Doc)

    document to which this element belongs - recursively applies to all descendants of this node

Returns:



63
64
65
66
67
68
69
70
# File 'lib/duxml/doc/element.rb', line 63

def set_doc!(_doc)
  @doc = _doc
  traverse do |node|
    next if node === self or node.is_a?(String)
    node.set_doc!(_doc)
  end
  self
end

#stubElement

Returns copy of this Element but with no children.

Returns:

  • (Element)

    copy of this Element but with no children



143
144
145
# File 'lib/duxml/doc/element.rb', line 143

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



247
248
249
# File 'lib/duxml/doc/element.rb', line 247

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)



153
154
155
156
157
158
# File 'lib/duxml/doc/element.rb', line 153

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



178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/duxml/doc/element.rb', line 178

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