class Nokogiri::XML::NodeSet
def self.new document, list = [] # :nodoc:
def self.new document, list = [] # :nodoc: set = NodeSet.wrap(LibXML.xmlXPathNodeSetCreate(nil)) set.document = document list.each { |x| set << x } yield set if block_given? set end
def self.wrap(ptr) # :nodoc:
def self.wrap(ptr) # :nodoc: set = allocate set.cstruct = LibXML::XmlNodeSet.new(ptr) set end
def &(node_set) # :nodoc:
def &(node_set) # :nodoc: raise(ArgumentError, "node_set must be a Nokogiri::XML::NodeSet") unless node_set.is_a?(XML::NodeSet) new_set_ptr = LibXML.xmlXPathIntersection(cstruct, node_set.cstruct) NodeSet.wrap(new_set_ptr) end
def -(node_set) # :nodoc:
def -(node_set) # :nodoc: raise(ArgumentError, "node_set must be a Nokogiri::XML::NodeSet") unless node_set.is_a?(XML::NodeSet) new_set_ptr = LibXML.xmlXPathNodeSetMerge(nil, self.cstruct) other_nodetab = node_set.cstruct.nodeTab node_set.cstruct[:nodeNr].times do |j| LibXML.xmlXPathNodeSetDel(new_set_ptr, other_nodetab[j]) end NodeSet.wrap(new_set_ptr) end
def == other
of elements and if each element is equal to the corresponding
Equality -- Two NodeSets are equal if the contain the same number
##
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
def [](*args) # :nodoc:
def [](*args) # :nodoc: raise(ArgumentError, "got #{args.length} arguments, expected 1 (or 2)") if args.length > 2 if args.length == 2 beg = args[0] len = args[1] beg += cstruct[:nodeNr] if beg < 0 return subseq(beg, len) end arg = args[0] return subseq(arg.first, arg.last-arg.first+1) if arg.is_a?(Range) index_at(arg) end
def add_class name
##
def add_class name each do |el| classes = el['class'].to_s.split(/\s+/) el['class'] = classes.push(name).uniq.join " " end self end
def after datum
##
def after datum last.after datum end
def at path, ns = document.root ? document.root.namespaces : {}
If path is a string, search this document for +path+ returning the
##
def at path, ns = document.root ? document.root.namespaces : {} return self[path] if path.is_a?(Numeric) search(path, ns).first end
def attr key, value = nil, &blk
Set the attribute +key+ to +value+ or the return value of +blk+
##
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
def before datum
##
def before datum first.before datum end
def children
Returns a new NodeSet containing all the children of all the nodes in
##
def children inject(NodeSet.new(document)) { |set, node| set += node.children } end
def css *paths
Search this NodeSet for css +paths+
##
def css *paths handler = ![ Hash, String, Symbol ].include?(paths.last.class) ? paths.pop : nil ns = paths.last.is_a?(Hash) ? paths.pop : nil sub_set = NodeSet.new(document) each do |node| doc = node.document search_ns = ns || doc.root ? doc.root.namespaces : {} xpaths = paths.map { |rule| [ CSS.xpath_for(rule.to_s, :prefix => ".//", :ns => search_ns), CSS.xpath_for(rule.to_s, :prefix => "self::", :ns => search_ns) ].join(' | ') } sub_set += node.xpath(*(xpaths + [search_ns, handler].compact)) end document.decorate(sub_set) sub_set end
def delete(node) # :nodoc:
def delete(node) # :nodoc: raise(ArgumentError, "node must be a Nokogiri::XML::Node") unless node.is_a?(XML::Node) if LibXML.xmlXPathNodeSetContains(cstruct, node.cstruct) != 0 LibXML.xmlXPathNodeSetDel(cstruct, node.cstruct) return node end return nil end
def dup # :nodoc:
def dup # :nodoc: dup = LibXML.xmlXPathNodeSetMerge(nil, self.cstruct) NodeSet.wrap(dup) end
def each(&block)
##
def each(&block) 0.upto(length - 1) do |x| yield self[x] end end
def empty?
##
def empty? length == 0 end
def filter expr
##
def filter expr find_all { |node| node.matches?(expr) } end
def first n = nil
##
def first n = nil return self[0] unless n list = [] 0.upto(n - 1) do |i| list << self[i] end list end
def include?(node) # :nodoc:
def include?(node) # :nodoc: raise(ArgumentError, "node must be a Nokogiri::XML::Node") unless node.is_a?(XML::Node) (LibXML.xmlXPathNodeSetContains(cstruct, node.cstruct) != 0) ? true : false end
def index(node)
##
def index(node) each_with_index { |member, j| return j if member == node } nil end
def index_at(number) # :nodoc:
def index_at(number) # :nodoc: return nil if (number >= cstruct[:nodeNr] || number.abs > cstruct[:nodeNr]) number = number + cstruct[:nodeNr] if number < 0 node_ptr = cstruct.nodeAt(number) node_cstruct = LibXML::XmlNode.new(node_ptr) if node_cstruct[:type] == XML::Node::NAMESPACE_DECL Namespace.wrap(document.cstruct, node_ptr) else Node.wrap(node_cstruct) end end
def initialize document, list = []
def initialize document, list = [] @document = document list.each { |x| self << x } yield self if block_given? end
def inner_html *args
##
def inner_html *args collect{|j| j.inner_html(*args) }.join('') end
def inner_text
##
def inner_text collect{|j| j.inner_text}.join('') end
def inspect
##
def inspect "[#{map { |c| c.inspect }.join ', '}]" end
def last
##
def last self[length - 1] end
def length # :nodoc:
def length # :nodoc: cstruct.pointer.null? ? 0 : cstruct[:nodeNr] end
def pop
Removes the last element from set and returns it, or +nil+ if
##
def pop return nil if length == 0 delete last end
def push(node) # :nodoc:
def push(node) # :nodoc: raise(ArgumentError, "node must be a Nokogiri::XML::Node") unless node.is_a?(XML::Node) LibXML.xmlXPathNodeSetAdd(cstruct, node.cstruct) self end
def remove_attr name
##
def remove_attr name each { |el| el.delete name } self end
def remove_class name = nil
If +name+ is nil, remove the class attribute from all Nodes in the
Remove the class attribute +name+ from all Node objects in the NodeSet.
##
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
def reverse
Returns a new NodeSet containing all the nodes in the NodeSet
##
def reverse node_set = NodeSet.new(document) (length - 1).downto(0) do |x| node_set.push self[x] end node_set end
def search *paths
For more information see Nokogiri::XML::Node#css and
Search this document for +paths+
##
def search *paths handler = ![ Hash, String, Symbol ].include?(paths.last.class) ? paths.pop : nil ns = paths.last.is_a?(Hash) ? paths.pop : nil sub_set = NodeSet.new(document) paths.each do |path| sub_set += send( path =~ /^(\.\/|\/)/ ? :xpath : :css, *(paths + [ns, handler]).compact ) end document.decorate(sub_set) sub_set end
def shift
Returns the first element of the NodeSet and removes it. Returns
##
def shift return nil if length == 0 delete first end
def subseq(beg, len) # :nodoc:
def subseq(beg, len) # :nodoc: return nil if beg > cstruct[:nodeNr] return nil if beg < 0 || len < 0 set = NodeSet.wrap(LibXML.xmlXPathNodeSetCreate(nil)) beg.upto(beg+len-1) do |j| LibXML.xmlXPathNodeSetAdd(set.cstruct, cstruct.nodeAt(j)); end set end
def to_a # :nodoc:
def to_a # :nodoc: cstruct.nodeTab.collect do |node| node_cstruct = LibXML::XmlNode.new(node) if node_cstruct[:type] == XML::Node::NAMESPACE_DECL Namespace.wrap(document.cstruct, node) else Node.wrap(node_cstruct) end end end
def to_html *args
##
def to_html *args map { |x| x.to_html(*args) }.join end
def to_s
##
def to_s map { |x| x.to_s }.join end
def to_xhtml *args
##
def to_xhtml *args map { |x| x.to_xhtml(*args) }.join end
def to_xml *args
##
def to_xml *args map { |x| x.to_xml(*args) }.join end
def unlink # :nodoc:
def unlink # :nodoc: nodetab = cstruct.nodeTab cstruct[:nodeNr].times do |j| node_cstruct = LibXML::XmlNode.new(nodetab[j]) if node_cstruct[:type] != XML::Node::NAMESPACE_DECL node = Node.wrap(node_cstruct) node.unlink nodetab[j] = node.cstruct.pointer end end cstruct.nodeTab = nodetab self end
def wrap(html, &blk)
##
def wrap(html, &blk) each do |j| new_parent = Nokogiri.make(html, &blk) j.add_next_sibling(new_parent) new_parent.add_child(j) end self end
def xpath *paths
Search this NodeSet for XPath +paths+
##
def xpath *paths handler = ![ Hash, String, Symbol ].include?(paths.last.class) ? paths.pop : nil ns = paths.last.is_a?(Hash) ? paths.pop : nil sub_set = NodeSet.new(document) each do |node| sub_set += node.xpath(*(paths + [ns, handler].compact)) end document.decorate(sub_set) sub_set end
def |(node_set) # :nodoc:
def |(node_set) # :nodoc: raise(ArgumentError, "node_set must be a Nokogiri::XML::NodeSet") unless node_set.is_a?(XML::NodeSet) new_set_ptr = LibXML::xmlXPathNodeSetMerge(nil, self.cstruct) new_set_ptr = LibXML::xmlXPathNodeSetMerge(new_set_ptr, node_set.cstruct) new_set = NodeSet.wrap(new_set_ptr) new_set.document = document new_set end