Search code examples
xquerymarklogicmarklogic-8xquery-3.0marklogic-9

fn:replace to return one string on iteration


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

Solution

  • 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