Class: Nokogiri::XML::NodeSet
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Instance Chain:
self,
Enumerable,
Searchable
|
|
| Inherits: | Object |
| Defined in: | lib/nokogiri/xml/node_set.rb, ext/nokogiri/xml_node_set.c |
Overview
A NodeSet is an Enumerable that contains a list of Node objects.
Typically a NodeSet is returned as a result of searching a Document via Searchable#css or Searchable#xpath.
Note that the #dup and #clone methods perform shallow copies; these methods do not copy the Nodes contained in the NodeSet (similar to how Array and other Enumerable classes work).
Constant Summary
-
IMPLIED_XPATH_CONTEXTS =
Internal use only
# File 'lib/nokogiri/xml/node_set.rb', line 446[".//", "self::"].freeze
Searchable - Included
Class Method Summary
-
.new(document, list = []) {|_self| ... } ⇒ NodeSet
constructor
Create a
NodeSetwith #document defaulting tolist
Instance Attribute Summary
-
#document
rw
The Document this
NodeSetis associated with. -
#empty? ⇒ Boolean
readonly
Is this
NodeSetempty?
Instance Method Summary
-
#%(*args)
Alias for #at.
-
#&(node_set)
Set Intersection — Returns a new
NodeSetcontaining nodes common to the two NodeSets. -
#+(rb_other)
Alias for #|.
-
#-(node_set)
Difference - returns a new
NodeSetthat is a copy of thisNodeSet, removing each item that also appears innode_set -
#<<(rb_node)
Alias for #push.
-
#==(other)
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. - #[](index) ⇒ Node? (also: #slice)
-
#add_class(name)
Add the class attribute
nameto allNodeobjects in theNodeSet. -
#after(datum)
Insert
datumafter the lastNodein thisNodeSet. -
#append_class(name)
Append the class attribute
nameto allNodeobjects in theNodeSet. -
#search(*paths, [namespace-bindings, xpath-variable-bindings, custom-handler-class])
(also: #%)
Search this object for
paths, and return only the first result. - #attr(key, value = nil, &block) (also: #set, #attribute)
-
#attribute(key, value = nil, &block)
Alias for #attr.
-
#before(datum)
Insert
datumbefore the firstNodein thisNodeSet. -
#children
Returns a new
NodeSetcontaining all the children of all the nodes in theNodeSet. -
#css(*rules, [namespace-bindings, custom-pseudo-class])
Search this node set for
::Nokogiri::CSSrules. -
#deconstruct() → Array)
Returns the members of this
NodeSetas an array, to use in pattern matching. -
#delete(node)
Delete
nodefrom the Nodeset, if it is a member. -
#each
Iterate over each node, yielding to
block -
#filter(expr)
Filter this list for nodes that match
expr -
#first(n = nil)
Get the first element of the
NodeSet. -
#include?(node)
Returns true if any member of node set equals
node. -
#index(node = nil)
Returns the index of the first node in self that is == to
nodeor meets the given block. -
#inner_html(*args)
Get the inner html of all contained
Nodeobjects. -
#inner_text
(also: #text)
Get the inner text of all contained
Nodeobjects. -
#inspect
Return a nicely formatted string representation.
-
#last
Get the last element of the
NodeSet. -
#length
(also: #size)
Get the length of the node set.
-
#pop
Removes the last element from set and returns it, or
nilif the set is empty. -
#push(node)
(also: #<<)
Append
nodeto theNodeSet. -
#remove
Alias for #unlink.
-
#remove_attr(name)
(also: #remove_attribute)
Remove the attributed named
namefrom allNodeobjects in theNodeSet. -
#remove_attribute(name)
Alias for #remove_attr.
-
#remove_class(name = nil)
Remove the class attribute
namefrom allNodeobjects in theNodeSet. -
#reverse
Returns a new
NodeSetcontaining all the nodes in theNodeSetin reverse order. -
#set(key, value = nil, &block)
Alias for #attr.
-
#shift
Returns the first element of the
NodeSetand removes it. -
#size
Alias for #length.
-
#slice(index) ⇒ Node?
Alias for #[].
-
#text
Alias for #inner_text.
-
#to_a ⇒ ?
(also: #to_ary)
Return this list as an Array.
-
#to_ary
Alias for #to_a.
-
#to_html(*args)
Convert this
NodeSetto::Nokogiri::HTML. -
#to_s
Convert this
NodeSetto a string. -
#to_xhtml(*args)
Convert this
NodeSetto XHTML. -
#to_xml(*args)
Convert this
NodeSetto::Nokogiri::XML. -
#unlink
(also: #remove)
Unlink this
NodeSetand allNodeobjects it contains from their current context. -
#wrap(markup) ⇒ self
Wrap each member of this
NodeSetwith the node parsed frommarkupor a dup of thenode. -
#xpath(*paths, [namespace-bindings, variable-bindings, custom-handler-class])
Search this node set for
XPathpaths. -
#|(node_set)
(also: #+)
Returns a new set built by merging the set and the elements of the given set.
- #initialize_copy(rb_other) private Internal use only
Searchable - Included
| #% | Alias for Searchable#at. |
| #/ | Alias for Searchable#search. |
| #> | Search this node’s immediate children using |
| #at | Search this object for |
| #at_css | Search this object for |
| #at_xpath | Search this node for |
| #css | Search this object for |
| #search | Search this object for |
| #xpath | Search this node for |
| #css_internal, #css_rules_to_xpath, #xpath_impl, #xpath_internal, #xpath_query_from_css_rule, #extract_params | |
Constructor Details
.new(document, list = []) {|_self| ... } ⇒ NodeSet
Create a NodeSet with #document defaulting to list
Instance Attribute Details
#document (rw)
The Document this NodeSet is associated with
# File 'lib/nokogiri/xml/node_set.rb', line 19
attr_accessor :document
#empty? ⇒ Boolean (readonly)
Is this NodeSet empty?
# File 'lib/nokogiri/xml/node_set.rb', line 47
def empty? length == 0 end
Instance Method Details
#%(*args)
Alias for #at.
# File 'lib/nokogiri/xml/node_set.rb', line 128
alias_method :%, :at
#&(node_set)
Set Intersection — Returns a new NodeSet containing nodes common to the two NodeSets.
# File 'ext/nokogiri/xml_node_set.c', line 205
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"));
}
#+(rb_other)
Alias for #|.
# File 'lib/nokogiri/xml/node_set.rb', line 433
alias_method :+, :|
#-(node_set)
Difference - returns a new NodeSet that is a copy of this NodeSet, removing each item that also appears in node_set
# File 'ext/nokogiri/xml_node_set.c', line 277
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"));
}
#<<(rb_node)
Alias for #push.
# File 'lib/nokogiri/xml/node_set.rb', line 75
alias_method :<<, :push
#==(other)
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
#[](index) ⇒ Node?
#[](start, length) ⇒ NodeSet?
#[](range) ⇒ NodeSet?
#slice(index) ⇒ Node?
#slice(start, length) ⇒ NodeSet?
#slice(range) ⇒ NodeSet?
Also known as: #slice
NodeSet?
#[](range) ⇒ NodeSet?
#slice(index) ⇒ Node?
#slice(start, length) ⇒ NodeSet?
#slice(range) ⇒ NodeSet?
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.
# File 'ext/nokogiri/xml_node_set.c', line 354
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));
}
#add_class(name)
Add the class attribute name to all Node objects in the NodeSet.
See Node#add_class for more information.
# File 'lib/nokogiri/xml/node_set.rb', line 141
def add_class(name) each do |el| el.add_class(name) end self end
#after(datum)
Insert datum after the last Node in this NodeSet
# File 'lib/nokogiri/xml/node_set.rb', line 71
def after(datum) last.after(datum) end
#append_class(name)
Append the class attribute name to all Node objects in the NodeSet.
See Node#append_class for more information.
# File 'lib/nokogiri/xml/node_set.rb', line 153
def append_class(name) each do |el| el.append_class(name) end self end
#search(*paths, [namespace-bindings, xpath-variable-bindings, custom-handler-class]) Also known as: #%
Search this object for paths, and return only the first result. paths must be one or more XPath or ::Nokogiri::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]
#attr(key, value = nil, &block) Also known as: #set, #attribute
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 }
#attribute(key, value = nil, &block)
Alias for #attr.
# File 'lib/nokogiri/xml/node_set.rb', line 221
alias_method :attribute, :attr
#before(datum)
Insert datum before the first Node in this NodeSet
# File 'lib/nokogiri/xml/node_set.rb', line 65
def before(datum) first.before(datum) end
#children
Returns a new NodeSet containing all the children of all the nodes in the NodeSet
#css(*rules, [namespace-bindings, custom-pseudo-class])
Search this node set for ::Nokogiri::CSS rules. rules must be one or more ::Nokogiri::CSS selectors. For example:
For more information see Searchable#css
#deconstruct() → Array)
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 442
def deconstruct to_a end
#delete(node)
Delete node from the Nodeset, if it is a member. Returns the deleted node if found, otherwise returns nil.
# File 'ext/nokogiri/xml_node_set.c', line 180
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 ;
}
#each
Iterate over each node, yielding to block
# File 'lib/nokogiri/xml/node_set.rb', line 233
def each return to_enum unless block_given? 0.upto(length - 1) do |x| yield self[x] end self end
#filter(expr)
Filter this list for nodes that match expr
# File 'lib/nokogiri/xml/node_set.rb', line 132
def filter(expr) find_all { |node| node.matches?(expr) } end
#first(n = nil)
Get the first element of the NodeSet.
# File 'lib/nokogiri/xml/node_set.rb', line 31
def first(n = nil) return self[0] unless n list = [] [n, length].min.times { |i| list << self[i] } list end
#include?(node)
Returns true if any member of node set equals node.
# File 'ext/nokogiri/xml_node_set.c', line 229
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)
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 53
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
#initialize_copy(rb_other) (private)
# File 'ext/nokogiri/xml_node_set.c', line 87
static VALUE
rb_xml_node_set_initialize_copy(VALUE rb_self, VALUE rb_other)
{
xmlNodeSetPtr c_self, c_other;
VALUE rb_document;
TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
TypedData_Get_Struct(rb_other, xmlNodeSet, &xml_node_set_type, c_other);
xmlXPathNodeSetMerge(c_self, c_other);
rb_document = rb_iv_get(rb_other, "@document");
if (!NIL_P(rb_document)) {
rb_iv_set(rb_self, "@document", rb_document);
rb_funcall(rb_document, decorate, 1, rb_self);
}
return rb_self;
}
#inner_html(*args)
Get the inner html of all contained Node objects
# File 'lib/nokogiri/xml/node_set.rb', line 262
def inner_html(*args) collect { |j| j.inner_html(*args) }.join("") end
#inner_text Also known as: #text
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 Node#content for more information.
# File 'lib/nokogiri/xml/node_set.rb', line 255
def inner_text collect(&:inner_text).join("") end
#inspect
Return a nicely formatted string representation
# File 'lib/nokogiri/xml/node_set.rb', line 429
def inspect "[#{map(&:inspect).join(", ")}]" end
#last
Get the last element of the NodeSet.
# File 'lib/nokogiri/xml/node_set.rb', line 41
def last self[-1] end
#length Also known as: #size
Get the length of the node set
# File 'ext/nokogiri/xml_node_set.c', line 141
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);
}
#pop
Removes the last element from set and returns it, or nil if the set is empty
#push(node) Also known as: #<<
Append node to the NodeSet.
# File 'ext/nokogiri/xml_node_set.c', line 157
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;
}
#remove
Alias for #unlink.
# File 'lib/nokogiri/xml/node_set.rb', line 76
alias_method :remove, :unlink
#remove_attr(name) Also known as: #remove_attribute
Remove the attributed named name from all Node objects in the NodeSet
#remove_attribute(name)
Alias for #remove_attr.
# File 'lib/nokogiri/xml/node_set.rb', line 229
alias_method :remove_attribute, :remove_attr
#remove_class(name = nil)
Remove the class attribute name from all Node objects in the NodeSet.
See Node#remove_class for more information.
# File 'lib/nokogiri/xml/node_set.rb', line 165
def remove_class(name = nil) each do |el| el.remove_class(name) end self end
#reverse
Returns a new NodeSet containing all the nodes in the NodeSet in reverse order
#set(key, value = nil, &block)
Alias for #attr.
# File 'lib/nokogiri/xml/node_set.rb', line 220
alias_method :set, :attr
#shift
Returns the first element of the NodeSet and removes it. Returns nil if the set is empty.
#size
Alias for #length.
# File 'lib/nokogiri/xml/node_set.rb', line 370
alias_method :size, :length
Alias for #[].
#text
Alias for #inner_text.
# File 'lib/nokogiri/xml/node_set.rb', line 258
alias_method :text, :inner_text
#to_a ⇒ ? Also known as: #to_ary
Return this list as an Array
# File 'ext/nokogiri/xml_node_set.c', line 401
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;
}
#to_ary
Alias for #to_a.
# File 'lib/nokogiri/xml/node_set.rb', line 371
alias_method :to_ary, :to_a
#to_html(*args)
Convert this NodeSet to ::Nokogiri::HTML
# File 'lib/nokogiri/xml/node_set.rb', line 343
def to_html(*args) if Nokogiri.jruby? = args.first.is_a?(Hash) ? args.shift : {} [:save_with] ||= Node::SaveOptions::DEFAULT_HTML args.insert(0, ) 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
Convert this NodeSet to a string.
# File 'lib/nokogiri/xml/node_set.rb', line 337
def to_s map(&:to_s).join end
#to_xhtml(*args)
Convert this NodeSet to XHTML
# File 'lib/nokogiri/xml/node_set.rb', line 360
def to_xhtml(*args) map { |x| x.to_xhtml(*args) }.join end
#to_xml(*args)
Convert this NodeSet to ::Nokogiri::XML
# File 'lib/nokogiri/xml/node_set.rb', line 366
def to_xml(*args) map { |x| x.to_xml(*args) }.join end
#unlink Also known as: #remove
Unlink this NodeSet and all Node objects it contains from their current context.
# File 'ext/nokogiri/xml_node_set.c', line 425
static VALUE
unlink_nodeset(VALUE rb_self)
{
xmlNodeSetPtr c_self;
int j, nodeNr ;
TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
nodeNr = c_self->nodeNr ;
for (j = 0 ; j < nodeNr ; j++) {
if (! NOKOGIRI_NAMESPACE_EH(c_self->nodeTab[j])) {
VALUE node ;
xmlNodePtr node_ptr;
node = noko_xml_node_wrap(Qnil, c_self->nodeTab[j]);
rb_funcall(node, rb_intern("unlink"), 0); /* modifies the C struct out from under the object */
Noko_Node_Get_Struct(node, xmlNode, node_ptr);
c_self->nodeTab[j] = node_ptr ;
}
}
return rb_self ;
}
#wrap(markup) ⇒ self
#wrap(node) ⇒ self
self
#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 330
def wrap() map { |node| node.wrap() } self end
#xpath(*paths, [namespace-bindings, variable-bindings, custom-handler-class])
Search this node set for XPath paths. paths must be one or more XPath queries.
For more information see Searchable#xpath
#|(node_set) Also known as: #+
Returns a new set built by merging the set and the elements of the given set.
# File 'ext/nokogiri/xml_node_set.c', line 251
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"));
}