class Nokogiri::XML::NodeSet

A NodeSet contains a list of Nokogiri::XML::Node objects. Typically a NodeSet is return as a result of searching a Document via Nokogiri::XML::Searchable#css or Nokogiri::XML::Searchable#xpath

Constants

LOOKS_LIKE_XPATH

Regular expression used by Searchable#search to determine if a query string is CSS or XPath

Attributes

document[RW]

The Document this NodeSet is associated with

Public Class Methods

new(document, list = []) { |self| ... } click to toggle source

Create a NodeSet with document defaulting to list

# File lib/nokogiri/xml/node_set.rb, line 20
def initialize(document, list = [])
  @document = document
  document.decorate(self)
  list.each { |x| self << x }
  yield self if block_given?
end

Public Instance Methods

search *paths, [namespace-bindings, xpath-variable-bindings, custom-handler-class]
Alias for: at
&(node_set) click to toggle source

Set Intersection — Returns a new NodeSet containing nodes common to the two NodeSets.

static VALUE
intersection(VALUE rb_self, VALUE rb_other)
{
  xmlNodeSetPtr c_self, c_other ;
  xmlNodeSetPtr intersection;

  if (!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet)) {
    rb_raise(rb_eArgError, "node_set must be a Nokogiri::XML::NodeSet");
  }

  TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
  TypedData_Get_Struct(rb_other, xmlNodeSet, &xml_node_set_type, c_other);

  intersection = xmlXPathIntersection(c_self, c_other);
  return noko_xml_node_set_wrap(intersection, rb_iv_get(rb_self, "@document"));
}
+(p1)
Alias for: |
-(node_set) click to toggle source

Difference - returns a new NodeSet that is a copy of this NodeSet, removing each item that also appears in node_set

static VALUE
minus(VALUE rb_self, VALUE rb_other)
{
  xmlNodeSetPtr c_self, c_other;
  xmlNodeSetPtr new;
  int j ;

  if (!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet)) {
    rb_raise(rb_eArgError, "node_set must be a Nokogiri::XML::NodeSet");
  }

  TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
  TypedData_Get_Struct(rb_other, xmlNodeSet, &xml_node_set_type, c_other);

  new = xmlXPathNodeSetMerge(NULL, c_self);
  for (j = 0 ; j < c_other->nodeNr ; ++j) {
    xpath_node_set_del(new, c_other->nodeTab[j]);
  }

  return noko_xml_node_set_wrap(new, rb_iv_get(rb_self, "@document"));
}
<<(p1)
Alias for: push
==(other) click to toggle source

Equality – Two NodeSets are equal if the contain the same number of elements and if each element is equal to the corresponding element in the other NodeSet

# File lib/nokogiri/xml/node_set.rb, line 393
def ==(other)
  return false unless other.is_a?(Nokogiri::XML::NodeSet)
  return false unless length == other.length

  each_with_index do |node, i|
    return false unless node == other[i]
  end
  true
end
[index] → Node or nil click to toggle source
[start, length] → NodeSet or nil
[range] → NodeSet or nil

Element reference - returns the node at index, or returns a NodeSet containing nodes starting at start and continuing for length elements, or returns a 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.

static VALUE
slice(int argc, VALUE *argv, VALUE rb_self)
{
  VALUE arg ;
  long beg, len ;
  xmlNodeSetPtr c_self;

  TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);

  if (argc == 2) {
    beg = NUM2LONG(argv[0]);
    len = NUM2LONG(argv[1]);
    if (beg < 0) {
      beg += c_self->nodeNr ;
    }
    return subseq(rb_self, beg, len);
  }

  if (argc != 1) {
    rb_scan_args(argc, argv, "11", NULL, NULL);
  }
  arg = argv[0];

  if (FIXNUM_P(arg)) {
    return index_at(rb_self, FIX2LONG(arg));
  }

  /* if arg is Range */
  switch (rb_range_beg_len(arg, &beg, &len, (long)c_self->nodeNr, 0)) {
    case Qfalse:
      break;
    case Qnil:
      return Qnil;
    default:
      return subseq(rb_self, beg, len);
  }

  return index_at(rb_self, NUM2LONG(arg));
}
Also aliased as: slice
add_class(name) click to toggle source

