Functx module and long strings with end of chars

100 Views Asked by At

I faced a problem with functx module dealing with strings with end of line characters. The following code should work (?)

declare %unit:test function test:substring-before-last() {

  let $title := 'Something
blah other'

  let $expected-title := 'Something
blah'

  return unit:assert-equals(functx:substring-before-last($title, ' other'),
    $expected-title)
};

However it gives a failure

"Something
blah" expected, "Something
blah other" returned.

Removing line breaking makes the test working. What I don't understand? :)

BR

2

There are 2 best solutions below

1
Martin Honnen On BEST ANSWER

I think the issue is in the definition or implementation of the functx function http://www.xqueryfunctions.com/xq/functx_substring-before-last.html:

declare function functx:substring-before-last
  ( $arg as xs:string? ,
    $delim as xs:string )  as xs:string {

   if (matches($arg, functx:escape-for-regex($delim)))
   then replace($arg,
            concat('^(.*)', functx:escape-for-regex($delim),'.*'),
            '$1')
   else ''
 } ;

and the regular expression dot . matching and the replace default "If the input string contains no substring that matches the regular expression, the result of the function is a single string identical to the input string."; if you add the flags m argument

declare function functx:substring-before-last
  ( $arg as xs:string? ,
    $delim as xs:string )  as xs:string {

   if (matches($arg, functx:escape-for-regex($delim)))
   then replace($arg,
            concat('^(.*)', functx:escape-for-regex($delim),'.*'),
            '$1', 'm')
   else ''
 } ;

you get the right match and replacement and comparison.

0
Neil Bradley On

Unfortunately, this does not work either reliable. Take this example, where the word 'end is being removed from both lines, not just the last line:

example