Edited: Per clarification from the original poster, the first string delimited by the underscores should not have its starting letter capitalized.
This solution does not use recursion and should be quite more efficient.
Here is the new solution:
string-join(
(for $i in 1 to count(tokenize(.,'_')),
$s in tokenize(.,'_')[$i],
$fl in substring($s,1,1),
$tail in substring($s,2)
return
if($i eq 1)
then $s
else concat(upper-case($fl), $tail)
),
''
)
The result is now exactly as required:
underLinedString
Below is the old solution.
The replace() function supposes that you have a fixed replacement -- therefore it is not the best tool for solving this problem.
Here is a one-liner XPath 2.0 solution (and it certainly can be used as part of an XSLT 2.0 transformation :) ):
string-join(
(for $s in tokenize(.,'_'),
$fl in substring($s,1,1),
$tail in substring($s,2)
return
concat(upper-case($fl), $tail)
),
''
)
When we use the above expression in an XSLT 2.0 transformation like this:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="/">
<xsl:sequence select=
"string-join(
(for $s in tokenize(.,'_'),
$fl in substring($s,1,1),
$tail in substring($s,2)
return
concat(upper-case($fl), $tail)
),
''
)
"/>
</xsl:template>
</xsl:stylesheet>
and apply it on this XML document:
<t>under_lined_String</t>
the wanted result is produced:
UnderLinedString