Add the class attribute name to all Node objects in the NodeSet.

See Nokogiri::XML::Node#add_class for more information.

# File lib/nokogiri/xml/node_set.rb, line 139
def add_class(name)
  each do |el|
    el.add_class(name)
  end
  self
end
after(datum) click to toggle source

Insert datum after the last Node in this NodeSet

# File lib/nokogiri/xml/node_set.rb, line 69
def after(datum)
  last.after(datum)
end
append_class(name) click to toggle source

Append the class attribute name to all Node objects in the NodeSet.

See Nokogiri::XML::Node#append_class for more information.

# File lib/nokogiri/xml/node_set.rb, line 151
def append_class(name)
  each do |el|
    el.append_class(name)
  end
  self
end
search *paths, [namespace-bindings, xpath-variable-bindings, custom-handler-class] click to toggle source

Search this object for paths, and return only the first result. paths must be one or more XPath or CSS queries.

See Searchable#search for more information.

Or, if passed an integer, index into the NodeSet:

node_set.at(3) # same as node_set[3]
Calls superclass method Nokogiri::XML::Searchable#at
# File lib/nokogiri/xml/node_set.rb, line 119
def at(*args)
  if args.length == 1 && args.first.is_a?(Numeric)
    return self[args.first]
  end

  super(*args)
end
Also aliased as: %
attr(key, value = nil) { |node| ... } click to toggle source

Set attributes on each Node in the NodeSet, or get an attribute from the first Node in the NodeSet.

To get an attribute from the first Node in a NodeSet:

node_set.attr("href") # => "https://www.nokogiri.org"

Note that an empty NodeSet will return nil when #attr is called as a getter.

To set an attribute on each node, key can either be an attribute name, or a Hash of attribute names and values. When called as a setter, #attr returns the NodeSet.

If key is an attribute name, then either value or block must be passed.

If key is a Hash then attributes will be set for each key/value pair:

node_set.attr("href" => "https://www.nokogiri.org", "class" => "member")

If value is passed, it will be used as the attribute value for all nodes:

node_set.attr("href", "https://www.nokogiri.org")

If block is passed, it will be called on each Node object in the NodeSet and the return value used as the attribute value for that node:

node_set.attr("class") { |node| node.name }
# File lib/nokogiri/xml/node_set.rb, line 203
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
Also aliased as: set, attribute
attribute(key, value = nil, &block)
Alias for: attr
before(datum) click to toggle source

Insert datum before the first Node in this NodeSet

# File lib/nokogiri/xml/node_set.rb, line 63
def before(datum)
  first.before(datum)
end
children() click to toggle source

Returns a new NodeSet containing all the children of all the nodes in the NodeSet

# File lib/nokogiri/xml/node_set.rb, line 406
def children
  node_set = NodeSet.new(document)
  each do |node|
    node.children.each { |n| node_set.push(n) }
  end
  node_set
end
dup
Alias for: dup
css *rules, [namespace-bindings, custom-pseudo-class] click to toggle source

Search this node set for CSS rules. rules must be one or more CSS selectors. For example:

For more information see Nokogiri::XML::Searchable#css

# File lib/nokogiri/xml/node_set.rb, line 83
def css(*args)
  rules, handler, ns, _ = extract_params(args)
  paths = css_rules_to_xpath(rules, ns)

  inject(NodeSet.new(document)) do |set, node|
    set + xpath_internal(node, paths, handler, ns, nil)
  end
end
deconstruct() → Array click to toggle source

Returns the members of this NodeSet as an array, to use in pattern matching.

Since v1.14.0

# File lib/nokogiri/xml/node_set.rb, line 440
def deconstruct
  to_a
end
delete(node) click to toggle source

Delete node from the Nodeset, if it is a member. Returns the deleted node if found, otherwise returns nil.

