From 8295fa578377f4491dbec486d18cd13b944216ed Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 26 Aug 2014 18:14:44 +0200 Subject: [PATCH] Support for the XPath translate() function. --- lib/oga/xpath/evaluator.rb | 29 ++++++++++++++++ .../xpath/evaluator/calls/translate_spec.rb | 34 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 spec/oga/xpath/evaluator/calls/translate_spec.rb diff --git a/lib/oga/xpath/evaluator.rb b/lib/oga/xpath/evaluator.rb index 1ca2d28..4231341 100644 --- a/lib/oga/xpath/evaluator.rb +++ b/lib/oga/xpath/evaluator.rb @@ -1002,6 +1002,35 @@ module Oga return str.strip.gsub(/\s+/, ' ') end + ## + # Processes the `translate()` function call. + # + # This function takes the string of the 1st argument and replaces all + # characters of the 2nd argument with those specified in the 3rd argument. + # + # @example + # translate("bar", "abc", "ABC") # => "BAr" + # + # @param [Oga::XML::NodeSet] context + # @param [Oga::XPath::Node] input + # @param [Oga::XPath::Node] find + # @param [Oga::XPath::Node] replace + # @return [String] + # + def on_call_translate(context, input, find, replace) + input_str = on_call_string(context, input) + find_chars = on_call_string(context, find).chars + replace_chars = on_call_string(context, replace).chars + replaced = input_str + + find_chars.each_with_index do |char, index| + replace_with = replace_chars[index] ? replace_chars[index] : '' + replaced = replaced.gsub(char, replace_with) + end + + return replaced + end + ## # Processes an `(int)` node. # diff --git a/spec/oga/xpath/evaluator/calls/translate_spec.rb b/spec/oga/xpath/evaluator/calls/translate_spec.rb new file mode 100644 index 0000000..bdc1491 --- /dev/null +++ b/spec/oga/xpath/evaluator/calls/translate_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe Oga::XPath::Evaluator do + context 'translate() function' do + before do + @document = parse('barabcABC') + @evaluator = described_class.new(@document) + end + + example 'translate a string using all string literals' do + @evaluator.evaluate('translate("bar", "abc", "ABC")').should == 'BAr' + end + + example "remove characters that don't occur in the replacement string" do + @evaluator.evaluate('translate("-aaa-", "abc-", "ABC")').should == 'AAA' + end + + example 'use the first character occurence in the search string' do + @evaluator.evaluate('translate("ab", "aba", "123")').should == '12' + end + + example 'ignore excess characters in the replacement string' do + @evaluator.evaluate('translate("abc", "abc", "123456")').should == '123' + end + + example 'translate a node set string using string literals' do + @evaluator.evaluate('translate(root/a, "abc", "ABC")').should == 'BAr' + end + + example 'translate a node set string using other node set strings' do + @evaluator.evaluate('translate(root/a, root/b, root/c)').should == 'BAr' + end + end +end