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
Create a NodeSet with document defaulting to list
# File lib/nokogiri/xml/node_set.rb, line 17
def initialize document, list = []
@document = document
document.decorate(self)
list.each { |x| self << x }
yield self if block_given?
end Set Intersection — Returns a new NodeSet containing nodes common to the two NodeSets.
static VALUE intersection(VALUE self, VALUE rb_other)
{
xmlNodeSetPtr node_set, other ;
xmlNodeSetPtr intersection;
if(!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet))
rb_raise(rb_eArgError, "node_set must be a Nokogiri::XML::NodeSet");
Data_Get_Struct(self, xmlNodeSet, node_set);
Data_Get_Struct(rb_other, xmlNodeSet, other);
intersection = xmlXPathIntersection(node_set, other);
return Nokogiri_wrap_xml_node_set(intersection, rb_iv_get(self, "@document"));
} 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 self, VALUE rb_other)
{
xmlNodeSetPtr node_set, 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");
Data_Get_Struct(self, xmlNodeSet, node_set);
Data_Get_Struct(rb_other, xmlNodeSet, other);
new = xmlXPathNodeSetMerge(NULL, node_set);
for (j = 0 ; j < other->nodeNr ; ++j) {
xpath_node_set_del(new, other->nodeTab[j]);
}
return Nokogiri_wrap_xml_node_set(new, rb_iv_get(self, "@document"));
} 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 283
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 Search this NodeSet's nodes' immediate children using CSS selector selector
# File lib/nokogiri/xml/node_set.rb, line 100 def > selector ns = document.root.namespaces xpath CSS.xpath_for(selector, :prefix => "./", :ns => ns).first end
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 self)
{
VALUE arg ;
long beg, len ;
xmlNodeSetPtr node_set;
Data_Get_Struct(self, xmlNodeSet, node_set);
if (argc == 2) {
beg = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
if (beg < 0) {
beg += node_set->nodeNr ;
}
return subseq(self, beg, len);
}
if (argc != 1) {
rb_scan_args(argc, argv, "11", NULL, NULL);
}
arg = argv[0];
if (FIXNUM_P(arg)) {
return index_at(self, FIX2LONG(arg));
}
/* if arg is Range */
switch (rb_range_beg_len(arg, &beg, &len, (long)node_set->nodeNr, 0)) {
case Qfalse:
break;
case Qnil:
return Qnil;
default:
return subseq(self, beg, len);
}
return index_at(self, NUM2LONG(arg));
} Search this object for paths, and return only the first result. paths must be one or more XPath or CSS queries.
See Nokogiri::XML::Searchable#search for more information.
Or, if passed an integer, index into the NodeSet:
node_set.at(3) # same as node_set[3]
# File lib/nokogiri/xml/node_set.rb, line 117
def at *args
if args.length == 1 && args.first.is_a?(Numeric)
return self[args.first]
end
super(*args)
end Set the attribute key to value or the return value of blk on all Node objects in the NodeSet.
# File lib/nokogiri/xml/node_set.rb, line 165
def attr key, value = nil, &blk
unless Hash === key || key && (value || blk)
return first.attribute(key)
end
hash = key.is_a?(Hash) ? key : { key => value }
hash.each { |k,v| each { |el| el[k] = v || blk[el] } }
self
end 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 74
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 Delete node from the Nodeset, if it is a member. Returns the deleted node if found, otherwise returns nil.
static VALUE
delete(VALUE self, VALUE rb_node)
{
xmlNodeSetPtr node_set;
xmlNodePtr node;
Check_Node_Set_Node_Type(rb_node);
Data_Get_Struct(self, xmlNodeSet, node_set);
Data_Get_Struct(rb_node, xmlNode, node);
if (xmlXPathNodeSetContains(node_set, node)) {
xpath_node_set_del(node_set, node);
return rb_node;
}
return Qnil ;
} Duplicate this node set
static VALUE duplicate(VALUE self)
{
xmlNodeSetPtr node_set;
xmlNodeSetPtr dupl;
Data_Get_Struct(self, xmlNodeSet, node_set);
dupl = xmlXPathNodeSetMerge(NULL, node_set);
return Nokogiri_wrap_xml_node_set(dupl, rb_iv_get(self, "@document"));
} Iterate over each node, yielding to block
# File lib/nokogiri/xml/node_set.rb, line 188
def each(&block)
0.upto(length - 1) do |x|
yield self[x]
end
end Is this NodeSet empty?
# File lib/nokogiri/xml/node_set.rb, line 41 def empty? length == 0 end
Filter this list for nodes that match expr
# File lib/nokogiri/xml/node_set.rb, line 128
def filter expr
find_all { |node| node.matches?(expr) }
end Get the first element of the NodeSet.
# File lib/nokogiri/xml/node_set.rb, line 26
def first n = nil
return self[0] unless n
list = []
[n, length].min.times { |i| list << self[i] }
list
end Returns true if any member of node set equals node.
static VALUE include_eh(VALUE self, VALUE rb_node)
{
xmlNodeSetPtr node_set;
xmlNodePtr node;
Check_Node_Set_Node_Type(rb_node);
Data_Get_Struct(self, xmlNodeSet, node_set);
Data_Get_Struct(rb_node, xmlNode, node);
return (xmlXPathNodeSetContains(node_set, node) ? Qtrue : Qfalse);
} Returns the index of the first node in self that is == to node. Returns nil if no match is found.
# File lib/nokogiri/xml/node_set.rb, line 47
def index(node)
each_with_index { |member, j| return j if member == node }
nil
end Get the inner html of all contained Node objects
# File lib/nokogiri/xml/node_set.rb, line 214
def inner_html *args
collect{|j| j.inner_html(*args) }.join('')
end 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 207
def inner_text
collect(&:inner_text).join('')
end Return a nicely formated string representation
# File lib/nokogiri/xml/node_set.rb, line 316
def inspect
"[#{map(&:inspect).join ', '}]"
end Get the last element of the NodeSet.
# File lib/nokogiri/xml/node_set.rb, line 35 def last self[-1] end
Get the length of the node set
static VALUE length(VALUE self)
{
xmlNodeSetPtr node_set;
Data_Get_Struct(self, xmlNodeSet, node_set);
return node_set ? INT2NUM(node_set->nodeNr) : INT2NUM(0);
} Removes the last element from set and returns it, or nil if the set is empty
# File lib/nokogiri/xml/node_set.rb, line 266 def pop return nil if length == 0 delete last end
Append node to the NodeSet.
static VALUE push(VALUE self, VALUE rb_node)
{
xmlNodeSetPtr node_set;
xmlNodePtr node;
Check_Node_Set_Node_Type(rb_node);
Data_Get_Struct(self, xmlNodeSet, node_set);
Data_Get_Struct(rb_node, xmlNode, node);
xmlXPathNodeSetAdd(node_set, node);
return self;
} Remove the class attribute name from all Node objects in the NodeSet. If name is nil, remove the class attribute from all Nodes in the NodeSet.
# File lib/nokogiri/xml/node_set.rb, line 146
def remove_class name = nil
each do |el|
if name
classes = el['class'].to_s.split(/\s+/)
if classes.empty?
el.delete 'class'
else
el['class'] = (classes - [name]).uniq.join " "
end
else
el.delete "class"
end
end
self
end 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 274 def shift return nil if length == 0 delete first end
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 self)
{
VALUE arg ;
long beg, len ;
xmlNodeSetPtr node_set;
Data_Get_Struct(self, xmlNodeSet, node_set);
if (argc == 2) {
beg = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
if (beg < 0) {
beg += node_set->nodeNr ;
}
return subseq(self, beg, len);
}
if (argc != 1) {
rb_scan_args(argc, argv, "11", NULL, NULL);
}
arg = argv[0];
if (FIXNUM_P(arg)) {
return index_at(self, FIX2LONG(arg));
}
/* if arg is Range */
switch (rb_range_beg_len(arg, &beg, &len, (long)node_set->nodeNr, 0)) {
case Qfalse:
break;
case Qnil:
return Qnil;
default:
return subseq(self, beg, len);
}
return index_at(self, NUM2LONG(arg));
} Return this list as an Array
static VALUE to_array(VALUE self, VALUE rb_node)
{
xmlNodeSetPtr node_set ;
VALUE list;
int i;
Data_Get_Struct(self, xmlNodeSet, node_set);
list = rb_ary_new2(node_set->nodeNr);
for(i = 0; i < node_set->nodeNr; i++) {
VALUE elt = Nokogiri_wrap_xml_node_set_node(node_set->nodeTab[i], self);
rb_ary_push( list, elt );
}
return list;
} # File lib/nokogiri/xml/node_set.rb, line 237
def to_html *args
if Nokogiri.jruby?
options = args.first.is_a?(Hash) ? args.shift : {}
if !options[:save_with]
options[:save_with] = Node::SaveOptions::NO_DECLARATION | Node::SaveOptions::NO_EMPTY_TAGS | Node::SaveOptions::AS_HTML
end
args.insert(0, options)
end
map { |x| x.to_html(*args) }.join
end Convert this NodeSet to a string.
# File lib/nokogiri/xml/node_set.rb, line 231 def to_s map(&:to_s).join end
Convert this NodeSet to XHTML
# File lib/nokogiri/xml/node_set.rb, line 250
def to_xhtml *args
map { |x| x.to_xhtml(*args) }.join
end Unlink this NodeSet and all Node objects it contains from their current context.
static VALUE unlink_nodeset(VALUE self)
{
xmlNodeSetPtr node_set;
int j, nodeNr ;
Data_Get_Struct(self, xmlNodeSet, node_set);
nodeNr = node_set->nodeNr ;
for (j = 0 ; j < nodeNr ; j++) {
if (! Nokogiri_namespace_eh(node_set->nodeTab[j])) {
VALUE node ;
xmlNodePtr node_ptr;
node = Nokogiri_wrap_xml_node(Qnil, node_set->nodeTab[j]);
rb_funcall(node, rb_intern("unlink"), 0); /* modifies the C struct out from under the object */
Data_Get_Struct(node, xmlNode, node_ptr);
node_set->nodeTab[j] = node_ptr ;
}
}
return self ;
} Wrap this NodeSet with html or the results of the builder in blk
# File lib/nokogiri/xml/node_set.rb, line 220
def wrap(html, &blk)
each do |j|
new_parent = document.parse(html).first
j.add_next_sibling(new_parent)
new_parent.add_child(j)
end
self
end 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 90
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 Returns a new set built by merging the set and the elements of the given set.
static VALUE set_union(VALUE self, VALUE rb_other)
{
xmlNodeSetPtr node_set, other;
xmlNodeSetPtr new;
if(!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet))
rb_raise(rb_eArgError, "node_set must be a Nokogiri::XML::NodeSet");
Data_Get_Struct(self, xmlNodeSet, node_set);
Data_Get_Struct(rb_other, xmlNodeSet, other);
new = xmlXPathNodeSetMerge(NULL, node_set);
new = xmlXPathNodeSetMerge(new, other);
return Nokogiri_wrap_xml_node_set(new, rb_iv_get(self, "@document"));
}
© 2008–2017 Aaron Patterson, Mike Dalessio, Charles Nutter, Sergio Arbeo
Patrick Mahoney, Yoko Harada, Akinori Musha, John Shahid
Licensed under the MIT License.