static VALUE
delete (VALUE rb_self, VALUE rb_node)
{
  xmlNodeSetPtr c_self;
  xmlNodePtr node;

  Check_Node_Set_Node_Type(rb_node);

  TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
  Noko_Node_Get_Struct(rb_node, xmlNode, node);

  if (xmlXPathNodeSetContains(c_self, node)) {
    xpath_node_set_del(c_self, node);
    return rb_node;
  }
  return Qnil ;
}
dup click to toggle source

Duplicate this NodeSet. Note that the Nodes contained in the NodeSet are not duplicated (similar to how Array and other Enumerable classes work).

static VALUE
duplicate(VALUE rb_self)
{
  xmlNodeSetPtr c_self;
  xmlNodeSetPtr dupl;

  TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);

  dupl = xmlXPathNodeSetMerge(NULL, c_self);

  return noko_xml_node_set_wrap(dupl, rb_iv_get(rb_self, "@document"));
}
Also aliased as: clone
each() { |self| ... } click to toggle source

Iterate over each node, yielding to block

# File lib/nokogiri/xml/node_set.rb, line 231
def each
  return to_enum unless block_given?

  0.upto(length - 1) do |x|
    yield self[x]
  end
  self
end
empty?() click to toggle source

Is this NodeSet empty?

# File lib/nokogiri/xml/node_set.rb, line 45
def empty?
  length == 0
end
filter(expr) click to toggle source

Filter this list for nodes that match expr

# File lib/nokogiri/xml/node_set.rb, line 130
def filter(expr)
  find_all { |node| node.matches?(expr) }
end
first(n = nil) click to toggle source

Get the first element of the NodeSet.

# File lib/nokogiri/xml/node_set.rb, line 29
def first(n = nil)
  return self[0] unless n

  list = []
  [n, length].min.times { |i| list << self[i] }
  list
end
include?(node) click to toggle source

Returns true if any member of node set equals node.

static VALUE
include_eh(VALUE rb_self, VALUE rb_node)
{
  xmlNodeSetPtr c_self;
  xmlNodePtr node;

  Check_Node_Set_Node_Type(rb_node);

  TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
  Noko_Node_Get_Struct(rb_node, xmlNode, node);

  return (xmlXPathNodeSetContains(c_self, node) ? Qtrue : Qfalse);
}
index(node = nil) { |member| ... } click to toggle source

Returns the index of the first node in self that is == to node or meets the given block. Returns nil if no match is found.

# File lib/nokogiri/xml/node_set.rb, line 51
def index(node = nil)
  if node
    warn("given block not used") if block_given?
    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) click to toggle source

Get the inner html of all contained Node objects

# File lib/nokogiri/xml/node_set.rb, line 260
def inner_html(*args)
  collect { |j| j.inner_html(*args) }.join("")
end
inner_text() click to toggle source

Get the inner text of all contained Node objects

Note: This joins the text of all Node objects in the NodeSet:

doc = Nokogiri::XML('<xml><a><d>foo</d><d>bar</d></a></xml>')
doc.css('d').text # => "foobar"

Instead, if you want to return the text of all nodes in the NodeSet:

doc.css('d').map(&:text) # => ["foo", "bar"]

See Nokogiri::XML::Node#content for more information.

# File lib/nokogiri/xml/node_set.rb, line 253
def inner_text
  collect(&:inner_text).join("")
end
Also aliased as: text
inspect() click to toggle source

Return a nicely formated string representation

# File lib/nokogiri/xml/node_set.rb, line 427
def inspect
  "[#{map(&:inspect).join(", ")}]"
end
last() click to toggle source

Get the last element of the NodeSet.

# File lib/nokogiri/xml/node_set.rb, line 39
def last
  self[-1]
end
length click to toggle source

Get the length of the node set

static VALUE
length(VALUE rb_self)
{
  xmlNodeSetPtr c_self;

  TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);

  return c_self ? INT2NUM(c_self->nodeNr) : INT2NUM(0);
}
Also aliased as: size
pop() click to toggle source

Removes the last element from set and returns it, or nil if the set is empty

# File lib/nokogiri/xml/node_set.rb, line 374
def pop
  return if length == 0

  delete(last)
end
push(node) click to toggle source

Append node to the NodeSet.

