Class: XPath::Renderer

Inherits:
Object
  • Object
show all
Defined in:
lib/xpath/renderer.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type) ⇒ Renderer

Returns a new instance of Renderer.



7
8
9
# File 'lib/xpath/renderer.rb', line 7

def initialize(type)
  @type = type
end

Class Method Details

.render(node, type) ⇒ Object



3
4
5
# File 'lib/xpath/renderer.rb', line 3

def self.render(node, type)
  new(type).render(node)
end

Instance Method Details

#and(one, two) ⇒ Object



134
135
136
# File 'lib/xpath/renderer.rb', line 134

def and(one, two)
  "(#{one} and #{two})"
end

#anywhere(element_names) ⇒ Object



116
117
118
119
120
121
122
123
124
# File 'lib/xpath/renderer.rb', line 116

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) ⇒ Object



73
74
75
# File 'lib/xpath/renderer.rb', line 73

def attribute(current, name)
  "#{current}/@#{name}"
end

#axis(parent, name, tag_name) ⇒ Object



61
62
63
# File 'lib/xpath/renderer.rb', line 61

def axis(parent, name, tag_name)
  "#{parent}/#{name}::#{tag_name}"
end

#child(parent, element_names) ⇒ Object



51
52
53
54
55
56
57
58
59
# File 'lib/xpath/renderer.rb', line 51

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) ⇒ Object



126
127
128
# File 'lib/xpath/renderer.rb', line 126

def contains(current, value)
  "contains(#{current}, #{value})"
end

#convert_argument(argument) ⇒ Object



16
17
18
19
20
21
22
23
24
# File 'lib/xpath/renderer.rb', line 16

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) ⇒ Object



105
106
107
108
109
110
# File 'lib/xpath/renderer.rb', line 105

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) ⇒ Object



41
42
43
44
45
46
47
48
49
# File 'lib/xpath/renderer.rb', line 41

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) ⇒ Object



77
78
79
# File 'lib/xpath/renderer.rb', line 77

def equality(one, two)
  "#{one} = #{two}"
end

#inverse(current) ⇒ Object



166
167
168
# File 'lib/xpath/renderer.rb', line 166

def inverse(current)
  "not(#{current})"
end

#is(one, two) ⇒ Object



81
82
83
84
85
86
87
# File 'lib/xpath/renderer.rb', line 81

def is(one, two)
  if @type == :exact
    equality(one, two)
  else
    contains(one, two)
  end
end

#literal(node) ⇒ Object



101
102
103
# File 'lib/xpath/renderer.rb', line 101

def literal(node)
  node
end

#next_sibling(current, element_names) ⇒ Object



146
147
148
149
150
151
152
153
154
# File 'lib/xpath/renderer.rb', line 146

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) ⇒ Object



65
66
67
# File 'lib/xpath/renderer.rb', line 65

def node_name(current)
  "name(#{current})"
end

#normalized_space(current) ⇒ Object



97
98
99
# File 'lib/xpath/renderer.rb', line 97

def normalized_space(current)
  "normalize-space(#{current})"
end

#one_of(current, values) ⇒ Object



142
143
144
# File 'lib/xpath/renderer.rb', line 142

def one_of(current, values)
  values.map { |value| "#{current} = #{value}" }.join(' or ')
end

#or(one, two) ⇒ Object



138
139
140
# File 'lib/xpath/renderer.rb', line 138

def or(one, two)
  "(#{one} or #{two})"
end

#previous_sibling(current, element_names) ⇒ Object



156
157
158
159
160
161
162
163
164
# File 'lib/xpath/renderer.rb', line 156

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) ⇒ Object



11
12
13
14
# File 'lib/xpath/renderer.rb', line 11

def render(node)
  arguments = node.arguments.map { |argument| convert_argument(argument) }
  send(node.expression, *arguments)
end

#starts_with(current, value) ⇒ Object



130
131
132
# File 'lib/xpath/renderer.rb', line 130

def starts_with(current, value)
  "starts-with(#{current}, #{value})"
end

#string_function(current) ⇒ Object



170
171
172
# File 'lib/xpath/renderer.rb', line 170

def string_function(current)
  "string(#{current})"
end

#string_literal(string) ⇒ Object



26
27
28
29
30
31
32
33
34
35
# File 'lib/xpath/renderer.rb', line 26

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) ⇒ Object



93
94
95
# File 'lib/xpath/renderer.rb', line 93

def text(current)
  "#{current}/text()"
end

#this_nodeObject



37
38
39
# File 'lib/xpath/renderer.rb', line 37

def this_node
  '.'
end

#union(*expressions) ⇒ Object



112
113
114
# File 'lib/xpath/renderer.rb', line 112

def union(*expressions)
  expressions.join(' | ')
end

#variable(name) ⇒ Object



89
90
91
# File 'lib/xpath/renderer.rb', line 89

def variable(name)
  "%{#{name}}"
end

#where(on, condition) ⇒ Object



69
70
71
# File 'lib/xpath/renderer.rb', line 69

def where(on, condition)
  "#{on}[#{condition}]"
end