Class: Makiri::NodeSet

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/makiri/node_set.rb,
ext/makiri/makiri.c

Overview

An ordered collection of nodes, returned by xpath/css queries.

Instance Method Summary collapse

Instance Method Details

#&(other) ⇒ Object

self & other -> intersection (self order, deduped).



301
302
303
304
305
# File 'ext/makiri/glue/ruby_node_set.c', line 301

static VALUE
mkr_node_set_op_and(VALUE self, VALUE other)
{
    return mkr_node_set_op_filter(self, other, 1);
}

#+(other) ⇒ Object

self + other -> concatenation (duplicates kept).



255
256
257
258
259
260
261
262
263
264
# File 'ext/makiri/glue/ruby_node_set.c', line 255

static VALUE
mkr_node_set_op_plus(VALUE self, VALUE other)
{
    mkr_node_set_data_t *s = mkr_node_set_get(self);
    mkr_node_set_data_t *o = mkr_node_set_get(other);
    VALUE result = mkr_node_set_new(s->document);
    for (size_t i = 0; i < s->count; i++) mkr_node_set_push(result, s->nodes[i]);
    for (size_t i = 0; i < o->count; i++) mkr_node_set_push(result, o->nodes[i]);
    return result;
}

#-(other) ⇒ Object

self - other -> difference (self order, deduped).



308
309
310
311
312
# File 'ext/makiri/glue/ruby_node_set.c', line 308

static VALUE
mkr_node_set_op_minus(VALUE self, VALUE other)
{
    return mkr_node_set_op_filter(self, other, 0);
}

#[](rb_index) ⇒ Object

set -> Node or nil. Negative indices count from the end.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'ext/makiri/glue/ruby_node_set.c', line 106

static VALUE
mkr_node_set_aref(VALUE self, VALUE rb_index)
{
    mkr_node_set_data_t *s;
    TypedData_Get_Struct(self, mkr_node_set_data_t, &mkr_node_set_type, s);

    long i = NUM2LONG(rb_index);
    if (i < 0) {
        i += (long)s->count;
    }
    if (i < 0 || (size_t)i >= s->count) {
        return Qnil;
    }
    return mkr_wrap_node(s->nodes[i], s->document);
}

#at(index) ⇒ Makiri::Node?

Index access; alias for #[].

Returns:



30
31
32
# File 'lib/makiri/node_set.rb', line 30

def at(index)
  self[index]
end

#at_css(selector) ⇒ Makiri::Node?

First node matching the CSS selector across the set, or nil.

Returns:



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

def at_css(selector)
  css(selector).first
end

#at_xpath(expr) ⇒ Object

First node matching the XPath expression across the set (or the scalar value for a non-node-set result).



72
73
74
75
# File 'lib/makiri/node_set.rb', line 72

def at_xpath(expr)
  result = xpath(expr)
  result.is_a?(NodeSet) ? result.first : result
end

#css(selector) ⇒ Makiri::NodeSet

Run a CSS selector against every node and return the unioned matches.

Returns:



50
51
52
53
54
# File 'lib/makiri/node_set.rb', line 50

def css(selector)
  return self if empty?

  map { |node| node.css(selector) }.reduce(:|)
end

#eachObject



122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'ext/makiri/glue/ruby_node_set.c', line 122

static VALUE
mkr_node_set_each(VALUE self)
{
    mkr_node_set_data_t *s;
    TypedData_Get_Struct(self, mkr_node_set_data_t, &mkr_node_set_type, s);

    RETURN_ENUMERATOR(self, 0, 0);

    for (size_t i = 0; i < s->count; i++) {
        rb_yield(mkr_wrap_node(s->nodes[i], s->document));
    }
    return self;
}

#empty?Boolean

Returns:

  • (Boolean)


14
15
16
# File 'lib/makiri/node_set.rb', line 14

def empty?
  length.zero?
end

#firstMakiri::Node?

Returns:



19
20
21
# File 'lib/makiri/node_set.rb', line 19

def first
  self[0]
end

#inspectObject



101
102
103
# File 'lib/makiri/node_set.rb', line 101

def inspect
  "#<#{self.class.name} length=#{length}>"
end

#lastMakiri::Node?

Returns:



24
25
26
# File 'lib/makiri/node_set.rb', line 24

def last
  self[length - 1]
end

#lengthObject



97
98
99
100
101
102
103
# File 'ext/makiri/glue/ruby_node_set.c', line 97

static VALUE
mkr_node_set_length(VALUE self)
{
    mkr_node_set_data_t *s;
    TypedData_Get_Struct(self, mkr_node_set_data_t, &mkr_node_set_type, s);
    return ULONG2NUM(s->count);
}

#removeself Also known as: unlink

Detach every node in the set from its tree.

Returns:

  • (self)


95
96
97
98
# File 'lib/makiri/node_set.rb', line 95

def remove
  to_a.each(&:remove)
  self
end

#remove_attr(name) ⇒ self Also known as: remove_attribute

Remove the named attribute from every node in the set.

Returns:

  • (self)


87
88
89
90
# File 'lib/makiri/node_set.rb', line 87

def remove_attr(name)
  each { |node| node.delete(name) }
  self
end

#search(path) ⇒ Makiri::NodeSet

CSS- or XPath-detecting query against every node (see Makiri::Node#search).

Returns:



79
80
81
82
83
# File 'lib/makiri/node_set.rb', line 79

def search(path)
  return self if empty?

  map { |node| node.search(path) }.reduce(:|)
end

#sizeInteger

Returns:

  • (Integer)


9
10
11
# File 'lib/makiri/node_set.rb', line 9

def size
  length
end

#textString Also known as: inner_text

Concatenated text content of every node in the set.

Returns:

  • (String)


43
44
45
# File 'lib/makiri/node_set.rb', line 43

def text
  map(&:text).join
end

#to_htmlString Also known as: to_s

Concatenated outer HTML of every node in the set.

Returns:

  • (String)


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

def to_html
  map(&:to_html).join
end

#xpath(expr) ⇒ Makiri::NodeSet

Run an XPath expression against every node and union the node-set results.

Returns:



58
59
60
61
62
# File 'lib/makiri/node_set.rb', line 58

def xpath(expr)
  return self if empty?

  map { |node| node.xpath(expr) }.reduce(:|)
end

#|(other) ⇒ Object

self | other -> union (deduped).



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'ext/makiri/glue/ruby_node_set.c', line 229

static VALUE
mkr_node_set_op_or(VALUE self, VALUE other)
{
    mkr_node_set_data_t *s = mkr_node_set_get(self);
    mkr_node_set_data_t *o = mkr_node_set_get(other);
    VALUE result = mkr_node_set_new(s->document);
    mkr_node_set_data_t *r = mkr_node_set_get(result);

    mkr_ptrset_t seen = { NULL, 0 };
    if (s->count + o->count > MKR_NODE_SET_HASH_MIN) {
        mkr_ptrset_init(&seen, s->count + o->count);
    }
    mkr_node_set_data_t *srcs[2] = { s, o };
    for (int k = 0; k < 2; k++) {
        for (size_t i = 0; i < srcs[k]->count; i++) {
            lxb_dom_node_t *n = srcs[k]->nodes[i];
            int fresh = seen.cap ? mkr_ptrset_add(&seen, n)
                                 : !mkr_node_set_member(r, n);
            if (fresh) mkr_node_set_push(result, n);
        }
    }
    mkr_ptrset_free(&seen);
    return result;
}