static VALUE
push(VALUE rb_self, VALUE rb_node)
{
  xmlNodeSetPtr c_self;
  xmlNodePtr node;

  Check_Node_Set_Node_Type(rb_node);

  TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
  Noko_Node_Get_Struct(rb_node, xmlNode, node);

  xmlXPathNodeSetAdd(c_self, node);

  return rb_self;
}
Also aliased as: <<
unlink
Alias for: unlink
remove_attr(name) click to toggle source

Remove the attributed named name from all Node objects in the NodeSet

# File lib/nokogiri/xml/node_set.rb, line 223
def remove_attr(name)
  each { |el| el.delete(name) }
  self
end
Also aliased as: remove_attribute
remove_attribute(name)
Alias for: remove_attr
remove_class(name = nil) click to toggle source

Remove the class attribute name from all Node objects in the NodeSet.

See Nokogiri::XML::Node#remove_class for more information.

# File lib/nokogiri/xml/node_set.rb, line 163
def remove_class(name = nil)
  each do |el|
    el.remove_class(name)
  end
  self
end
reverse() click to toggle source

Returns a new NodeSet containing all the nodes in the NodeSet in reverse order

# File lib/nokogiri/xml/node_set.rb, line 417
def reverse
  node_set = NodeSet.new(document)
  (length - 1).downto(0) do |x|
    node_set.push(self[x])
  end
  node_set
end
set(key, value = nil, &block)
Alias for: attr
shift() click to toggle source

Returns the first element of the NodeSet and removes it. Returns nil if the set is empty.

# File lib/nokogiri/xml/node_set.rb, line 383
def shift
  return if length == 0

  delete(first)
end
length
Alias for: length
slice(index) → Node or nil
slice(start, length) → NodeSet or nil
slice(range) → NodeSet or nil

Element reference - returns the node at index, or returns a NodeSet containing nodes starting at start and continuing for length elements, or returns a 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.

Alias for: []
text()
Alias for: inner_text
to_a click to toggle source

Return this list as an Array

static VALUE
to_array(VALUE rb_self)
{
  xmlNodeSetPtr c_self ;
  VALUE list;
  int i;

  TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);

  list = rb_ary_new2(c_self->nodeNr);
  for (i = 0; i < c_self->nodeNr; i++) {
    VALUE elt = noko_xml_node_wrap_node_set_result(c_self->nodeTab[i], rb_self);
    rb_ary_push(list, elt);
  }

  return list;
}
Also aliased as: to_ary
to_a
Alias for: to_a
to_html(*args) click to toggle source

Convert this NodeSet to HTML

# File lib/nokogiri/xml/node_set.rb, line 341
def to_html(*args)
  if Nokogiri.jruby?
    options = args.first.is_a?(Hash) ? args.shift : {}
    options[:save_with] ||= Node::SaveOptions::DEFAULT_HTML
    args.insert(0, options)
  end
  if empty?
    encoding = (args.first.is_a?(Hash) ? args.first[:encoding] : nil)
    encoding ||= document.encoding
    encoding.nil? ? "" : "".encode(encoding)
  else
    map { |x| x.to_html(*args) }.join
  end
end
to_s() click to toggle source

Convert this NodeSet to a string.

# File lib/nokogiri/xml/node_set.rb, line 335
def to_s
  map(&:to_s).join
end
to_xhtml(*args) click to toggle source

Convert this NodeSet to XHTML

# File lib/nokogiri/xml/node_set.rb, line 358
def to_xhtml(*args)
  map { |x| x.to_xhtml(*args) }.join
end
to_xml(*args) click to toggle source

Convert this NodeSet to XML

# File lib/nokogiri/xml/node_set.rb, line 364
def to_xml(*args)
  map { |x| x.to_xml(*args) }.join
end
wrap(markup) → self click to toggle source
wrap(node) → self

Wrap each member of this NodeSet with the node parsed from markup or a dup of the node.

Parameters
  • markup (String) Markup that is parsed, once per member of the NodeSet, and used as the wrapper. Each node’s parent, if it exists, is used as the context node for parsing; otherwise the associated document is used. If the parsed fragment has multiple roots, the first root node is used as the wrapper.

  • node (Nokogiri::XML::Node) An element that is ‘#dup`ed and used as the wrapper.

