Class: Oga::XML::NodeSet

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/oga/xml/node_set.rb

Overview

The NodeSet class contains a set of unique Node instances that can be queried and modified. Optionally NodeSet instances can take ownership of a node (besides just containing it). This allows the nodes to query their previous and next elements.

There are two types of sets:

  1. Regular node sets
  2. Owned node sets

Both behave similar to Ruby's Array class. The difference between an owned and regular node set is that an owned set modifies nodes that are added or removed by certain operations. For example, when a node is added to an owned set the node_set attribute of said node points to the set it was just added to.

Owned node sets are used when building a DOM tree with Parser. By taking ownership of nodes in a set Oga makes it possible to use these sets as following:

document = Oga::XML::Document.new
element  = Oga::XML::Element.new

document.children << element

element.node_set == document.children # => true

If ownership was not handled then you'd have to manually set the element variable's node_set attribute after pushing it into a set.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(nodes = [], owner = nil) ⇒ NodeSet

Returns a new instance of NodeSet.

Parameters:

  • nodes (Array) (defaults to: [])

    The nodes to add to the set.

  • owner (Oga::XML::NodeSet) (defaults to: nil)

    The owner of the set.



40
41
42
43
44
45
46
# File 'lib/oga/xml/node_set.rb', line 40

def initialize(nodes = [], owner = nil)
  @nodes    = nodes
  @owner    = owner
  @existing = {}

  take_ownership_on_nodes
end

Instance Attribute Details

#ownerOga::XML::Node

Returns:



36
37
38
# File 'lib/oga/xml/node_set.rb', line 36

def owner
  @owner
end

Instance Method Details

#+(other) ⇒ Oga::XML::NodeSet

Creates a new set based on the current and the specified set. The newly created set does not inherit ownership rules of the current set.

Parameters:

Returns:



181
182
183
# File 'lib/oga/xml/node_set.rb', line 181

def +(other)
  self.class.new(to_a | other.to_a)
end

#==(other) ⇒ Object

Returns true if the current node set and the one given in other are equal to each other.

Parameters:



189
190
191
# File 'lib/oga/xml/node_set.rb', line 189

def ==(other)
  other.is_a?(NodeSet) && other.equal_nodes?(@nodes)
end

#[](index) ⇒ Oga::XML::Node

Returns the node for the given index.

Parameters:

  • index (Fixnum)

Returns:



165
166
167
# File 'lib/oga/xml/node_set.rb', line 165

def [](index)
  @nodes[index]
end

#attribute(name) ⇒ Array Also known as: attr

Returns the values of the given attribute.

Parameters:

  • name (String|Symbol)

    The name of the attribute.

Returns:

  • (Array)


252
253
254
255
256
257
258
259
260
261
262
# File 'lib/oga/xml/node_set.rb', line 252

def attribute(name)
  values = []

  @nodes.each do |node|
    if node.respond_to?(:attribute)
      values << node.attribute(name)
    end
  end

  values
end

#concat(other) ⇒ Object

Adds the nodes of the given node set to the current node set.

Parameters:



206
207
208
# File 'lib/oga/xml/node_set.rb', line 206

def concat(other)
  other.each { |node| push(node) }
end

#delete(node) ⇒ Object

Removes a node from the current set only.



236
237
238
239
240
241
242
243
244
245
246
# File 'lib/oga/xml/node_set.rb', line 236

def delete(node)
  removed = @nodes.delete(node)

  if removed
    unmark_existing(removed)

    remove_ownership(removed) if @owner
  end

  removed
end

#each {|| ... } ⇒ Object

Yields the supplied block for every node.

Yield Parameters:



51
52
53
54
55
# File 'lib/oga/xml/node_set.rb', line 51

def each
  return to_enum(:each) unless block_given?

  @nodes.each { |node| yield node }
end

#empty?TrueClass|FalseClass

Returns true if the set is empty.

Returns:

  • (TrueClass|FalseClass)


67
68
69
# File 'lib/oga/xml/node_set.rb', line 67

def empty?
  @nodes.empty?
end

#equal_nodes?(nodes) ⇒ Boolean

Returns true if the nodes given in nodes are equal to those specified in the current @nodes variable. This method allows two NodeSet instances to compare each other without the need of exposing @nodes to the public.

Parameters:

Returns:

  • (Boolean)


