class Ayril::Selector

Constants

Assertions
Operators
Patterns
XPath

Attributes

expr[R]
xpath[R]

Public Class Methods

find_child_elements(element, expressions) click to toggle source
# File lib/ayril/selector.rb, line 243
def self.find_child_elements(element, expressions)
  Selector::split(expressions.join(',')).map do |expression|
    Selector.new(expression.strip).find_elements(element)
  end.uniq.flatten
end
find_element(elements, *rest) click to toggle source
# File lib/ayril/selector.rb, line 237
def self.find_element(elements, *rest)
  expression, index = rest[0], rest[1]
  (expression = nil; index = expression) if expression.kind_of? Integer
  Selector::match_elements(elements, expression || '*')[index || 0]
end
match_elements(elements, expression) click to toggle source
# File lib/ayril/selector.rb, line 233
def self.match_elements(elements, expression)
  elements & elements[0].rootDocument.select(expression)
end
new(expr) click to toggle source
# File lib/ayril/selector.rb, line 6
def initialize(expr)
  @expr = expr.strip
  self.compile_xpath_matcher
end
split(expression) click to toggle source
# File lib/ayril/selector.rb, line 225
def self.split(expression)
  expressions = []
  expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/) do |m|
    expressions << m[1].strip
  end
  expressions
end

Public Instance Methods

compile_xpath_matcher() click to toggle source
# File lib/ayril/selector.rb, line 11
def compile_xpath_matcher
  e = @expr.dup; le = nil
  return (@xpath = @@cache[e]) if @@cache.include? e

  @matcher = [".//*"]
  while (e != '') and (le != e) and (e =~ /\S/)
    le = e.dup
    Selector::Patterns.each do |pattern|
      n = Selector::XPath[pattern[:name]]
      if m = e.match(pattern[:re])
        m = m.to_a unless m.nil?
        @matcher << (n.kind_of?(Proc) ? n.call(m) : n.interpolate(m))
        e.sub! m[0], ''
        break
      end
    end
  end

  @xpath = @matcher.join
  @@cache[@expr] = @xpath.gsub! %r{\*?\[name\(\)='([a-zA-Z]+)'\]}, '\1'
end
find_elements(root) click to toggle source
# File lib/ayril/selector.rb, line 33
def find_elements(root)
  root.select_by_xpath @xpath
end
inspect() click to toggle source
# File lib/ayril/selector.rb, line 71
def inspect
  "#<Selector:#{@expr.inspect}>"
end
match?(element) click to toggle source
# File lib/ayril/selector.rb, line 37
def match?(element)
  @tokens = []

  e = @expr.dup; le = nil
  while (e != '') and (le != e) and (e =~ /\S/)
    le = e.dup
    Selector::Patterns.each do |pattern|
      if m = e.patch(pattern[:re])
        m = m.to_a unless m.nil?
        if Selector::Assertions.include? name
          @tokens << [pattern[:name], m.clone]
          e.sub! m[0], ''
        else # resort to whole document
          return self.find_elements(element.rootDocument).include? element
        end
      end
    end
  end

  match = true
  @tokens.each do |token|
    name, matches = token[0..1]
    if not Selector::Assertions[name].call self, matches
      match = false
      break
    end
  end
  match
end
to_s() click to toggle source
# File lib/ayril/selector.rb, line 67
def to_s
  @expr
end