Returns

self, to support chaining.

⚠ Note that if a String is passed, the markup will be parsed once per node in the NodeSet. You can avoid this overhead in cases where you know exactly the wrapper you wish to use by passing a Node instead.

Also see Node#wrap

Example with a String argument:

doc = Nokogiri::HTML5(<<~HTML)
  <html><body>
    <a>a</a>
    <a>b</a>
    <a>c</a>
    <a>d</a>
  </body></html>
HTML
doc.css("a").wrap("<div></div>")
doc.to_html
# => <html><head></head><body>
#      <div><a>a</a></div>
#      <div><a>b</a></div>
#      <div><a>c</a></div>
#      <div><a>d</a></div>
#    </body></html>

Example with a Node argument

💡 Note that this is faster than the equivalent call passing a String because it avoids having to reparse the wrapper markup for each node.

doc = Nokogiri::HTML5(<<~HTML)
  <html><body>
    <a>a</a>
    <a>b</a>
    <a>c</a>
    <a>d</a>
  </body></html>
HTML
doc.css("a").wrap(doc.create_element("div"))
doc.to_html
# => <html><head></head><body>
#      <div><a>a</a></div>
#      <div><a>b</a></div>
#      <div><a>c</a></div>
#      <div><a>d</a></div>
#    </body></html>
# File lib/nokogiri/xml/node_set.rb, line 328
def wrap(node_or_tags)
  map { |node| node.wrap(node_or_tags) }
  self
end
xpath *paths, [namespace-bindings, variable-bindings, custom-handler-class] click to toggle source

Search this node set for XPath paths. paths must be one or more XPath queries.

For more information see Nokogiri::XML::Searchable#xpath

# File lib/nokogiri/xml/node_set.rb, line 99
def xpath(*args)
  paths, handler, ns, binds = extract_params(args)

  inject(NodeSet.new(document)) do |set, node|
    set + xpath_internal(node, paths, handler, ns, binds)
  end
end
|(node_set) click to toggle source

Returns a new set built by merging the set and the elements of the given set.

static VALUE
rb_xml_node_set_union(VALUE rb_self, VALUE rb_other)
{
  xmlNodeSetPtr c_self, c_other;
  xmlNodeSetPtr c_new_node_set;

  if (!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet)) {
    rb_raise(rb_eArgError, "node_set must be a Nokogiri::XML::NodeSet");
  }

  TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
  TypedData_Get_Struct(rb_other, xmlNodeSet, &xml_node_set_type, c_other);

  c_new_node_set = xmlXPathNodeSetMerge(NULL, c_self);
  c_new_node_set = xmlXPathNodeSetMerge(c_new_node_set, c_other);

  return noko_xml_node_set_wrap(c_new_node_set, rb_iv_get(rb_self, "@document"));
}
Also aliased as: +

Searching via XPath or CSS Queries

↑ top

Public Instance Methods

/(*args)
Alias for: search
>(selector) → NodeSet click to toggle source

Search this node’s immediate children using CSS selector selector

# File lib/nokogiri/xml/searchable.rb, line 201
def >(selector) # rubocop:disable Naming/BinaryOperatorParameterName
  ns = document.root&.namespaces || {}
  xpath(CSS.xpath_for(selector, prefix: "./", ns: ns).first)
end
at_css(*rules, [namespace-bindings, custom-pseudo-class]) click to toggle source

Search this object for CSS rules, and return only the first match. rules must be one or more CSS selectors.

See Searchable#css for more information.

# File lib/nokogiri/xml/searchable.rb, line 143
def at_css(*args)
  css(*args).first
end
at_xpath(*paths, [namespace-bindings, variable-bindings, custom-handler-class]) click to toggle source

Search this node for XPath paths, and return only the first match. paths must be one or more XPath queries.

See Searchable#xpath for more information.

# File lib/nokogiri/xml/searchable.rb, line 193
def at_xpath(*args)
  xpath(*args).first
end