lib/xpath/renderer.rb in xpath-3.1.0 vs lib/xpath/renderer.rb in xpath-3.2.0
- old
+ new
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
module XPath
class Renderer
def self.render(node, type)
new(type).render(node)
end
@@ -13,23 +15,23 @@
send(node.expression, *arguments)
end
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
+ 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
def string_literal(string)
if string.include?("'")
string = string.split("'", -1).map do |substr|
"'#{substr}'"
- end.join(%q{,"'",})
+ end.join(%q(,"'",))
"concat(#{string})"
else
"'#{string}'"
end
end
@@ -49,28 +51,32 @@
def axis(current, name, element_names)
with_element_conditions("#{current}/#{name}::", element_names)
end
def anywhere(element_names)
- with_element_conditions("//", element_names)
+ with_element_conditions('//', element_names)
end
def where(on, condition)
"#{on}[#{condition}]"
end
def attribute(current, name)
- "#{current}/@#{name}"
+ if valid_xml_name?(name)
+ "#{current}/@#{name}"
+ else
+ "#{current}/attribute::*[local-name(.) = #{string_literal(name)}]"
+ end
end
def binary_operator(name, left, right)
"(#{left} #{name} #{right})"
end
def is(one, two)
if @type == :exact
- binary_operator("=", one, two)
+ binary_operator('=', one, two)
else
function(:contains, one, two)
end
end
@@ -96,21 +102,25 @@
def union(*expressions)
expressions.join(' | ')
end
def function(name, *arguments)
- "#{name}(#{arguments.join(", ")})"
+ "#{name}(#{arguments.join(', ')})"
end
private
def with_element_conditions(expression, element_names)
if element_names.length == 1
"#{expression}#{element_names.first}"
elsif element_names.length > 1
- "#{expression}*[#{element_names.map { |e| "self::#{e}" }.join(" | ")}]"
+ "#{expression}*[#{element_names.map { |e| "self::#{e}" }.join(' | ')}]"
else
"#{expression}*"
end
+ end
+
+ def valid_xml_name?(name)
+ name =~ /^[a-zA-Z_:][a-zA-Z0-9_:\.\-]*$/
end
end
end