diff options
author | Kouhei Sutou <[email protected]> | 2019-05-25 18:28:00 +0900 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2019-08-04 11:55:55 +0900 |
commit | 310a2a98601168aae8c071749b5cb572b55d5046 (patch) | |
tree | 16b3e9ba7d8ca26e389eec34f91eda549810df86 /lib/rexml/xpath_parser.rb | |
parent | 39f275edf7284ef0c0f9b9391038ae9f2c019731 (diff) |
[ruby/rexml] xpath: add missing value conversions for equality and relational expressions
GitHub: fix #18
Reported by Mirko Budszuhn. Thanks!!!
https://github.com/ruby/rexml/commit/0dca2a2ba0
Diffstat (limited to 'lib/rexml/xpath_parser.rb')
-rw-r--r-- | lib/rexml/xpath_parser.rb | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/lib/rexml/xpath_parser.rb b/lib/rexml/xpath_parser.rb index 8f107e5a2c..b989725403 100644 --- a/lib/rexml/xpath_parser.rb +++ b/lib/rexml/xpath_parser.rb @@ -864,32 +864,51 @@ module REXML # Else, convert to string # Else # Convert both to numbers and compare - set1 = unnode(set1) if set1.is_a?(Array) - set2 = unnode(set2) if set2.is_a?(Array) - s1 = Functions.string(set1) - s2 = Functions.string(set2) - if s1 == 'true' or s1 == 'false' or s2 == 'true' or s2 == 'false' - set1 = Functions::boolean( set1 ) - set2 = Functions::boolean( set2 ) + compare(set1, op, set2) + end + end + + def value_type(value) + case value + when true, false + :boolean + when Numeric + :number + when String + :string + else + raise "[BUG] Unexpected value type: <#{value.inspect}>" + end + end + + def normalize_compare_values(a, operator, b) + a_type = value_type(a) + b_type = value_type(b) + case operator + when :eq, :neq + if a_type == :boolean or b_type == :boolean + a = Functions.boolean(a) unless a_type == :boolean + b = Functions.boolean(b) unless b_type == :boolean + elsif a_type == :number or b_type == :number + a = Functions.number(a) unless a_type == :number + b = Functions.number(b) unless b_type == :number else - if op == :eq or op == :neq - if s1 =~ /^\d+(\.\d+)?$/ or s2 =~ /^\d+(\.\d+)?$/ - set1 = Functions::number( s1 ) - set2 = Functions::number( s2 ) - else - set1 = Functions::string( set1 ) - set2 = Functions::string( set2 ) - end - else - set1 = Functions::number( set1 ) - set2 = Functions::number( set2 ) - end + a = Functions.string(a) unless a_type == :string + b = Functions.string(b) unless b_type == :string end - compare( set1, op, set2 ) + when :lt, :lteq, :gt, :gteq + a = Functions.number(a) unless a_type == :number + b = Functions.number(b) unless b_type == :number + else + message = "[BUG] Unexpected compare operator: " + + "<#{operator.inspect}>: <#{a.inspect}>: <#{b.inspect}>" + raise message end + [a, b] end def compare(a, operator, b) + a, b = normalize_compare_values(a, operator, b) case operator when :eq a == b |