199
200
201
# File 'lib/oga/xml/node_set.rb', line 199

def equal_nodes?(nodes)
  @nodes == nodes
end

#index(node) ⇒ Fixnum

Returns the index of the given node.

Parameters:

Returns:

  • (Fixnum)


85
86
87
# File 'lib/oga/xml/node_set.rb', line 85

def index(node)
  @nodes.index(node)
end

#insert(index, node) ⇒ Object

Inserts a node into the set at the given index.

Parameters:

  • index (Fixnum)

    The index to insert the node at.

  • node (Oga::XML::Node)


151
152
153
154
155
156
157
158
159
# File 'lib/oga/xml/node_set.rb', line 151

def insert(index, node)
  return if exists?(node)

  @nodes.insert(index, node)

  mark_existing(node)

  take_ownership(node, index) if @owner
end

#inspectString

Returns:

  • (String)


282
283
284
285
286
# File 'lib/oga/xml/node_set.rb', line 282

def inspect
  values = @nodes.map(&:inspect).join(', ')

  "NodeSet(#{values})"
end

#lastOga::XML::Node

Returns the last node in the set.

Returns:



60
61
62
# File 'lib/oga/xml/node_set.rb', line 60

def last
  @nodes[-1]
end

#lengthFixnum Also known as: count, size

Returns the amount of nodes in the set.

Returns:

  • (Fixnum)


74
75
76
# File 'lib/oga/xml/node_set.rb', line 74

def length
  @nodes.length
end

#popOga::XML::Node

Pops a node from the end of the set.

Returns:



135
136
137
138
139
140
141
142
143
144
145
# File 'lib/oga/xml/node_set.rb', line 135

def pop
  node = @nodes.pop

  if node
    unmark_existing(node)

    remove_ownership(node) if @owner
  end

  node
end

#push(node) ⇒ Object Also known as: <<

Pushes the node at the end of the set.

Parameters:



92
93
94
95
96
97
98
99
100
# File 'lib/oga/xml/node_set.rb', line 92

def push(node)
  return if exists?(node)

  @nodes << node

  mark_existing(node)

  take_ownership(node, length - 1) if @owner
end

#removeObject

Removes the current nodes from their owning set. The nodes are not removed from the current set.

This method is intended to remove nodes from an XML document/node.



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/oga/xml/node_set.rb', line 214

def remove
  sets = []

  # First we gather all the sets to remove nodse from, then we remove the
  # actual nodes. This is done as you can not reliably remove elements
  # from an Array while iterating on that same Array.
  @nodes.each do |node|
    if node.node_set
      sets << node.node_set

      node.node_set = nil
      node.next     = nil
      node.previous = nil
    end
  end

  sets.each do |set|
    @nodes.each { |node| set.delete(node) }
  end
end

#shiftOga::XML::Node

Shifts a node from the start of the set.

Returns:



120
121
122
123
124
125
126
127
128
129
130
# File 'lib/oga/xml/node_set.rb', line 120

def shift
  node = @nodes.shift

  if node
    unmark_existing(node)

    remove_ownership(node) if @owner
  end

  node
end

#take_ownership_on_nodesObject



288
289
290
291
292
293
294
# File 'lib/oga/xml/node_set.rb', line 288

def take_ownership_on_nodes
  @nodes.each_with_index do |node, index|
    mark_existing(node)

    take_ownership(node, index) if @owner
  end
end

#textString

Returns the text of all nodes in the set, ignoring comment nodes.

Returns:

  • (String)


269
270
271
272
273
274
275
276
277
278
279
# File 'lib/oga/xml/node_set.rb', line 269

def text
  text = ''

  @nodes.each do |node|
    if node.respond_to?(:text) and !node.is_a?(Comment)
      text << node.text
    end
  end

  text
end

#to_aArray

Converts the current set to an Array.

Returns:

  • (Array)


172
173
174
# File 'lib/oga/xml/node_set.rb', line 172

def to_a
  @nodes
end

#unshift(node) ⇒ Object

Pushes the node at the start of the set.

Parameters:



107
108
109
110
111
112
113
114
115
# File 'lib/oga/xml/node_set.rb', line 107

def unshift(node)
  return if exists?(node)

  @nodes.unshift(node)

  mark_existing(node)

  take_ownership(node, 0) if @owner
end