3

I am looking to implement a find and replace for a string from a document by using the key and value pair of a map. The code I currently have seems to be returning 2 strings because of 2 map values. I am looking to return one string with values in curly braces be replaced by the value in the map.

let $text:='On ${date} the value of alert is ${alerts}'
    let $params:= map:map()
    let $noop:=map:put($params,'date','TESTINGDATE')
    let $noop:=map:put($params,'alerts','TESTALERT')


    let $formatted-message:=for $keys in map:keys($params)
                            let $message:=fn:replace($text,fn:concat('\$\{',$keys,'\}'),map:get($params,$keys))
                            return $message

    return $formatted-message
SteeleDev
  • 169
  • 1
  • 3
  • 12

1 Answers1

4

You could use a recursive function:

declare function local:replace-all($text, $key, $rest, $params) 
{
  if (fn:empty($key)) then
    $text
  else
    local:replace-all(fn:replace($text, fn:concat('\$\{',$key,'\}'), map:get($params,$key)), 
                      fn:head($rest), 
                      fn:tail($rest), 
                      $params)

};

let $text:='On ${date} the value of alert is ${alerts}'
let $params:= map:map()
let $noop:=map:put($params,'date','TESTINGDATE')
let $noop:=map:put($params,'alerts','TESTALERT')
let $keys := map:keys($params)
return
  local:replace-all($text, fn:head($keys), fn:tail($keys), $params)

Or you could use fn:fold-left():

let $text:='On ${date} the value of alert is ${alerts}'
let $params:= map:map()
let $noop:=map:put($params,'date','TESTINGDATE')
let $noop:=map:put($params,'alerts','TESTALERT')
let $keys := map:keys($params)
return
  fn:fold-left(
    function($text, $keys) {
      let $key := fn:head($keys)
      return 
        fn:replace($text, fn:concat('\$\{',$key,'\}'), map:get($params,$key))
    },
    $text,
    $keys
  )

Both produce:

On TESTINGDATE the value of alert is TESTALERT
Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
  • When recursing, it's a good idea to put the recurse call last (and to omit the return type in the signature) to take advantage of tail recursion optimization. An alternative would be to fold with the input string as the initial value over the keys of the map with a function that has a closure on the map: http://docs.marklogic.com/fn:fold-left – ehennum Mar 21 '18 at 22:30