Class: Nokolexbor::NodeSet
- Includes:
- Enumerable
- Defined in:
- lib/nokolexbor/node_set.rb,
ext/nokolexbor/nl_node_set.c
Constant Summary
Constants inherited from Node
Nokolexbor::Node::ATTRIBUTE_NODE, Nokolexbor::Node::CDATA_SECTION_NODE, Nokolexbor::Node::COMMENT_NODE, Nokolexbor::Node::DOCUMENT_FRAG_NODE, Nokolexbor::Node::DOCUMENT_NODE, Nokolexbor::Node::DOCUMENT_TYPE_NODE, Nokolexbor::Node::ELEMENT_NODE, Nokolexbor::Node::ENTITY_NODE, Nokolexbor::Node::ENTITY_REF_NODE, Nokolexbor::Node::LOOKS_LIKE_XPATH, Nokolexbor::Node::NOTATION_NODE, Nokolexbor::Node::PI_NODE, Nokolexbor::Node::TEXT_NODE
Instance Attribute Summary
Attributes inherited from Node
Class Method Summary collapse
-
.new(document, list = []) {|Document| ... } ⇒ Document
Create a NodeSet with
document
defaulting tolist
.
Instance Method Summary collapse
-
#&(other) ⇒ NodeSet
A new NodeSet with the common nodes only.
-
#-(other) ⇒ NodeSet
A new NodeSet with the nodes in this NodeSet that aren’t in
other
. -
#==(other) ⇒ Boolean
True if two NodeSets contain the same number of elements and each element is equal to the corresponding element in the other NodeSet.
- #[](*args) ⇒ Node, ... (also: #slice)
-
#add_class(name) ⇒ Object
Add the class attribute
name
to all containing nodes. -
#after(node) ⇒ Object
Insert
node
after the last Node in this NodeSet. -
#append_class(name) ⇒ Object
Append the class attribute
name
to all containing nodes. -
#at_css(selector) ⇒ Node?
Like #css, but returns the first match.
-
#attr(key, value = nil, &block) ⇒ NodeSet
(also: #set, #attribute)
Set attributes on each Node in the NodeSet, or get an attribute from the first Node in the NodeSet.
-
#before(node) ⇒ Object
Insert
node
before the first Node in this NodeSet. -
#children ⇒ NodeSet
A new NodeSet containing all the children of all the nodes in the NodeSet.
-
#content ⇒ String
(also: #text, #inner_text, #to_str)
Get the content of all contained Nodes.
-
#css(selector) ⇒ NodeSet
Search this object for CSS
rules
. -
#delete(node) ⇒ Node?
Delete
node
from the NodeSet. -
#destroy ⇒ Object
Destroy all nodes in the NodeSet.
-
#each {|Node| ... } ⇒ Object
Iterate over each node.
-
#empty? ⇒ Boolean
True if this NodeSet is empty.
-
#first(n = nil) ⇒ Node+
Get the first
n
elements of the NodeSet. -
#include?(node) ⇒ Boolean
True if any member of this NodeSet equals
node
. -
#index(node = nil) ⇒ Integer
The index of the first node in this NodeSet that is equal to
node
or meets the given block. -
#inner_html(*args) ⇒ String
Get the inner html of all contained Nodes.
- #inspect ⇒ Object
-
#last ⇒ Node?
Get the last element of the NodeSet.
-
#length ⇒ Integer
(also: #size)
Get the length of this NodeSet.
-
#nokogiri_css(*args) ⇒ NodeSet
Search this object for CSS
rules
. -
#outer_html(*args) ⇒ String
(also: #to_s, #to_html, #serialize)
Convert this NodeSet to HTML.
-
#pop ⇒ Node?
The last element of this NodeSet and removes it.
-
#push(node) ⇒ NodeSet
(also: #<<)
Append
node
to the NodeSet. -
#remove ⇒ Object
(also: #unlink)
Remove all nodes in this NodeSet.
-
#remove_attr(name) ⇒ Object
(also: #remove_attribute)
Remove the attributed named
name
from all containing nodes. -
#remove_class(name = nil) ⇒ Object
Remove the class attribute
name
from all containing nodes. -
#reverse ⇒ NodeSet
A new NodeSet containing all the nodes in the NodeSet in reverse order.
-
#shift ⇒ Node?
The first element of this NodeSet and removes it.
-
#to_a ⇒ Array<Node>
(also: #to_ary)
This list as an Array.
-
#wrap(node_or_tags) ⇒ NodeSet
Wrap all nodes of this NodeSet with
node_or_tags
. -
#xpath(*args) ⇒ NodeSet
Search this node for XPath
paths
. -
#|(other) ⇒ NodeSet
(also: #+)
A new set built by merging the
other
set, excluding duplicates.
Methods inherited from Node
#[]=, #add_child, #add_next_sibling, #add_previous_sibling, #add_sibling, #ancestors, #at, #at_css_impl, #at_xpath, #attribute_nodes, #attributes, #attrs, #cdata?, #child, #children=, #classes, #clone, #comment?, #content=, #css_impl, #css_path, #document?, #element?, #element_children, #first_element_child, #fragment, #fragment?, #key?, #keys, #kwattr_add, #kwattr_append, #kwattr_remove, #kwattr_values, #last_element_child, #matches?, #name, #next, #next_element, #node_type, #nokogiri_at_css, #parent, #parent=, #parse, #path, #prepend_child, #previous, #previous_element, #processing_instruction?, #replace, #search, #source_location, #swap, #text?, #traverse, #value?, #values, #write_to
Class Method Details
.new(document, list = []) {|Document| ... } ⇒ Document
Create a NodeSet with document
defaulting to list
.
12 13 14 15 16 17 18 |
# File 'lib/nokolexbor/node_set.rb', line 12 def self.new(document, list = []) obj = allocate obj.instance_variable_set(:@document, document) list.each { |x| obj << x } yield obj if block_given? obj end |
Instance Method Details
#&(other) ⇒ NodeSet
Returns A new NodeSet with the common nodes only.
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'ext/nokolexbor/nl_node_set.c', line 306
static VALUE
nl_node_set_intersection(VALUE self, VALUE other)
{
if (!rb_obj_is_kind_of(other, cNokolexborNodeSet)) {
rb_raise(rb_eArgError, "Parameter must be a Nokolexbor::NodeSet");
}
lexbor_array_t *self_array = nl_rb_node_set_unwrap(self);
lexbor_array_t *other_array = nl_rb_node_set_unwrap(other);
lexbor_array_t *new_array = lexbor_array_create();
for (size_t i = 0; i < self_array->length; i++) {
for (size_t j = 0; j < other_array->length; j++) {
if (self_array->list[i] == other_array->list[j]) {
lexbor_array_push(new_array, self_array->list[i]);
break;
}
}
}
return nl_rb_node_set_create_with_data(new_array, nl_rb_document_get(self));
}
|
#-(other) ⇒ NodeSet
Returns A new NodeSet with the nodes in this NodeSet that aren’t in other
.
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
# File 'ext/nokolexbor/nl_node_set.c', line 333
static VALUE
nl_node_set_difference(VALUE self, VALUE other)
{
if (!rb_obj_is_kind_of(other, cNokolexborNodeSet)) {
rb_raise(rb_eArgError, "Parameter must be a Nokolexbor::NodeSet");
}
lexbor_array_t *self_array = nl_rb_node_set_unwrap(self);
lexbor_array_t *other_array = nl_rb_node_set_unwrap(other);
lexbor_array_t *new_array = lexbor_array_create();
for (size_t i = 0; i < self_array->length; i++) {
bool found = false;
for (size_t j = 0; j < other_array->length; j++) {
if (self_array->list[i] == other_array->list[j]) {
found = true;
break;
}
}
if (!found) {
lexbor_array_push(new_array, self_array->list[i]);
}
}
return nl_rb_node_set_create_with_data(new_array, nl_rb_document_get(self));
}
|
#==(other) ⇒ Boolean
Returns true if two NodeSets contain the same number of elements and each element is equal to the corresponding element in the other NodeSet.
142 143 144 145 146 147 148 149 150 |
# File 'lib/nokolexbor/node_set.rb', line 142 def ==(other) return false unless other.is_a?(NodeSet) return false unless length == other.length each_with_index do |node, i| return false unless node == other[i] end true end |
#[](index) ⇒ Node? #[](start, length) ⇒ NodeSet? #[](range) ⇒ NodeSet? Also known as: slice
The Nokolexbor::Node at index
, or returns a Nokolexbor::NodeSet containing nodes starting at start
and continuing for length
elements, or returns a Nokolexbor::NodeSet containing nodes specified by range
. Negative indices
count backward from the end of the node_set
(-1 is the last node). Returns nil if the index
(or start
) are out of range.
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 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'ext/nokolexbor/nl_node_set.c', line 212
static VALUE
nl_node_set_slice(int argc, VALUE *argv, VALUE self)
{
VALUE arg;
long beg, len;
lexbor_array_t *array = nl_rb_node_set_unwrap(self);
if (argc == 2) {
beg = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
if (beg < 0) {
beg += array->length;
}
return nl_node_set_subseq(self, beg, len);
}
if (argc != 1) {
rb_scan_args(argc, argv, "11", NULL, NULL);
}
arg = argv[0];
if (FIXNUM_P(arg)) {
return nl_node_set_index_at(self, FIX2LONG(arg));
}
/* if arg is Range */
switch (rb_range_beg_len(arg, &beg, &len, array->length, 0)) {
case Qfalse:
break;
case Qnil:
return Qnil;
default:
return nl_node_set_subseq(self, beg, len);
}
return nl_node_set_index_at(self, NUM2LONG(arg));
}
|
#add_class(name) ⇒ Object
Add the class attribute name
to all containing nodes.
185 186 187 188 189 190 |
# File 'lib/nokolexbor/node_set.rb', line 185 def add_class(name) each do |el| el.add_class(name) end self end |
#after(node) ⇒ Object
Insert node
after the last Node in this NodeSet
63 64 65 |
# File 'lib/nokolexbor/node_set.rb', line 63 def after(node) last.after(node) end |
#append_class(name) ⇒ Object
Append the class attribute name
to all containing nodes.
195 196 197 198 199 200 |
# File 'lib/nokolexbor/node_set.rb', line 195 def append_class(name) each do |el| el.append_class(name) end self end |
#at_css(selector) ⇒ Node?
Like #css, but returns the first match.
This method uses Lexbor as the selector engine. Its performance is much higher than Nokolexbor::Node#at_xpath or Nokolexbor::Node#nokogiri_at_css.
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 |
# File 'ext/nokolexbor/nl_node_set.c', line 414
static VALUE
nl_node_set_at_css(VALUE self, VALUE selector)
{
lexbor_array_t *array = lexbor_array_create();
lxb_dom_document_t *doc = nl_rb_document_unwrap(nl_rb_document_get(self));
lxb_status_t status = nl_node_set_find(self, selector, nl_node_at_css_callback, array);
if (status != LXB_STATUS_OK) {
lexbor_array_destroy(array, true);
nl_raise_lexbor_error(status);
}
if (array->length == 0) {
lexbor_array_destroy(array, true);
return Qnil;
}
nl_sort_nodes_if_necessary(selector, doc, array);
VALUE ret = nl_rb_node_create(array->list[0], nl_rb_document_get(self));
lexbor_array_destroy(array, true);
return ret;
}
|
#attr(key, value = nil, &block) ⇒ NodeSet Also known as: set, attribute
Set attributes on each Node in the NodeSet, or get an attribute from the first Node in the NodeSet.
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/nokolexbor/node_set.rb', line 233 def attr(key, value = nil, &block) unless key.is_a?(Hash) || (key && (value || block)) return first&.attribute(key) end hash = key.is_a?(Hash) ? key : { key => value } hash.each do |k, v| each do |node| node[k] = v || yield(node) end end self end |
#before(node) ⇒ Object
Insert node
before the first Node in this NodeSet
58 59 60 |
# File 'lib/nokolexbor/node_set.rb', line 58 def before(node) first.before(node) end |
#children ⇒ NodeSet
Returns A new NodeSet containing all the children of all the nodes in the NodeSet.
154 155 156 157 158 159 160 |
# File 'lib/nokolexbor/node_set.rb', line 154 def children node_set = NodeSet.new(@document) each do |node| node.children.each { |n| node_set.push(n) } end node_set end |
#content ⇒ String Also known as: text, inner_text, to_str
Get the content of all contained Nodes.
80 81 82 |
# File 'lib/nokolexbor/node_set.rb', line 80 def content self.map(&:content).join end |
#css(selector) ⇒ NodeSet
Search this object for CSS rules
. rules
must be one or more CSS selectors.
This method uses Lexbor as the selector engine. Its performance is much higher than #xpath or #nokogiri_css.
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 |
# File 'ext/nokolexbor/nl_node_set.c', line 444
static VALUE
nl_node_set_css(VALUE self, VALUE selector)
{
lexbor_array_t *array = lexbor_array_create();
lxb_dom_document_t *doc = nl_rb_document_unwrap(nl_rb_document_get(self));
lxb_status_t status = nl_node_set_find(self, selector, nl_node_css_callback, array);
if (status != LXB_STATUS_OK) {
lexbor_array_destroy(array, true);
nl_raise_lexbor_error(status);
}
nl_sort_nodes_if_necessary(selector, doc, array);
return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
}
|
#delete(node) ⇒ Node?
Delete node
from the NodeSet.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'ext/nokolexbor/nl_node_set.c', line 111
static VALUE
nl_node_set_delete(VALUE self, VALUE rb_node)
{
lexbor_array_t *array = nl_rb_node_set_unwrap(self);
lxb_dom_node_t *node = nl_rb_node_unwrap(rb_node);
size_t i;
for (i = 0; i < array->length; i++)
if (array->list[i] == node) {
break;
}
if (i >= array->length) {
// not found
return Qnil;
}
lexbor_array_delete(array, i, 1);
return rb_node;
}
|
#destroy ⇒ Object
Destroy all nodes in the NodeSet.
119 120 121 |
# File 'lib/nokolexbor/node_set.rb', line 119 def destroy self.each(&:destroy) end |
#each {|Node| ... } ⇒ Object
Iterate over each node.
23 24 25 26 27 28 29 30 |
# File 'lib/nokolexbor/node_set.rb', line 23 def each return to_enum unless block_given? 0.upto(length - 1) do |x| yield self[x] end self end |
#empty? ⇒ Boolean
Returns true if this NodeSet is empty.
53 54 55 |
# File 'lib/nokolexbor/node_set.rb', line 53 def empty? length == 0 end |
#first(n = nil) ⇒ Node+
Get the first n
elements of the NodeSet.
37 38 39 40 41 42 43 |
# File 'lib/nokolexbor/node_set.rb', line 37 def first(n = nil) return self[0] unless n list = [] [n, length].min.times { |i| list << self[i] } list end |
#include?(node) ⇒ Boolean
Returns true if any member of this NodeSet equals node
.
137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'ext/nokolexbor/nl_node_set.c', line 137
static VALUE
nl_node_set_is_include(VALUE self, VALUE rb_node)
{
lexbor_array_t *array = nl_rb_node_set_unwrap(self);
lxb_dom_node_t *node = nl_rb_node_unwrap(rb_node);
for (size_t i = 0; i < array->length; i++)
if (array->list[i] == node) {
return Qtrue;
}
return Qfalse;
}
|
#index(node = nil) ⇒ Integer
Returns The index of the first node in this NodeSet that is equal to node
or meets the given block. Returns nil if no match is found.
68 69 70 71 72 73 74 75 |
# File 'lib/nokolexbor/node_set.rb', line 68 def index(node = nil) if node each_with_index { |member, j| return j if member == node } elsif block_given? each_with_index { |member, j| return j if yield(member) } end nil end |
#inner_html(*args) ⇒ String
Get the inner html of all contained Nodes.
91 92 93 |
# File 'lib/nokolexbor/node_set.rb', line 91 def inner_html(*args) self.map { |n| n.inner_html(*args) }.join end |
#inspect ⇒ Object
278 279 280 |
# File 'lib/nokolexbor/node_set.rb', line 278 def inspect "[#{map(&:inspect).join(', ')}]" end |
#last ⇒ Node?
Get the last element of the NodeSet.
48 49 50 |
# File 'lib/nokolexbor/node_set.rb', line 48 def last self[-1] end |
#length ⇒ Integer Also known as: size
Get the length of this NodeSet.
71 72 73 74 75 |
# File 'ext/nokolexbor/nl_node_set.c', line 71
static VALUE
nl_node_set_length(VALUE self)
{
return INT2NUM(nl_rb_node_set_unwrap(self)->length);
}
|
#nokogiri_css(*args) ⇒ NodeSet
Search this object for CSS rules
. rules
must be one or more CSS selectors. It supports a mixed syntax of CSS selectors and XPath.
This method uses libxml2 as the selector engine. It works the same way as Nokogiri::Node#css.
265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/nokolexbor/node_set.rb', line 265 def nokogiri_css(*args) rules, handler, ns, _ = extract_params(args) paths = css_rules_to_xpath(rules, ns) NodeSet.new(@document) do |set| each do |node| node.send(:xpath_internal, node, paths, handler, ns, nil).each do |inner_node| set << inner_node end end end end |
#outer_html(*args) ⇒ String Also known as: to_s, to_html, serialize
Convert this NodeSet to HTML.
98 99 100 |
# File 'lib/nokolexbor/node_set.rb', line 98 def outer_html(*args) self.map { |n| n.outer_html(*args) }.join end |
#pop ⇒ Node?
Returns The last element of this NodeSet and removes it. Returns nil
if the set is empty.
125 126 127 128 129 |
# File 'lib/nokolexbor/node_set.rb', line 125 def pop return nil if length == 0 delete(last) end |
#push(node) ⇒ NodeSet Also known as: <<
Append node
to the NodeSet.
87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'ext/nokolexbor/nl_node_set.c', line 87
static VALUE
nl_node_set_push(VALUE self, VALUE rb_node)
{
lexbor_array_t *array = nl_rb_node_set_unwrap(self);
lxb_dom_node_t *node = nl_rb_node_unwrap(rb_node);
lxb_status_t status = lexbor_array_push_unique(array, node);
if (status != LXB_STATUS_OK && status != LXB_STATUS_STOPPED) {
nl_raise_lexbor_error(status);
}
return self;
}
|
#remove ⇒ Object Also known as: unlink
Remove all nodes in this NodeSet.
109 110 111 |
# File 'lib/nokolexbor/node_set.rb', line 109 def remove self.each(&:remove) end |
#remove_attr(name) ⇒ Object Also known as: remove_attribute
Remove the attributed named name
from all containing nodes.
215 216 217 218 |
# File 'lib/nokolexbor/node_set.rb', line 215 def remove_attr(name) each { |el| el.delete(name) } self end |
#remove_class(name = nil) ⇒ Object
Remove the class attribute name
from all containing nodes.
205 206 207 208 209 210 |
# File 'lib/nokolexbor/node_set.rb', line 205 def remove_class(name = nil) each do |el| el.remove_class(name) end self end |
#reverse ⇒ NodeSet
Returns A new NodeSet containing all the nodes in the NodeSet in reverse order.
164 165 166 167 168 169 170 |
# File 'lib/nokolexbor/node_set.rb', line 164 def reverse node_set = NodeSet.new(@document) (length - 1).downto(0) do |x| node_set.push(self[x]) end node_set end |
#shift ⇒ Node?
Returns The first element of this NodeSet and removes it. Returns nil
if the set is empty.
133 134 135 136 137 |
# File 'lib/nokolexbor/node_set.rb', line 133 def shift return nil if length == 0 delete(first) end |
#to_a ⇒ Array<Node> Also known as: to_ary
Returns This list as an Array.
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'ext/nokolexbor/nl_node_set.c', line 254
static VALUE
nl_node_set_to_array(VALUE self)
{
lexbor_array_t *array = nl_rb_node_set_unwrap(self);
VALUE list = rb_ary_new2(array->length);
VALUE doc = nl_rb_document_get(self);
for (size_t i = 0; i < array->length; i++) {
lxb_dom_node_t *node = (lxb_dom_node_t *)array->list[i];
VALUE rb_node = nl_rb_node_create(node, doc);
rb_ary_push(list, rb_node);
}
return list;
}
|
#wrap(node_or_tags) ⇒ NodeSet
Wrap all nodes of this NodeSet with node_or_tags
.
177 178 179 180 |
# File 'lib/nokolexbor/node_set.rb', line 177 def wrap() map { |node| node.wrap() } self end |
#xpath(*args) ⇒ NodeSet
Search this node for XPath paths
. paths
must be one or more XPath queries.
It works the same way as Nokogiri::Node#xpath.
252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/nokolexbor/node_set.rb', line 252 def xpath(*args) paths, handler, ns, binds = extract_params(args) NodeSet.new(@document) do |set| each do |node| node.send(:xpath_internal, node, paths, handler, ns, binds).each do |inner_node| set << inner_node end end end end |
#|(other) ⇒ NodeSet Also known as: +
Returns A new set built by merging the other
set, excluding duplicates.
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'ext/nokolexbor/nl_node_set.c', line 273
static VALUE
nl_node_set_union(VALUE self, VALUE other)
{
if (!rb_obj_is_kind_of(other, cNokolexborNodeSet)) {
rb_raise(rb_eArgError, "Parameter must be a Nokolexbor::NodeSet");
}
lexbor_array_t *self_array = nl_rb_node_set_unwrap(self);
lexbor_array_t *other_array = nl_rb_node_set_unwrap(other);
if (self_array->length + other_array->length == 0) {
return nl_rb_node_set_create_with_data(NULL, nl_rb_document_get(self));
}
lexbor_array_t *new_array = lexbor_array_create();
lxb_status_t status = lexbor_array_init(new_array, self_array->length + other_array->length);
if (status != LXB_STATUS_OK) {
nl_raise_lexbor_error(status);
}
memcpy(new_array->list, self_array->list, sizeof(lxb_dom_node_t *) * self_array->length);
new_array->length = self_array->length;
for (size_t i = 0; i < other_array->length; i++) {
lexbor_array_push_unique(new_array, other_array->list[i]);
}
return nl_rb_node_set_create_with_data(new_array, nl_rb_document_get(self));
}
|