module Nokogiri::XML::Searchable

def at(*args)

See Searchable#search for more information.

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

call-seq: search *paths, [namespace-bindings, xpath-variable-bindings, custom-handler-class]
##
def at(*args)
  search(*args).first
end

def at_css(*args)

See Searchable#css for more information.

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

call-seq: css *rules, [namespace-bindings, custom-pseudo-class]
#
def at_css(*args)
  css(*args).first
end

def at_xpath(*args)

See Searchable#xpath for more information.

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

call-seq: xpath *paths, [namespace-bindings, variable-bindings, custom-handler-class]
#
def at_xpath(*args)
  xpath(*args).first
end

def css(*args)


(e.g., "H1" is distinct from "h1").
found in an XML document, where tags names are case-sensitive
will match only lowercase CSS queries. However, "H1" might be
an HTML document, you'll never find anything, since HTML tags
to your document type. That is, if you're looking for "H1" in
Note that the CSS query string is case-sensitive with regards

}.new)
end
node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
def regex node_set, regex
node.css('title:regex("\w+")', Class.new {

arguments are ones that you pass in. For example:
method will be the current matching NodeSet. Any other
pseudo class you want defined. The first argument to the
custom pseudo classes, create a class and implement the custom
Custom CSS pseudo classes may also be defined. To define

node.css('bike|tire', {'bike' => 'http://schwinn.com/'})

A hash of namespace bindings may be appended. For example:

node.css('div + p.green', 'div#one')
node.css('body h1.bold')
node.css('title')

selectors. For example:
Search this object for CSS +rules+. +rules+ must be one or more CSS

call-seq: css *rules, [namespace-bindings, custom-pseudo-class]
##
def css(*args)
  rules, handler, ns, _ = extract_params(args)
  css_internal self, rules, handler, ns
end

def css_internal(node, rules, handler, ns)

def css_internal(node, rules, handler, ns)
  xpath_internal node, css_rules_to_xpath(rules, ns), handler, ns, nil
end

def css_rules_to_xpath(rules, ns)

def css_rules_to_xpath(rules, ns)
  rules.map { |rule| xpath_query_from_css_rule(rule, ns) }
end

def extract_params(params) # :nodoc:

:nodoc:
def extract_params(params) # :nodoc:
  handler = params.find do |param|
    ![Hash, String, Symbol].include?(param.class)
  end
  params -= [handler] if handler
  hashes = []
  while Hash === params.last || params.last.nil?
    hashes << params.pop
    break if params.empty?
  end
  ns, binds = hashes.reverse
  ns ||= document.root ? document.root.namespaces : {}
  [params, handler, ns, binds]
end

def search(*args)

See Searchable#xpath and Searchable#css for further usage help.

)
}.new
end
node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
def regex node_set, regex
Class.new {
node.search('.//title[regex(., "\w+")]', 'div.employee:regex("[0-9]+")'

appear anywhere in the argument list. For example:
arguments are ones that you pass in. Note that this class may
to the method will be the current matching NodeSet. Any other
implement the function you want to define. The first argument
defined. To define custom functions create a class and
Custom XPath functions and CSS pseudo-selectors may also be

node.search('.//address[@domestic=$value]', nil, {:value => 'Yes'})

appended to the namespace bindings. For example:
For XPath queries, a hash of variable bindings may also be

node.search('bike|tire', {'bike' => 'http://schwinn.com/'})
node.search('.//bike:tire', {'bike' => 'http://schwinn.com/'})

A hash of namespace bindings may be appended:

node.search("div.employee", ".//title")

Search this object for +paths+. +paths+ must be one or more XPath or CSS queries:

call-seq: search *paths, [namespace-bindings, xpath-variable-bindings, custom-handler-class]
##
def search(*args)
  paths, handler, ns, binds = extract_params(args)
  xpaths = paths.map(&:to_s).map do |path|
    (path =~ LOOKS_LIKE_XPATH) ? path : xpath_query_from_css_rule(path, ns)
  end.flatten.uniq
  xpath(*(xpaths + [ns, handler, binds].compact))
end

def xpath(*args)


}.new)
end
node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
def regex node_set, regex
node.xpath('.//title[regex(., "\w+")]', Class.new {

argument list. For example:
you pass in. Note that this class may appear anywhere in the
current matching NodeSet. Any other arguments are ones that
to define. The first argument to the method will be the
functions create a class and implement the function you want
Custom XPath functions may also be defined. To define custom

node.xpath('.//address[@domestic=$value]', nil, {:value => 'Yes'})

A hash of variable bindings may also be appended to the namespace bindings. For example:

node.xpath('.//xmlns:name', node.root.namespaces)
node.xpath('.//foo:name', {'foo' => 'http://example.org/'})

A hash of namespace bindings may be appended. For example:

node.xpath('.//title')

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

call-seq: xpath *paths, [namespace-bindings, variable-bindings, custom-handler-class]
##
def xpath(*args)
  paths, handler, ns, binds = extract_params(args)
  xpath_internal self, paths, handler, ns, binds
end

def xpath_impl(node, path, handler, ns, binds)

def xpath_impl(node, path, handler, ns, binds)
  ctx = XPathContext.new(node)
  ctx.register_namespaces(ns)
  path = path.gsub(/xmlns:/, " :") unless Nokogiri.uses_libxml?
  binds.each do |key, value|
    ctx.register_variable key.to_s, value
  end if binds
  ctx.evaluate(path, handler)
end

def xpath_internal(node, paths, handler, ns, binds)

def xpath_internal(node, paths, handler, ns, binds)
  document = node.document
  return NodeSet.new(document) unless document
  if paths.length == 1
    return xpath_impl(node, paths.first, handler, ns, binds)
  end
  NodeSet.new(document) do |combined|
    paths.each do |path|
      xpath_impl(node, path, handler, ns, binds).each { |set| combined << set }
    end
  end
end

def xpath_query_from_css_rule(rule, ns)

def xpath_query_from_css_rule(rule, ns)
  visitor = Nokogiri::CSS::XPathVisitorOptimallyUseBuiltins.new
  self.class::IMPLIED_XPATH_CONTEXTS.map do |implied_xpath_context|
    CSS.xpath_for(rule.to_s, {:prefix => implied_xpath_context, :ns => ns,
                              :visitor => visitor})
  end.join(" | ")
end