Hi aakikce, try like this,
use strict;
use warnings;
my $content = do{local $/; <DATA>};
$content =~ s/(<surname>(?:(?:(?!<\/surname>).)*)<\/surname>\,?\s*<giv
+enname>(?:(?:(?!<\/givenname>).)*)<\/givenname>)/<au>$1<\/au>/gsi;
$content =~ s/(<\/givenname>\,\s*)<au>(\s*<surname>)/$1$2/gis;
$content =~ s/(<\/givenname>\s*)<\/au>(\,\s*<surname>)/$1$2/gis;
$content =~ s/(<givenname>(?:(?:(?!<\/givenname>).)*)<\/givenname>\,?\
+s*<surname>(?:(?:(?!<\/surname>).)*)<\/surname>)/<au>$1<\/au>/gsi;
print $content;
__DATA__
<surname>Coff</surname>, <givenname>D.,</givenname> et al., <givenname
+>J.</givenname> <surname>Amat</surname> <surname>Coffman</surname>, <
+givenname>D.D.,</givenname>
<givenname>D.,</givenname>, <surname>Coff</surname> et al., <givenname
+>J.</givenname> <surname>Amat</surname> <surname>Coffman</surname>, <
+givenname>D.D.,</givenname>
output:
-------
<au><surname>Coff</surname>, <givenname>D.,</givenname></au>, <au><sur
+name>Coff</surname>, <givenname>D.,</givenname></au>
<au><givenname>D.,</givenname>, <surname>Coff</surname></au>, <au><giv
+enname>D.,</givenname>, <surname>Coff</surname></au>
In your expected output, second line is same as input. I think it's typo.
Updated: aakikce, now you can try with your sample.
Regards,
Velusamy R.
eval"print uc\"\\c$_\""for split'','j)@,/6%@0%2,`e@3!-9v2)/@|6%,53!-9@2~j';