Class: Moxml::NodeSet

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(nodes, context, parent_node = nil) ⇒ NodeSet

nodes: Array of natives, or an adapter's LazyNodeSet — the native set is held unmaterialized until an operation needs an Array (#+, #<<, #delete, Range slices).



12
13
14
15
16
17
18
# File 'lib/moxml/node_set.rb', line 12

def initialize(nodes, context, parent_node = nil)
  @nodes = nodes.is_a?(Array) ? nodes : nil
  @lazy = @nodes ? nil : nodes
  @context = context
  @wrapped = nil
  @parent_node = parent_node
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



7
8
9
# File 'lib/moxml/node_set.rb', line 7

def context
  @context
end

Instance Method Details

#+(other) ⇒ Object



89
90
91
# File 'lib/moxml/node_set.rb', line 89

def +(other)
  self.class.new(native_nodes + other.native_nodes, @context, @parent_node)
end

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



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

def <<(node)
  native_node = node.is_a?(Node) ? node.native : node
  # Materialize the buffer first so it allocates at the pre-append
  # size and stays in lockstep with the natives.
  wrapped_buffer << nil
  native_nodes << native_node
  self
end

#==(other) ⇒ Object



120
121
122
123
124
125
126
# File 'lib/moxml/node_set.rb', line 120

def ==(other)
  self.class == other.class &&
    length == other.length &&
    native_nodes.each_with_index.all? do |_node, index|
      self[index] == other[index]
    end
end

#[](index) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/moxml/node_set.rb', line 46

def [](index)
  case index
  when Integer
    actual = index.negative? ? native_size + index : index
    return nil unless actual >= 0 && actual < native_size

    wrapped_buffer[actual] ||= wrap_with_parent((@nodes || @lazy)[actual])
  when Range
    self.class.new(native_nodes[index], @context)
  end
end

#delete(node) ⇒ Object

Delete a node from the set Accepts both wrapped Moxml nodes and native nodes



139
140
141
142
143
144
145
146
147
148
149
# File 'lib/moxml/node_set.rb', line 139

def delete(node)
  native_node = node.is_a?(Node) ? node.native : node
  idx = native_nodes.index(native_node)
  if idx
    native_nodes.delete_at(idx)
    wrapped_buffer.delete_at(idx) if @wrapped
  else
    native_nodes.delete(native_node)
  end
  self
end

#eachObject



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/moxml/node_set.rb', line 29

def each
  return to_enum(:each) unless block_given?

  wrapped = wrapped_buffer
  index = 0
  (@nodes || @lazy).each do |node|
    wrapper = wrapped[index]
    unless wrapper
      wrapper = wrap_with_parent(node)
      wrapped[index] = wrapper
    end
    yield wrapper
    index += 1
  end
  self
end

#empty?Boolean

Returns:



70
71
72
# File 'lib/moxml/node_set.rb', line 70

def empty?
  native_size.zero?
end

#first(n = nil) ⇒ Object



58
59
60
61
62
63
64
# File 'lib/moxml/node_set.rb', line 58

def first(n = nil)
  if n.nil?
    native_size.zero? ? nil : self[0]
  else
    n.times.filter_map { |i| self[i] }
  end
end

#lastObject



66
67
68
# File 'lib/moxml/node_set.rb', line 66

def last
  native_size.zero? ? nil : self[native_size - 1]
end

#native_nodesObject

The raw native nodes — adapter-internal work only (issue #26). The public surface is wrapper-only: every Enumerable access goes through #each/#[]/#to_a, which wrap.



23
24
25
26
27
# File 'lib/moxml/node_set.rb', line 23

def native_nodes
  return @nodes unless @nodes.nil?

  @nodes = @lazy.to_a
end

#removeObject



132
133
134
135
# File 'lib/moxml/node_set.rb', line 132

def remove
  each(&:remove)
  self
end

#sizeObject Also known as: length



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

def size
  native_size
end

#textObject



128
129
130
# File 'lib/moxml/node_set.rb', line 128

def text
  map(&:text).join
end

#to_aObject



79
80
81
82
83
84
85
86
87
# File 'lib/moxml/node_set.rb', line 79

def to_a
  i = 0
  wrapped = wrapped_buffer
  (@nodes || @lazy).each do |node|
    wrapped[i] ||= wrap_with_parent(node)
    i += 1
  end
  wrapped.compact
end

#uniq_by_nativeObject

Deduplicate nodes based on native object identity This is crucial for XPath operations like descendant-or-self which may yield the same native node multiple times



106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/moxml/node_set.rb', line 106

def uniq_by_native
  seen = {}
  unique_natives = native_nodes.select do |native|
    id = native.object_id
    if seen[id]
      false
    else
      seen[id] = true
      true
    end
  end
  self.class.new(unique_natives, @context)
end