and(one, two)
click to toggle source
def and(one, two)
"(#{one} and #{two})"
end
anywhere(element_names)
click to toggle source
def anywhere(element_names)
if element_names.length == 1
"//#{element_names.first}"
elsif element_names.length > 1
"//*[#{element_names.map { |e| "self::#{e}" }.join(" | ")}]"
else
"//*"
end
end
attribute(current, name)
click to toggle source
def attribute(current, name)
"#{current}/@#{name}"
end
axis(parent, name, tag_name)
click to toggle source
def axis(parent, name, tag_name)
"#{parent}/#{name}::#{tag_name}"
end
child(parent, element_names)
click to toggle source
def child(parent, element_names)
if element_names.length == 1
"#{parent}/#{element_names.first}"
elsif element_names.length > 1
"#{parent}/*[#{element_names.map { |e| "self::#{e}" }.join(" | ")}]"
else
"#{parent}/*"
end
end
contains(current, value)
click to toggle source
def contains(current, value)
"contains(#{current}, #{value})"
end
convert_argument(argument)
click to toggle source
def convert_argument(argument)
case argument
when Expression, Union then render(argument)
when Array then argument.map { |element| convert_argument(element) }
when String then string_literal(argument)
when Literal then argument.value
else argument.to_s
end
end
css(current, selector)
click to toggle source
def css(current, selector)
paths = Nokogiri::CSS.xpath_for(selector).map do |xpath_selector|
"#{current}#{xpath_selector}"
end
union(paths)
end
descendant(parent, element_names)
click to toggle source
def descendant(parent, element_names)
if element_names.length == 1
"#{parent}//#{element_names.first}"
elsif element_names.length > 1
"#{parent}//*[#{element_names.map { |e| "self::#{e}" }.join(" | ")}]"
else
"#{parent}//*"
end
end
equality(one, two)
click to toggle source
def equality(one, two)
"#{one} = #{two}"
end
inverse(current)
click to toggle source
def inverse(current)
"not(#{current})"
end
is(one, two)
click to toggle source
def is(one, two)
if @type == :exact
equality(one, two)
else
contains(one, two)
end
end
literal(node)
click to toggle source
def literal(node)
node
end
next_sibling(current, element_names)
click to toggle source
def next_sibling(current, element_names)
if element_names.length == 1
"#{current}/following-sibling::*[1]/self::#{element_names.first}"
elsif element_names.length > 1
"#{current}/following-sibling::*[1]/self::*[#{element_names.map { |e| "self::#{e}" }.join(" | ")}]"
else
"#{current}/following-sibling::*[1]/self::*"
end
end
node_name(current)
click to toggle source
def node_name(current)
"name(#{current})"
end
normalized_space(current)
click to toggle source
def normalized_space(current)
"normalize-space(#{current})"
end
one_of(current, values)
click to toggle source
def one_of(current, values)
values.map { |value| "#{current} = #{value}" }.join(' or ')
end
or(one, two)
click to toggle source
def or(one, two)
"(#{one} or #{two})"
end
previous_sibling(current, element_names)
click to toggle source
def previous_sibling(current, element_names)
if element_names.length == 1
"#{current}/preceding-sibling::*[1]/self::#{element_names.first}"
elsif element_names.length > 1
"#{current}/preceding-sibling::*[1]/self::*[#{element_names.map { |e| "self::#{e}" }.join(" | ")}]"
else
"#{current}/preceding-sibling::*[1]/self::*"
end
end
render(node)
click to toggle source
def render(node)
arguments = node.arguments.map { |argument| convert_argument(argument) }
send(node.expression, *arguments)
end
starts_with(current, value)
click to toggle source
def starts_with(current, value)
"starts-with(#{current}, #{value})"
end
string_function(current)
click to toggle source
def string_function(current)
"string(#{current})"
end
string_literal(string)
click to toggle source
def string_literal(string)
if string.include?("'")
string = string.split("'", -1).map do |substr|
"'#{substr}'"
end.join(%q{,"'",})
"concat(#{string})"
else
"'#{string}'"
end
end
text(current)
click to toggle source
def text(current)
"#{current}/text()"
end
this_node()
click to toggle source
union(*expressions)
click to toggle source
def union(*expressions)
expressions.join(' | ')
end
variable(name)
click to toggle source
def variable(name)
"%{#{name}}"
end
where(on, condition)
click to toggle source
def where(on, condition)
"#{on}[#{condition}]"
end