Skip to content

Instantly share code, notes, and snippets.

@ramhoj
Created September 2, 2010 15:26
Show Gist options
  • Select an option

  • Save ramhoj/562431 to your computer and use it in GitHub Desktop.

Select an option

Save ramhoj/562431 to your computer and use it in GitHub Desktop.
module XPath
extend self
def self.generate
yield(Expression::Self.new)
end
class Expression
include XPath
def current
self
end
...
end
class Self < Expression
def to_xpath(predicate=nil)
'.'
end
end
class Descendant < Expression
def initialize(left, right)
@left = wrap_xpath(left)
@right = wrap_xpath(right)
end
def to_xpath(predicate=nil)
"#{@left.to_xpath(predicate)}//#{@right.first.to_xpath(predicate)}"
end
end
def current
Expression::Self.new
end
def descendant(*expressions)
Expression::Descendant.new(current, expressions)
end
end
XPath.descendant('foo') # => .//foo
XPath.descendant('foo').descendant('bar') # => .//foo//bar
XPath.descendant('foo').descendant('bar')[XPath.descendant('baz').attr('id') == 'bar'] # => .//foo//bar[.//baz/@id = 'bar']
XPath.generate { |x| x.descendant('foo').descendant('bar')[x.descendant('baz').attr('id') == 'bar']
module MyModule
include XPath
def link(locator)
descendant(:a)[text == locator]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment